View Javadoc

1   /*
2    * Copyright 2011 The Ohio State University
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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   * A principal connector that attempts to look up a name identifier within a store.
34   */
35  public class CryptoTransientPrincipalConnector extends BasePrincipalConnector {
36  
37      /** Class logger. */
38      private static Logger log = LoggerFactory.getLogger(CryptoTransientPrincipalConnector.class);
39  
40      /** Object used to protect and encrypt the data. */
41      private DataSealer dataSealer;
42      
43      /**
44       * Constructor.
45       * 
46       * @param sealer object used to protect and encrypt the data
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      /** {@inheritDoc} */
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          // Split the identifier.
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     /** {@inheritDoc} */
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 }