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