source: ccr/trunk/nhin-vista/projects/NHINC/Current/Product/Production/Examples/DynamicPolicyExample/TokenInfoManagerEJB/src/java/xwss/saml/SamlCallbackHandler.java@ 507

Last change on this file since 507 was 507, checked in by George Lilly, 15 years ago

NHIN gateway and adaptor for use on linux with VistA EHR and RPMS

File size: 33.0 KB
Line 
1package xwss.saml;
2
3import com.sun.org.apache.xml.internal.security.keys.KeyInfo;
4import com.sun.xml.wss.XWSSecurityException;
5import java.io.*;
6import java.security.KeyStoreException;
7import java.security.NoSuchAlgorithmException;
8import java.security.UnrecoverableKeyException;
9import java.security.cert.CertificateException;
10import java.util.*;
11
12import java.security.KeyStore;
13import java.security.PrivateKey;
14import java.security.PublicKey;
15import java.security.cert.X509Certificate;
16import java.security.cert.Certificate;
17import javax.security.auth.callback.Callback;
18import javax.security.auth.callback.CallbackHandler;
19import javax.security.auth.callback.UnsupportedCallbackException;
20import com.sun.xml.wss.impl.callback.*;
21import com.sun.xml.wss.saml.*;
22import javax.xml.parsers.DocumentBuilderFactory;
23import javax.xml.parsers.ParserConfigurationException;
24import org.w3c.dom.*;
25import gov.hhs.fha.nhinc.token.InternalTokenMgr;
26import java.text.ParseException;
27import java.text.SimpleDateFormat;
28//import javax.mail.internet.AddressException;
29//import javax.mail.internet.InternetAddress;
30import javax.security.auth.x500.X500Principal;
31import org.apache.commons.logging.Log;
32import org.apache.commons.logging.LogFactory;
33
34/**
35 * This class implements the CallbackHandler which is invoked upon sending a
36 * message requiring the SAML Assertion Token. It accessed the information from
37 * the storage file in order to build up the required token elements.
38 */
39public class SamlCallbackHandler implements CallbackHandler {
40
41 private static Log log = LogFactory.getLog(SamlCallbackHandler.class);
42 private static final String AUTHN_DECISION = "Permit";
43 private static final String EVIDENCE_FORM_TYPE = "application/pdf";
44 public static final String HOK_CONFIRM = "urn:oasis:names:tc:SAML:2.0:cm:holder-of-key";
45 public static final String SV_CONFIRM = "urn:oasis:names:tc:SAML:2.0:cm:authorization-over-ssl";
46 private static final String X509_ID = "urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName";
47 private static final String WIN_ID = "urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName";
48 private static final String UNSPECIFIED = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified";
49 private static final String X509_AUTHN_CNTX_CLS = "urn:oasis:names:tc:SAML:2.0:ac:classes:X509";
50 private static final String NHIN_NS = "http://www.hhs.gov/healthit/nhin";
51 private static final int defaultName = 0;
52 private static final int primaryName = 1;
53 private Properties tokenVals;
54 private KeyStore keyStore;
55 private KeyStore trustStore;
56 private static final String storeType = "JKS";
57 private static Element svAssertion;
58 private static Element hokAssertion20;
59
60
61 static {
62 //WORKAROUND NEEDED IN METRO1.4. TO BE REMOVED LATER.
63 javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
64 new javax.net.ssl.HostnameVerifier() {
65
66 public boolean verify(String hostname,
67 javax.net.ssl.SSLSession sslSession) {
68 return true;
69 }
70 });
71 }
72
73 /**
74 * Constructs the callback handler and initializes the keystore and
75 * truststore references to the security certificates
76 */
77 public SamlCallbackHandler() {
78 log.debug("SamlCallbackHandler Constructor -- Begin");
79 try {
80 initKeyStore();
81 initTrustStore();
82 } catch (IOException e) {
83 log.error("SamlCallbackHandler Exception: " + e.getMessage());
84 e.printStackTrace();
85 throw new RuntimeException(e);
86 }
87 log.debug("SamlCallbackHandler Constructor -- Begin");
88 }
89
90 /**
91 * This is the invoked implementation to handle the SAML Token creation upon
92 * notification of an outgoing message needing SAML. Based on the type of
93 * confirmation method detected on the Callbace it creates either a
94 * "Sender Vouches: or a "Holder-ok_Key" variant of the SAML Assertion.
95 * @param callbacks The SAML Callback
96 * @throws java.io.IOException
97 * @throws javax.security.auth.callback.UnsupportedCallbackException
98 */
99 public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
100 log.debug(" ********************************** Handle SAML Callback Begin**************************");
101 getProperties();
102 for (int i = 0; i < callbacks.length; i++) {
103 if (callbacks[i] instanceof SAMLCallback) {
104 SAMLCallback samlCallback = (SAMLCallback) callbacks[i];
105 if (samlCallback.getConfirmationMethod().equals(SAMLCallback.HOK_ASSERTION_TYPE)) {
106 samlCallback.setAssertionElement(createHOKSAMLAssertion20());
107 hokAssertion20 = samlCallback.getAssertionElement();
108 } else if (samlCallback.getConfirmationMethod().equals(SAMLCallback.SV_ASSERTION_TYPE)) {
109 samlCallback.setAssertionElement(createSVSAMLAssertion20());
110 svAssertion = samlCallback.getAssertionElement();
111 } else {
112 log.error("Unknown SAML Assertion Type: " + samlCallback.getConfirmationMethod());
113 throw new UnsupportedCallbackException(null, "SAML Assertion Type is not matched:" + samlCallback.getConfirmationMethod());
114 }
115 } else {
116 log.error("Unknown Callback encountered: " + callbacks[i]);
117 throw new UnsupportedCallbackException(null, "Unsupported Callback Type Encountered");
118 }
119 }
120 log.debug("********************************** Handle SAML Callback End**************************");
121 System.out.flush();
122 }
123
124 /**
125 * Creates the "Sender Vouches" variant of the SAML Assertion token.
126 * @return The Assertion element
127 */
128 private Element createSVSAMLAssertion20() {
129 log.debug("SamlCallbackHandler.createSVSAMLAssertion20() -- Begin");
130 Assertion assertion = null;
131 try {
132 SAMLAssertionFactory factory = SAMLAssertionFactory.newInstance(SAMLAssertionFactory.SAML2_0);
133
134 // create the assertion id
135 String aID = String.valueOf(UUID.randomUUID());
136
137 // name id of the issuer - For now just use default
138 NameID issueId = create509NameID(factory, defaultName);
139
140 // issue instant
141 GregorianCalendar issueInstant = calendarFactory();
142
143 // name id of the subject - user name
144 String uname = "defUser";
145 if (tokenVals.containsKey(InternalTokenMgr.userNameAttrName)) {
146 uname = tokenVals.getProperty(InternalTokenMgr.userNameAttrName);
147 }
148 NameID nmId = factory.createNameID(uname, null, WIN_ID);
149 Subject subj = factory.createSubject(nmId, null);
150
151 // authentication statement
152 List statements = createAuthnStatements(factory, issueInstant);
153
154 assertion = factory.createAssertion(aID, issueId, issueInstant,
155 null, null, subj, statements);
156
157 assertion.setVersion("2.0");
158
159 log.debug("createSVSAMLAssertion20 end ()");
160 return assertion.toElement(null);
161 } catch (Exception e) {
162 e.printStackTrace();
163 throw new RuntimeException(e);
164 }
165 }
166
167 /**
168 * Creates the "Holder-of-Key" variant of the SAML Assertion token.
169 * @return The Assertion element
170 */
171 private Element createHOKSAMLAssertion20() {
172 log.debug("SamlCallbackHandler.createHOKSAMLAssertion20() -- Begin");
173 Assertion assertion = null;
174 try {
175 SAMLAssertionFactory factory = SAMLAssertionFactory.newInstance(SAMLAssertionFactory.SAML2_0);
176
177 // create the assertion id
178 String aID = String.valueOf(UUID.randomUUID());
179
180 // name id of the issuer - For now just use default
181 NameID issueId = create509NameID(factory, defaultName);
182
183 // issue instant
184 GregorianCalendar issueInstant = calendarFactory();
185
186 // subject information
187 NameID subjId = create509NameID(factory, primaryName);
188
189 // default private key cert request
190 SignatureKeyCallback.DefaultPrivKeyCertRequest request = new SignatureKeyCallback.DefaultPrivKeyCertRequest();
191 getDefaultPrivKeyCert(request);
192 if (request.getX509Certificate() == null) {
193 throw new RuntimeException("Not able to resolve the Default Certificate");
194 }
195 PublicKey pubKey = request.getX509Certificate().getPublicKey();
196 PrivateKey privKey = request.getPrivateKey();
197
198 // subject confirmation
199 DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
200 Document doc = docFactory.newDocumentBuilder().newDocument();
201 KeyInfo keyInfo = new KeyInfo(doc);
202 keyInfo.addKeyValue(pubKey);
203 SubjectConfirmationData scd = factory.createSubjectConfirmationData(null, null, null, null, null, keyInfo.getElement());
204 SubjectConfirmation scf = factory.createSubjectConfirmation(null, scd, HOK_CONFIRM);
205 Subject subj = factory.createSubject(subjId, scf);
206
207 // authentication statement
208 List statements = createAuthnStatements(factory, issueInstant);
209
210 assertion = factory.createAssertion(aID, issueId, issueInstant, null, null, subj, statements);
211 assertion.setVersion("2.0");
212 log.debug("SamlCallbackHandler.createHOKSAMLAssertion20() -- End");
213 return assertion.sign(pubKey, privKey);
214 } catch (ParserConfigurationException ex) {
215 log.error("Unable to create HOK Assertion: " + ex.getMessage());
216 ex.printStackTrace();
217 throw new RuntimeException(ex);
218 } catch (IOException ex) {
219 log.error("Unable to create HOK Assertion: " + ex.getMessage());
220 ex.printStackTrace();
221 throw new RuntimeException(ex);
222 } catch (SAMLException ex) {
223 log.error("Unable to create HOK Assertion: " + ex.getMessage());
224 ex.printStackTrace();
225 throw new RuntimeException(ex);
226 } catch (XWSSecurityException ex) {
227 log.error("Unable to create HOK Assertion: " + ex.getMessage());
228 ex.printStackTrace();
229 throw new RuntimeException(ex);
230 }
231 }
232
233 /**
234 * Both the Issuer and the Subject elements have a NameID element which is
235 * formed through this method. Currently default data is used to specify
236 * the required Issuer information. However, the Subject information is
237 * defined based on the stored value of the userid. If this is a legal X509
238 * structute the NameId is constructed in that format, if not it is
239 * constructed as an "Unspecified" format.
240 * @param factory The factory object used to assist in the construction of
241 * the SAML Assertion token
242 * @param assId Identifies this as default usage case or one with declared
243 * value.
244 * @return The constructed NameID element
245 * @throws com.sun.xml.wss.saml.SAMLException
246 */
247 private NameID create509NameID(SAMLAssertionFactory factory, int assId) throws SAMLException {
248 log.debug("SamlCallbackHandler.createNameID() -- Begin");
249 NameID nmId = null;
250 String defCN = "SAML User";
251 String defOU = "SU";
252 String defO = "SAML User";
253 String defL = "Los Angeles";
254 String defST = "CA";
255 String defC = "US";
256
257 String identifier;
258 if (assId != primaryName) {
259 identifier = "CN=" + defCN + "," + "OU=" + defOU + "," +
260 "O=" + defO + "," + "L=" + defL + "," +
261 "ST=" + defST + "," + "C=" + defC;
262 nmId = factory.createNameID(identifier, null, X509_ID);
263 log.debug("Create X509 name: " + identifier);
264 } else {
265 String x509Name = "UID=" + tokenVals.getProperty(InternalTokenMgr.userNameAttrName);
266 try {
267 X500Principal prin = new X500Principal(x509Name);
268 nmId = factory.createNameID(x509Name, null, X509_ID);
269 log.debug("Create X509 name: " + x509Name);
270 } catch (IllegalArgumentException iae) {
271 /* Could also test if email form if we wanted to support that */
272 log.warn("Set format as Unspecified. Invalid X509 format: " +
273 tokenVals.getProperty(InternalTokenMgr.userNameAttrName) + " " + iae.getMessage());
274 nmId = factory.createNameID(tokenVals.getProperty(InternalTokenMgr.userNameAttrName), null, UNSPECIFIED);
275 }
276 }
277
278 log.debug("SamlCallbackHandler.createNameID() -- End");
279 return nmId;
280 }
281
282 /*public boolean isValidEmailAddress(String address) {
283 log.debug("SamlCallbackHandler.isValidEmailAddress() " + address + " -- Begin");
284 boolean retBool = false;
285 if (address != null && address.length() > 0) {
286 try {
287 InternetAddress emailAddr = new InternetAddress(address, true);
288 String[] tokens = address.split("@");
289 if (tokens.length == 2 && tokens[0].trim().length() > 0 && tokens[1].trim().length() > 0) {
290 retBool = true;
291 } else {
292 log.debug("Address does not follow the form 'local-part@domain'");
293 }
294 } catch (AddressException ex) {
295 // address does not comply with RFC822
296 log.debug("Address is not of the RFC822 format");
297 }
298 }
299 log.debug("SamlCallbackHandler.isValidEmailAddress() " + retBool + " -- End");
300 return retBool;
301 }*/
302 /**
303 * Creates the authentication statement, the attribute statements, and the
304 * authorization decision statements for placement in the SAML Assertion.
305 * @param factory The factory object used to assist in the construction of
306 * the SAML Assertion token
307 * @param issueInstant The calendar representing the time of Assertion issuance
308 * @return A listing of all statements
309 * @throws com.sun.xml.wss.saml.SAMLException
310 */
311 private List createAuthnStatements(SAMLAssertionFactory factory, GregorianCalendar issueInstant) throws SAMLException {
312 log.debug("SamlCallbackHandler.createAuthnStatements() -- Begin");
313 List statements = new ArrayList();
314
315 // Create Subject Locality
316 SubjectLocality subjLoc = null;
317 /* This is currently an optional item
318 try {
319 subjLoc = factory.createSubjectLocality(InetAddress.getLocalHost().getHostAddress(), InetAddress.getLocalHost().getCanonicalHostName());
320 } catch (UnknownHostException ex) {
321 log.debug("Optional element SubjectLocality can not be determined: " + ex.getMessage());
322 }*/
323 AuthnContext authnContext = factory.createAuthnContext(X509_AUTHN_CNTX_CLS, null);
324
325 // Create Authentication statement
326 AuthnStatement authState = (com.sun.xml.wss.saml.assertion.saml20.jaxb20.AuthnStatement) factory.createAuthnStatement(issueInstant, subjLoc, authnContext, "123456", null);
327
328 if (authState != null) {
329 statements.add(authState);
330 }
331
332 statements.addAll(addAssertStatements(factory));
333
334 // Create resource for Authentication Statement
335 String resource = null;
336 if (tokenVals.containsKey(InternalTokenMgr.resourceAttrName)) {
337 resource = tokenVals.getProperty(InternalTokenMgr.resourceAttrName);
338 }
339
340 // Options are Permit (Deny and Indeterminate are not used at this time)
341 String decision = AUTHN_DECISION;
342
343 List actions = new ArrayList();
344 if (tokenVals.containsKey(InternalTokenMgr.actionAttrName)) {
345 String actionAttr = tokenVals.getProperty(InternalTokenMgr.actionAttrName);
346 try {
347 final Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
348 final Element elemURAttr = document.createElementNS("urn:oasis:names:tc:SAML:2.0:assertion", "Action");
349 elemURAttr.setAttribute("Namespace", NHIN_NS);
350 elemURAttr.setTextContent(actionAttr);
351 actions.add(elemURAttr);
352 } catch (ParserConfigurationException ex) {
353 actions.add(actionAttr);
354 }
355 }
356
357 // Evidence Assertion generation
358 Evidence evidence = createEvidence(factory, issueInstant);
359
360 AuthnDecisionStatement authDecState = factory.createAuthnDecisionStatement(resource, decision, actions, evidence);
361 if (authDecState != null) {
362 statements.add(authDecState);
363 }
364
365 log.debug("SamlCallbackHandler.createAuthnStatements() -- End");
366 return statements;
367 }
368
369 /**
370 * Creates the Attribute statements for UserName, UserOrganization,
371 * UserRole, and PurposeForUse
372 * @param factory The factory object used to assist in the construction of
373 * the SAML Assertion token
374 * @return The listing of all Attribute statements
375 * @throws com.sun.xml.wss.saml.SAMLException
376 */
377 private List addAssertStatements(SAMLAssertionFactory factory) throws SAMLException {
378
379 log.debug("SamlCallbackHandler.addAssertStatements() -- Begin");
380 List statements = new ArrayList();
381 List attributes = new ArrayList();
382
383 // Set the User Name Attribute
384 List attributeValues1 = new ArrayList();
385 attributeValues1.add(tokenVals.getProperty(InternalTokenMgr.userFirstNameAttrName) + " " + tokenVals.getProperty(InternalTokenMgr.userMiddleNameAttrName) + " " + tokenVals.getProperty(InternalTokenMgr.userLastNameAttrName));
386 attributes.add(factory.createAttribute(InternalTokenMgr.userNameAttrName, NHIN_NS, attributeValues1));
387
388 // Set the User Organization Attribute
389 List attributeValues2 = new ArrayList();
390 attributeValues2.add(tokenVals.getProperty(InternalTokenMgr.userOrgAttrName));
391 attributes.add(factory.createAttribute(InternalTokenMgr.userOrgAttrName, NHIN_NS, attributeValues2));
392
393 try {
394 // Set the User Role Attribute
395 List attributeValues3 = new ArrayList();
396 final Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
397 final Element elemURAttr = document.createElementNS("urn:oasis:names:tc:SAML:2.0:assertion", "AttibuteValue");
398 final Element userRole = document.createElementNS(NHIN_NS, "nhin:Role");
399 elemURAttr.appendChild(userRole);
400 userRole.setAttribute("code", tokenVals.getProperty(InternalTokenMgr.userRoleCodeAttrName));
401 userRole.setAttribute("codeSystem", tokenVals.getProperty(InternalTokenMgr.userRoleCodeSystemAttrName));
402 userRole.setAttribute("codeSystemName", tokenVals.getProperty(InternalTokenMgr.userRoleCodeSystemNameAttrName));
403 userRole.setAttribute("displayName", tokenVals.getProperty(InternalTokenMgr.userRoleDisplayAttrName));
404 attributeValues3.add(elemURAttr);
405 attributes.add(factory.createAttribute("UserRole", NHIN_NS, attributeValues3));
406
407 // Add a hardcoded string for Purpose For Use Attribute
408 List attributeValues4 = new ArrayList();
409 final Element elemPFUAttr = document.createElementNS("urn:oasis:names:tc:SAML:2.0:assertion", "AttibuteValue");
410 final Element purpose = document.createElementNS(NHIN_NS, "nhin:PurposeForUse");
411 elemPFUAttr.appendChild(purpose);
412 purpose.setAttribute("code", tokenVals.getProperty(InternalTokenMgr.purposeCodeAttrName));
413 purpose.setAttribute("codeSystem", tokenVals.getProperty(InternalTokenMgr.purposeCodeSystemAttrName));
414 purpose.setAttribute("codeSystemName", tokenVals.getProperty(InternalTokenMgr.purposeCodeSystemNameAttrName));
415 purpose.setAttribute("displayName", tokenVals.getProperty(InternalTokenMgr.purposeDisplayAttrName));
416 attributeValues4.add(elemPFUAttr);
417 attributes.add(factory.createAttribute("PurposeForUse", NHIN_NS, attributeValues4));
418
419 if (!attributes.isEmpty()) {
420 statements.add(factory.createAttributeStatement(attributes));
421 }
422 } catch (ParserConfigurationException ex) {
423 log.debug("Unable to create an XML Document to set Attributes" + ex.getMessage());
424 }
425 log.debug("SamlCallbackHandler.addAssertStatements() -- End");
426 return statements;
427
428 }
429
430 /**
431 * Creates the Evidence element that encompasses the Assertion defining the
432 * authorization form needed in cases where evidence of authorization to
433 * access the medical records must be provided along with the message request
434 * @param factory The factory object used to assist in the construction of
435 * the SAML Assertion token
436 * @param issueInstant The calendar representing the time of Assertion issuance
437 * @return The Evidence element
438 * @throws com.sun.xml.wss.saml.SAMLException
439 */
440 private Evidence createEvidence(SAMLAssertionFactory factory, GregorianCalendar issueInstant) throws SAMLException {
441 log.debug("SamlCallbackHandler.createEvidence() -- Begin");
442
443 List evAsserts = new ArrayList();
444 try {
445 String evAssertionID = String.valueOf(UUID.randomUUID());
446 NameID evIssuerId = create509NameID(factory, defaultName);
447
448 GregorianCalendar beginValidTime = calendarFactory();
449 if (tokenVals.containsKey(InternalTokenMgr.signDateAttrName)) {
450 beginValidTime = createCal(tokenVals.getProperty(InternalTokenMgr.signDateAttrName));
451 }
452 GregorianCalendar endValidTime = calendarFactory();
453 if (tokenVals.containsKey(InternalTokenMgr.expireDateAttrName)) {
454 endValidTime = createCal(tokenVals.getProperty(InternalTokenMgr.expireDateAttrName));
455 }
456
457 if (beginValidTime.after(endValidTime)) {
458 // set beginning time to now
459 beginValidTime = calendarFactory();
460 log.warn("The beginning time for the valid evidence should be before the ending time. " +
461 "Setting the beginning time to the current system time.");
462 }
463
464 Conditions conditions = factory.createConditions(beginValidTime, endValidTime, null, null, null, null);
465
466 List statements = createEvidenceStatements(factory);
467 evAsserts.add(factory.createAssertion(evAssertionID, evIssuerId, issueInstant, conditions, null, null, statements));
468 } catch (SAMLException ex) {
469 log.debug("Unable to create Evidence Assertion: " + ex.getMessage());
470 }
471 Evidence evidence = factory.createEvidence(null, evAsserts);
472 log.debug("SamlCallbackHandler.createEvidence() -- End");
473 return evidence;
474 }
475
476 /**
477 * Creates a calendar object representing the time given.
478 * @param time following the simple date form MM/dd/yyyy HH:mm:ss
479 * @return The calendar object representing the given time
480 */
481 private GregorianCalendar createCal(String time) {
482 GregorianCalendar cal = calendarFactory();
483 try {
484 SimpleDateFormat dateForm = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
485 cal.setTime(dateForm.parse(time));
486 log.info("SamlCallbackHandler.createCal() Date: " + (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DAY_OF_MONTH) + "/" + cal.get(Calendar.YEAR) + " " + cal.get(Calendar.HOUR_OF_DAY) + ":" + cal.get(Calendar.MINUTE) + ":" + cal.get(Calendar.SECOND));
487 } catch (ParseException ex) {
488 log.error(SamlCallbackHandler.class.getName() + "Date form is expected to be MM/dd/yyyy HH:mm:ss set default date");
489 }
490 return cal;
491 }
492
493 /**
494 * Creates the Attribute Statements needed for the Evidence element. These
495 * include the Attributes for the ContentType, ContentReference, and the
496 * base64binary Content as well.
497 * @param factory The factory object used to assist in the construction of
498 * the SAML Assertion token
499 * @return The listing of the attribute statements for the Evidence element
500 * @throws com.sun.xml.wss.saml.SAMLException
501 */
502 private List createEvidenceStatements(SAMLAssertionFactory factory) throws SAMLException {
503 log.debug("SamlCallbackHandler.createEvidenceStatements() -- Begin");
504 List statements = new ArrayList();
505 List attributes = new ArrayList();
506
507 // Set the Reference to the SSA-827 form
508 List attributeValues1 = new ArrayList();
509 attributeValues1.add(tokenVals.getProperty(InternalTokenMgr.claimRefAttrName));
510 attributes.add(factory.createAttribute(InternalTokenMgr.claimRefAttrName, NHIN_NS, attributeValues1));
511
512 // Set the format of the SSA-827 form
513 List attributeValues2 = new ArrayList();
514 attributeValues2.add(EVIDENCE_FORM_TYPE);
515 attributes.add(factory.createAttribute("ContentType", NHIN_NS, attributeValues2));
516
517 // Set the content of the SSA-827 form
518 List attributeValues3 = new ArrayList();
519 attributeValues3.add(tokenVals.getProperty(InternalTokenMgr.claimFormAttrName).getBytes());
520 attributes.add(factory.createAttribute(InternalTokenMgr.claimFormAttrName, NHIN_NS, attributeValues3));
521
522 if (!attributes.isEmpty()) {
523 statements.add(factory.createAttributeStatement(attributes));
524 }
525 log.debug("SamlCallbackHandler.createEvidenceStatements() -- End");
526 return statements;
527 }
528
529 /**
530 * Reads the storage file and extracts all the stored key / value pairs as
531 * properties
532 */
533 private void getProperties() {
534 log.debug("SamlCallbackHandler.getProperties() -- Begin");
535
536 tokenVals = new Properties();
537 BufferedReader reader = null;
538 String fileName = null;
539 try {
540 PropertyResourceBundle prop = (PropertyResourceBundle) PropertyResourceBundle.getBundle(InternalTokenMgr.propFileName);
541 fileName = prop.getString(InternalTokenMgr.storeFileName);
542
543 reader = new BufferedReader(new FileReader(fileName));
544 tokenVals.load(reader);
545
546 } catch (IOException ex) {
547 log.error("Can not access " + fileName + " " + ex);
548 } finally {
549 try {
550 if (reader != null) {
551 reader.close();
552 }
553 } catch (IOException iOException) {
554 log.error("SamlCallbackHandler " + iOException.getMessage());
555 }
556 }
557 log.debug("SamlCallbackHandler.getProperties() -- End");
558 return;
559 }
560
561 /**
562 * Initializes the keystore access using the system properties defined in
563 * the domain.xml javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword
564 * @throws java.io.IOException
565 */
566 private void initKeyStore() throws IOException {
567 log.debug("SamlCallbackHandler.initKeyStore() -- Begin");
568 InputStream is = null;
569 String storeLoc = System.getProperty("javax.net.ssl.keyStore");
570 if (storeLoc != null) {
571 String password = System.getProperty("javax.net.ssl.keyStorePassword");
572 if (password != null) {
573 try {
574 keyStore = KeyStore.getInstance(storeType);
575 is = new FileInputStream(storeLoc);
576 keyStore.load(is, password.toCharArray());
577 } catch (NoSuchAlgorithmException ex) {
578 log.error("Error initializing KeyStore: " + ex);
579 throw new IOException(ex.getMessage());
580 } catch (CertificateException ex) {
581 log.error("Error initializing KeyStore: " + ex);
582 throw new IOException(ex.getMessage());
583 } catch (KeyStoreException ex) {
584 log.error("Error initializing KeyStore: " + ex);
585 throw new IOException(ex.getMessage());
586 }
587 log.debug("SamlCallbackHandler.initKeyStore() -- End");
588 } else {
589 log.error("javax.net.ssl.keyStorePassword is not defined in domain.xml");
590 }
591 } else {
592 log.error("javax.net.ssl.keyStore is not defined in domain.xml");
593 }
594 }
595
596 /**
597 * Initializes the truststore access using the system properties defined in
598 * the domain.xml javax.net.ssl.trustStore and
599 * javax.net.ssl.trustStorePassword
600 * @throws java.io.IOException
601 */
602 private void initTrustStore() throws IOException {
603 log.debug("SamlCallbackHandler.initTrustStore() -- Begin");
604 InputStream is = null;
605 String storeLoc = System.getProperty("javax.net.ssl.trustStore");
606 if (storeLoc != null) {
607 String password = System.getProperty("javax.net.ssl.trustStorePassword");
608 if (password != null) {
609 try {
610 trustStore = KeyStore.getInstance(storeType);
611 is = new FileInputStream(storeLoc);
612 trustStore.load(is, password.toCharArray());
613 } catch (NoSuchAlgorithmException ex) {
614 log.error("Error initializing TrustStore: " + ex);
615 throw new IOException(ex.getMessage());
616 } catch (CertificateException ex) {
617 log.error("Error initializing TrustStore: " + ex);
618 throw new IOException(ex.getMessage());
619 } catch (KeyStoreException ex) {
620 log.error("Error initializing TrustStore: " + ex);
621 throw new IOException(ex.getMessage());
622 }
623 } else {
624 log.error("javax.net.ssl.trustStorePassword is not defined in domain.xml");
625 }
626 } else {
627 log.error("javax.net.ssl.trustStore is not defined in domain.xml");
628 }
629 log.debug("SamlCallbackHandler.initTrustStore() -- End");
630 }
631
632 /**
633 * Finds the X509 certificate in the keystore with the client alias as
634 * defined in the domain.xml system property CLIENT_KEY_ALIAS and
635 * establishes the private key on the SignatureKeyCallback request using
636 * this certificate.
637 * @param request The SignatureKeyCallback request object
638 * @throws java.io.IOException
639 */
640 private void getDefaultPrivKeyCert(
641 SignatureKeyCallback.DefaultPrivKeyCertRequest request)
642 throws IOException {
643 log.debug("SamlCallbackHandler.getDefaultPrivKeyCert() -- Begin");
644 String uniqueAlias = null;
645 String client_key_alias = System.getProperty("CLIENT_KEY_ALIAS");
646 if (client_key_alias != null) {
647 String password = System.getProperty("javax.net.ssl.keyStorePassword");
648 if (password != null) {
649 try {
650 Enumeration aliases = keyStore.aliases();
651 while (aliases.hasMoreElements()) {
652 String currentAlias = (String) aliases.nextElement();
653 if (currentAlias.equals(client_key_alias)) {
654 if (keyStore.isKeyEntry(currentAlias)) {
655 Certificate thisCertificate = keyStore.getCertificate(currentAlias);
656 if (thisCertificate != null) {
657 if (thisCertificate instanceof X509Certificate) {
658 if (uniqueAlias == null) {
659 uniqueAlias = currentAlias;
660 break;
661 }
662 }
663 }
664 }
665 }
666 }
667 if (uniqueAlias != null) {
668 request.setX509Certificate(
669 (X509Certificate) keyStore.getCertificate(uniqueAlias));
670 request.setPrivateKey(
671 (PrivateKey) keyStore.getKey(uniqueAlias, password.toCharArray()));
672 } else {
673 log.error("Client key alais can not be determined");
674 }
675 } catch (UnrecoverableKeyException ex) {
676 log.error("Error initializing Private Key: " + ex);
677 throw new IOException(ex.getMessage());
678 } catch (NoSuchAlgorithmException ex) {
679 log.error("Error initializing Private Key: " + ex);
680 throw new IOException(ex.getMessage());
681 } catch (KeyStoreException ex) {
682 log.error("Error initializing Private Key: " + ex);
683 throw new IOException(ex.getMessage());
684 }
685 } else {
686 log.error("javax.net.ssl.keyStorePassword is not defined in domain.xml");
687 }
688 } else {
689 log.error("CLIENT_KEY_ALIAS is not defined in domain.xml");
690 }
691 log.debug("SamlCallbackHandler.getDefaultPrivKeyCert() -- End");
692 }
693
694 /**
695 * Creates a calendar instance set to the current system time in GMT
696 * @return The calendar instance
697 */
698 private GregorianCalendar calendarFactory() {
699 GregorianCalendar calendar = new GregorianCalendar();
700 calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
701 return calendar;
702 }
703}
Note: See TracBrowser for help on using the repository browser.