View Javadoc

1   /*
2    * The MIT License
3    *
4    * Original work sponsored and donated by National Board of e-Health (NSI), Denmark (http://www.nsi.dk)
5    *
6    * Copyright (C) 2011 National Board of e-Health (NSI), Denmark (http://www.nsi.dk)
7    *
8    * Permission is hereby granted, free of charge, to any person obtaining a copy of
9    * this software and associated documentation files (the "Software"), to deal in
10   * the Software without restriction, including without limitation the rights to
11   * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12   * of the Software, and to permit persons to whom the Software is furnished to do
13   * so, subject to the following conditions:
14   *
15   * The above copyright notice and this permission notice shall be included in all
16   * copies or substantial portions of the Software.
17   *
18   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24   * SOFTWARE.
25   *
26   * $HeadURL: https://svn.softwareborsen.dk/sosi/trunk/modules/seal/src/main/java/dk/sosi/seal/modelbuilders/IDCardModelBuilder.java $
27   * $Id: IDCardModelBuilder.java 8697 2011-09-02 10:33:55Z chg@lakeside.dk $
28   */
29  package dk.sosi.seal.modelbuilders;
30  
31  import dk.sosi.seal.model.*;
32  import dk.sosi.seal.model.constants.*;
33  import dk.sosi.seal.xml.XmlUtil;
34  import org.apache.xml.security.utils.IdResolver;
35  import org.w3c.dom.*;
36  
37  import java.text.ParseException;
38  import java.util.Date;
39  
40  /**
41   * Builds ID-card model objects from a DOM document.
42   *
43   * @author Jan Riis
44   * @author $LastChangedBy: chg@lakeside.dk $
45   * @since 1.0
46   */
47  public class IDCardModelBuilder { // NOPMD
48  
49  	/**
50  	 * Builds an ID-card objects from a DOM document.
51  	 *
52  	 * @param doc
53  	 *            The DOM document used for the ID-card.
54  	 */
55  	public IDCard buildModel(Document doc) throws ModelBuildException {
56  
57  		Element idCardElement = null;
58  		IDCard result = null;
59  
60  		NodeList assertions = doc.getElementsByTagNameNS(NameSpaces.SAML2ASSERTION_SCHEMA, SAMLTags.ASSERTION);
61  		for (int i = 0; i < assertions.getLength(); i++) {
62  			Element elem = (Element) assertions.item(i);
63  			XmlUtil.registerElementByIdExtended(elem);
64  			idCardElement = IdResolver.getElementById(doc, IDValues.IDCARD);
65  		}
66  		if (idCardElement != null) {
67              result = internalBuild(idCardElement);
68  		}
69  		return result;
70  	}
71  
72      /**
73       * Builds an ID-card object from a DOM element.
74       *
75       * @param assertion
76       *            The DOM element for the ID-card
77       */
78      public IDCard buildModel(Element assertion) {
79          return internalBuild(assertion);
80      }
81  
82  
83      private IDCard internalBuild(Element idCardElement) {
84          IDCard result;
85          String itSystemName = null, ocesCertHash = null, id = null, version = null,
86          cpr = null, givenName = null, surName = null, email = null, occupation = null, userRole = null,
87          authorizationCode = null, careProviderID = null, careProviderIDType = null,
88          careProviderName = null, authLevel = null;
89          boolean hasIDCardData = false, hasSystemLog=false, hasUserLog=false;
90  
91          String alternativeIdentifier = null;
92          String username = null;
93          String password = null;
94  
95          Date createdDate, expiryDate;
96  
97          // Check validity interval
98          Node timeContraints = idCardElement.getElementsByTagNameNS(NameSpaces.SAML2ASSERTION_SCHEMA, SAMLTags.CONDITIONS).item(0);
99          NamedNodeMap conditionsAttributes = timeContraints.getAttributes();
100         try {
101             expiryDate = XmlUtil.fromXMLTimeStamp(conditionsAttributes.getNamedItem(SAMLAttributes.NOT_ON_OR_AFTER).getNodeValue());
102             createdDate = XmlUtil.fromXMLTimeStamp(conditionsAttributes.getNamedItem(SAMLAttributes.NOT_BEFORE).getNodeValue());
103         } catch (DOMException e) {
104             throw new ModelBuildException("SAML:Conditions could not be found", e);
105         } catch (ParseException e) {
106             throw new ModelBuildException("SAML:Conditions could not be parsed", e);
107         }
108 
109         //Check for an alternative Identifier
110         Node subjectNameIdNode = idCardElement.getElementsByTagNameNS(NameSpaces.SAML2ASSERTION_SCHEMA, SAMLTags.NAMEID).item(0);
111         NamedNodeMap nameIdAttributes = subjectNameIdNode.getAttributes();
112         Node nameIdFormatNode = nameIdAttributes.getNamedItem(SAMLAttributes.FORMAT);
113         if (nameIdFormatNode.getFirstChild().getNodeValue().equals(SubjectIdentifierTypeValues.OTHER)) {
114             alternativeIdentifier = subjectNameIdNode.getFirstChild().getNodeValue();
115         }
116 
117         //AuthenticationLevel 2
118         Element usernameTokenElement = (Element) idCardElement.getElementsByTagNameNS(NameSpaces.WSSE_SCHEMA, WSSETags.USERNAME_TOKEN).item(0);
119         if (usernameTokenElement != null) {
120             Node usernameNode = usernameTokenElement.getElementsByTagNameNS(NameSpaces.WSSE_SCHEMA, WSSETags.USERNAME).item(0);
121             username = XmlUtil.getTextNodeValue(usernameNode);
122             Node passwordNode = usernameTokenElement.getElementsByTagNameNS(NameSpaces.WSSE_SCHEMA, WSSETags.PASSWORD).item(0);
123             password = XmlUtil.getTextNodeValue(passwordNode);
124 
125         }
126 
127         // IDCard attributes
128         Node issuerNode = idCardElement.getElementsByTagNameNS(NameSpaces.SAML2ASSERTION_SCHEMA, SAMLTags.ISSUER).item(0);
129         String issuer = issuerNode.getFirstChild().getNodeValue();
130 
131         NodeList attributeStatementNodeList = idCardElement.getElementsByTagNameNS(NameSpaces.SAML2ASSERTION_SCHEMA, SAMLTags.ATTRIBUTE_STATEMENT);
132 
133         Boolean isUserIDCard = null;
134         for (int nodeCount = 0; nodeCount < attributeStatementNodeList.getLength(); nodeCount++) {
135             NamedNodeMap map = attributeStatementNodeList.item(nodeCount).getAttributes();
136 
137             for (int attributeCount = 0; attributeCount < map.getLength(); attributeCount++) {
138 
139                 String attributeValue = map.item(attributeCount).getNodeValue();
140 
141                 if (IDValues.SYSTEM_LOG.equals(attributeValue)) {
142                     // Iterate saml:Attributes in SystemLog
143                     NodeList samlAttributeNodes = ((Element) attributeStatementNodeList.item(nodeCount)).getElementsByTagNameNS(NameSpaces.SAML2ASSERTION_SCHEMA, SAMLTags.ATTRIBUTE);
144 
145                     for (int samlAttributeCount = 0; samlAttributeCount < samlAttributeNodes.getLength(); samlAttributeCount++) {
146                         Element samlAttribute = (Element) samlAttributeNodes.item(samlAttributeCount);
147                         String attributeName = samlAttribute.getAttributes().getNamedItem(SAMLAttributes.NAME).getNodeValue();
148                         Element elmAttributeValue =  (Element) samlAttribute.getElementsByTagNameNS(NameSpaces.SAML2ASSERTION_SCHEMA, SAMLTags.ATTRIBUTE_VALUE).item(0);
149                         String attributeNameValue = XmlUtil.getTextNodeValue(elmAttributeValue);
150                         if (MedcomAttributes.IT_SYSTEM_NAME.equals(attributeName)) {
151                             itSystemName = attributeNameValue;
152                         } else if (MedcomAttributes.CARE_PROVIDER_ID.equals(attributeName)) {
153                             careProviderID = attributeNameValue;
154                             careProviderIDType = samlAttribute.getAttributes().getNamedItem(SAMLAttributes.NAME_FORMAT).getNodeValue();
155                         } else if (MedcomAttributes.CARE_PROVIDER_NAME.equals(attributeName)) {
156                             careProviderName = attributeNameValue;
157                         }
158                     }
159                     hasSystemLog = true;
160                 } else if (IDValues.IDCARD_DATA.equals(attributeValue)) {
161                     // Iterate saml:Attributes in IDCard
162                     NodeList samlAttributeNodes = ((Element) attributeStatementNodeList.item(nodeCount)).getElementsByTagNameNS(NameSpaces.SAML2ASSERTION_SCHEMA, SAMLTags.ATTRIBUTE);
163 
164                     for (int samlAttributeCount = 0; samlAttributeCount < samlAttributeNodes.getLength(); samlAttributeCount++) {
165                         Element samlAttribute = (Element) samlAttributeNodes.item(samlAttributeCount);
166                         String attributeName = samlAttribute.getAttributes().getNamedItem(SAMLAttributes.NAME).getNodeValue();
167                         Element elmAttributeValue =  (Element) samlAttribute.getElementsByTagNameNS(NameSpaces.SAML2ASSERTION_SCHEMA, SAMLTags.ATTRIBUTE_VALUE).item(0);
168                         String attributeNameValue = XmlUtil.getTextNodeValue(elmAttributeValue);
169                         // Cert Hash
170                         if (SOSIAttributes.OCES_CERT_HASH.equals(attributeName)) {
171                             ocesCertHash = attributeNameValue;
172                             // CardID
173                         } else if (SOSIAttributes.IDCARD_ID.equals(attributeName)) {
174                             id = attributeNameValue;
175                             // CardVersion
176                         } else if (SOSIAttributes.IDCARD_VERSION.equals(attributeName)) {
177                             version = attributeNameValue;
178                             // IDCardType
179                         } else if (SOSIAttributes.IDCARD_TYPE.equals(attributeName)) {
180                             if (IDCard.IDCARDTYPE_USER.equals(attributeNameValue))
181                                 isUserIDCard = Boolean.TRUE;
182                             else if (IDCard.IDCARDTYPE_SYSTEM.equals(attributeNameValue))
183                                 isUserIDCard = Boolean.FALSE;
184                         } else if (SOSIAttributes.AUTHENTICATION_LEVEL.equals(attributeName)) {
185                             authLevel = attributeNameValue;
186                         }
187                     }
188                     hasIDCardData = true;
189                 } else if (IDValues.USER_LOG.equals(attributeValue)) {
190                     // Iterate saml:Attributes in UserLog
191                     NodeList samlAttributeNodes = ((Element) attributeStatementNodeList.item(nodeCount)).getElementsByTagNameNS(NameSpaces.SAML2ASSERTION_SCHEMA, SAMLTags.ATTRIBUTE);
192 
193                     for (int samlAttributeCount = 0; samlAttributeCount < samlAttributeNodes.getLength(); samlAttributeCount++) {
194                         Element samlAttribute = (Element) samlAttributeNodes.item(samlAttributeCount);
195                         String attributeName = samlAttribute.getAttributes().getNamedItem(SAMLAttributes.NAME).getNodeValue();
196                         Element elmAttributeValue =  (Element) samlAttribute.getElementsByTagNameNS(NameSpaces.SAML2ASSERTION_SCHEMA, SAMLTags.ATTRIBUTE_VALUE).item(0);
197                         String attributeNameValue = XmlUtil.getTextNodeValue(elmAttributeValue);
198 
199                         if (MedcomAttributes.USER_CIVIL_REGISTRATION_NUMBER.equals(attributeName)) {
200                             cpr = attributeNameValue;
201                         } else if (MedcomAttributes.USER_GIVEN_NAME.equals(attributeName)) {
202                             givenName = attributeNameValue;
203                         } else if (MedcomAttributes.USER_SURNAME.equals(attributeName)) {
204                             surName = attributeNameValue;
205                         } else if (MedcomAttributes.USER_EMAIL_ADDRESS.equals(attributeName)) {
206                             email = attributeNameValue;
207                         } else if (MedcomAttributes.USER_OCCUPATION.equals(attributeName)) {
208                             occupation = attributeNameValue;
209                         } else if (MedcomAttributes.USER_ROLE.equals(attributeName)) {
210                             userRole = attributeNameValue;
211                         } else if (MedcomAttributes.USER_AUTHORIZATION_CODE.equals(attributeName)) {
212                             authorizationCode = attributeNameValue;
213                         }
214                     }
215                     hasUserLog = true;
216                 }
217             }
218         }
219 
220         CareProvider careProvider = new CareProvider(careProviderIDType, careProviderID, careProviderName);
221         SystemInfo systemInfo = new SystemInfo(careProvider, itSystemName);
222 
223         // All IDCard types must have a IDCardData element
224         if(!hasIDCardData)  throw new ModelBuildException("IDCardData element missing for IDCard");
225 
226         // All IDCard types must have a SystemLog element
227         if(!hasSystemLog)  throw new ModelBuildException("SystemLog element missing for IDCard");
228 
229         if (isUserIDCard == null)
230             throw new ModelBuildException("ID Card type not found or invalid");
231         else if (isUserIDCard.booleanValue()) {
232             if(!hasUserLog) throw new ModelBuildException("UserLog element missing for UserIDCard");
233             UserInfo userInfo = new UserInfo(cpr, givenName, surName, email, occupation, userRole, authorizationCode);
234             result = new UserIDCard(version, idCardElement, id, AuthenticationLevel.getEnumeratedValue(Integer.parseInt(authLevel)), ocesCertHash,
235                     issuer, systemInfo, userInfo, createdDate, expiryDate, alternativeIdentifier, username, password);
236         } else {
237             if(hasUserLog) throw new ModelBuildException("IDCard type is 'system', but also has a UserLog element (??)");
238             result = new SystemIDCard(version, idCardElement, id, AuthenticationLevel.getEnumeratedValue(Integer.parseInt(authLevel)),
239                     ocesCertHash, issuer, systemInfo, createdDate, expiryDate, alternativeIdentifier, username, password);
240         }
241         return result;
242     }
243 
244 }