1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package edu.internet2.middleware.shibboleth.common.attribute.resolver.provider.principalConnector;
19
20 import org.opensaml.common.SAMLObject;
21 import org.opensaml.saml1.core.NameIdentifier;
22 import org.opensaml.saml2.core.NameID;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 import edu.internet2.middleware.shibboleth.common.attribute.resolver.AttributeResolutionException;
27 import edu.internet2.middleware.shibboleth.common.attribute.resolver.provider.ShibbolethResolutionContext;
28 import edu.internet2.middleware.shibboleth.common.profile.provider.SAMLProfileRequestContext;
29 import edu.internet2.middleware.shibboleth.common.util.DataExpiredException;
30 import edu.internet2.middleware.shibboleth.common.util.DataSealer;
31 import edu.internet2.middleware.shibboleth.common.util.DataSealerException;
32
33
34
35
36 public class CryptoTransientPrincipalConnector extends BasePrincipalConnector {
37
38
39 private static Logger log = LoggerFactory.getLogger(CryptoTransientPrincipalConnector.class);
40
41
42 private DataSealer dataSealer;
43
44
45
46
47
48
49 public CryptoTransientPrincipalConnector(DataSealer sealer) {
50 if (sealer == null) {
51 throw new IllegalArgumentException("DataSealer may not be null.");
52 }
53 dataSealer = sealer;
54 }
55
56
57 public String resolve(ShibbolethResolutionContext resolutionContext) throws AttributeResolutionException {
58 SAMLProfileRequestContext<?, ?, ?, ?> requestContext = resolutionContext.getAttributeRequestContext();
59
60 String transientId = null;
61 String nameQualifier = null;
62 String spNameQualifier = null;
63 SAMLObject subjectId = requestContext.getSubjectNameIdentifier();
64 if (subjectId instanceof NameIdentifier) {
65 NameIdentifier nameId = (NameIdentifier) requestContext.getSubjectNameIdentifier();
66 if (nameId != null) {
67 transientId = nameId.getNameIdentifier();
68 nameQualifier = nameId.getNameQualifier();
69 }
70 } else if (requestContext.getSubjectNameIdentifier() instanceof NameID) {
71 NameID nameId = (NameID) requestContext.getSubjectNameIdentifier();
72 if (nameId != null) {
73 transientId = nameId.getValue();
74 nameQualifier = nameId.getNameQualifier();
75 spNameQualifier = nameId.getSPNameQualifier();
76 }
77 } else {
78 throw new AttributeResolutionException("Subject name identifier is not of a supported type");
79 }
80
81 if (transientId == null) {
82 throw new AttributeResolutionException("Invalid subject name identifier");
83 }
84
85 String decodedId;
86 try {
87 decodedId = dataSealer.unwrap(transientId);
88 } catch (DataExpiredException e) {
89 throw new AttributeResolutionException("Principal identifier has expired.");
90 } catch (DataSealerException e) {
91 throw new AttributeResolutionException("Caught exception unwrapping principal identifier.", e);
92 }
93
94 if (decodedId == null) {
95 throw new AttributeResolutionException("Unable to recover principal from transient identifier: "
96 + transientId);
97 }
98
99
100 String[] parts = decodedId.split("!");
101 if (parts.length != 3) {
102 throw new AttributeResolutionException("Decoded principal information was invalid: "
103 + decodedId);
104 }
105
106 if (nameQualifier != null && !nameQualifier.equals(parts[0])) {
107 throw new AttributeResolutionException("Decoded NameQualifier (" + nameQualifier +
108 ") does not match supplied value (" + parts[0] + ").");
109 } else if (spNameQualifier != null && !spNameQualifier.equals(parts[1])) {
110 throw new AttributeResolutionException("Decoded SPNameQualifier (" + spNameQualifier +
111 ") does not match supplied value (" + parts[1] + ").");
112 } else if (!parts[0].equals(requestContext.getOutboundMessageIssuer())) {
113 throw new AttributeResolutionException("Decoded NameQualifier (" + parts[0] +
114 ") does not match issuer (" + requestContext.getOutboundMessageIssuer() + ").");
115 } else if (!parts[1].equals(requestContext.getInboundMessageIssuer())) {
116 throw new AttributeResolutionException("Decoded SPNameQualifier (" + parts[0] +
117 ") does not match requester (" + requestContext.getInboundMessageIssuer() + ").");
118 }
119
120 return parts[2];
121 }
122
123
124 public void validate() throws AttributeResolutionException {
125 if (dataSealer == null) {
126 log.error("CryptoTransientPrincipalConnector (" + getId()
127 + ") must have a DataSealer object set.");
128 throw new AttributeResolutionException("CryptoTransientPrincipalConnector (" + getId()
129 + ") must have a DataSealer object set.");
130 }
131 }
132 }