1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.ws.security.handler;
21
22 import java.security.cert.X509Certificate;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Properties;
30 import java.util.concurrent.ConcurrentHashMap;
31 import java.util.regex.Pattern;
32 import java.util.regex.PatternSyntaxException;
33
34 import javax.security.auth.callback.Callback;
35 import javax.security.auth.callback.CallbackHandler;
36
37 import org.apache.ws.security.WSConstants;
38 import org.apache.ws.security.WSEncryptionPart;
39 import org.apache.ws.security.WSPasswordCallback;
40 import org.apache.ws.security.WSSConfig;
41 import org.apache.ws.security.WSSecurityEngine;
42 import org.apache.ws.security.WSSecurityEngineResult;
43 import org.apache.ws.security.WSSecurityException;
44 import org.apache.ws.security.action.Action;
45 import org.apache.ws.security.components.crypto.AlgorithmSuite;
46 import org.apache.ws.security.components.crypto.Crypto;
47 import org.apache.ws.security.components.crypto.CryptoFactory;
48 import org.apache.ws.security.message.WSSecHeader;
49 import org.apache.ws.security.message.token.SignatureConfirmation;
50 import org.apache.ws.security.util.Loader;
51 import org.apache.ws.security.util.StringUtil;
52 import org.apache.ws.security.util.WSSecurityUtil;
53 import org.w3c.dom.Document;
54
55
56
57
58
59
60
61
62
63
64 public abstract class WSHandler {
65 private static org.apache.commons.logging.Log log =
66 org.apache.commons.logging.LogFactory.getLog(WSHandler.class);
67 protected WSSecurityEngine secEngine = new WSSecurityEngine();
68 protected Map<String, Crypto> cryptos = new ConcurrentHashMap<String, Crypto>();
69
70 private boolean doDebug = log.isDebugEnabled();
71
72
73
74
75
76
77
78
79
80
81
82
83 @SuppressWarnings("unchecked")
84 protected void doSenderAction(
85 int doAction,
86 Document doc,
87 RequestData reqData,
88 List<Integer> actions,
89 boolean isRequest
90 ) throws WSSecurityException {
91
92 boolean mu = decodeMustUnderstand(reqData);
93
94 WSSConfig wssConfig = reqData.getWssConfig();
95 if (wssConfig == null) {
96 wssConfig = secEngine.getWssConfig();
97 }
98
99 boolean enableSigConf = decodeEnableSignatureConfirmation(reqData);
100 wssConfig.setEnableSignatureConfirmation(
101 enableSigConf || ((doAction & WSConstants.SC) != 0)
102 );
103 wssConfig.setPasswordsAreEncoded(decodeUseEncodedPasswords(reqData));
104
105 wssConfig.setPrecisionInMilliSeconds(
106 decodeTimestampPrecision(reqData)
107 );
108 reqData.setWssConfig(wssConfig);
109
110 Object mc = reqData.getMsgContext();
111 String actor = getString(WSHandlerConstants.ACTOR, mc);
112 reqData.setActor(actor);
113
114 WSSecHeader secHeader = new WSSecHeader(actor, mu);
115 secHeader.insertSecurityHeader(doc);
116
117 reqData.setSecHeader(secHeader);
118 reqData.setSoapConstants(
119 WSSecurityUtil.getSOAPConstants(doc.getDocumentElement())
120 );
121 wssConfig.setWsiBSPCompliant(decodeBSPCompliance(reqData));
122
123
124
125
126 if ((doAction & WSConstants.UT) == WSConstants.UT) {
127 decodeUTParameter(reqData);
128 }
129
130
131
132
133 if ((doAction & WSConstants.UT_SIGN) == WSConstants.UT_SIGN) {
134 decodeUTParameter(reqData);
135 decodeSignatureParameter(reqData);
136 }
137
138
139
140
141 if ((doAction & WSConstants.SIGN) == WSConstants.SIGN) {
142 if (reqData.getSigCrypto() == null) {
143 reqData.setSigCrypto(loadSignatureCrypto(reqData));
144 }
145 decodeSignatureParameter(reqData);
146 }
147
148
149
150
151
152 if ((doAction & WSConstants.ST_SIGNED) == WSConstants.ST_SIGNED) {
153 decodeSignatureParameter(reqData);
154 }
155
156
157
158
159 if ((doAction & WSConstants.ENCR) == WSConstants.ENCR) {
160 if (reqData.getEncCrypto() == null) {
161 reqData.setEncCrypto(loadEncryptionCrypto(reqData));
162 }
163 decodeEncryptionParameter(reqData);
164 }
165
166
167
168
169
170
171 if (reqData.getSignatureParts().isEmpty()) {
172 WSEncryptionPart encP = new WSEncryptionPart(reqData.getSoapConstants()
173 .getBodyQName().getLocalPart(), reqData.getSoapConstants()
174 .getEnvelopeURI(), "Content");
175 reqData.getSignatureParts().add(encP);
176 }
177
178
179
180
181
182
183 if (wssConfig.isEnableSignatureConfirmation() && !isRequest) {
184 String done =
185 (String)getProperty(reqData.getMsgContext(), WSHandlerConstants.SIG_CONF_DONE);
186 if (done == null) {
187 wssConfig.getAction(WSConstants.SC).execute(this, WSConstants.SC, doc, reqData);
188 }
189 }
190
191
192
193
194 List<Integer> actionsToPerform = actions;
195 if (actions.contains(WSConstants.SIGN) && actions.contains(WSConstants.TS)
196 && (actions.indexOf(WSConstants.SIGN) < actions.indexOf(WSConstants.TS))) {
197 boolean signTimestamp = false;
198 for (WSEncryptionPart encP : reqData.getSignatureParts()) {
199 if (WSConstants.WSU_NS.equals(encP.getNamespace())
200 && "Timestamp".equals(encP.getName())) {
201 signTimestamp = true;
202 }
203 }
204 if (signTimestamp) {
205 actionsToPerform = new ArrayList<Integer>(actions);
206 Collections.copy(actionsToPerform, actions);
207 int signatureIndex = actions.indexOf(WSConstants.SIGN);
208 actionsToPerform.remove(signatureIndex);
209 actionsToPerform.add(WSConstants.SIGN);
210 reqData.setAppendSignatureAfterTimestamp(true);
211 reqData.setOriginalSignatureActionPosition(signatureIndex);
212 }
213 }
214
215
216
217
218
219 for (Integer actionToDo : actionsToPerform) {
220 if (doDebug) {
221 log.debug("Performing Action: " + actionToDo);
222 }
223
224 switch (actionToDo) {
225 case WSConstants.UT:
226 case WSConstants.ENCR:
227 case WSConstants.SIGN:
228 case WSConstants.ST_SIGNED:
229 case WSConstants.ST_UNSIGNED:
230 case WSConstants.TS:
231 case WSConstants.UT_SIGN:
232 wssConfig.getAction(actionToDo).execute(this, actionToDo, doc, reqData);
233 break;
234
235
236
237
238
239 default:
240 Action doit = null;
241 try {
242 doit = wssConfig.getAction(actionToDo);
243 } catch (final WSSecurityException e) {
244 log.warn(
245 "Error trying to locate a custom action (" + actionToDo + ")",
246 e
247 );
248 }
249 if (doit != null) {
250 doit.execute(this, actionToDo, doc, reqData);
251 }
252 }
253 }
254
255
256
257
258
259
260 if (wssConfig.isEnableSignatureConfirmation()
261 && isRequest && reqData.getSignatureValues().size() > 0) {
262 List<byte[]> savedSignatures =
263 (List<byte[]>)getProperty(reqData.getMsgContext(), WSHandlerConstants.SEND_SIGV);
264 if (savedSignatures == null) {
265 savedSignatures = new ArrayList<byte[]>();
266 setProperty(
267 reqData.getMsgContext(), WSHandlerConstants.SEND_SIGV, savedSignatures
268 );
269 }
270 savedSignatures.addAll(reqData.getSignatureValues());
271 }
272 }
273
274 protected void doReceiverAction(int doAction, RequestData reqData)
275 throws WSSecurityException {
276
277 WSSConfig wssConfig = reqData.getWssConfig();
278 if (wssConfig == null) {
279 wssConfig = secEngine.getWssConfig();
280 }
281 boolean enableSigConf = decodeEnableSignatureConfirmation(reqData);
282 wssConfig.setEnableSignatureConfirmation(
283 enableSigConf || ((doAction & WSConstants.SC) != 0)
284 );
285 wssConfig.setTimeStampStrict(decodeTimestampStrict(reqData));
286 if (decodePasswordTypeStrict(reqData)) {
287 String passwordType = decodePasswordType(reqData);
288 wssConfig.setRequiredPasswordType(passwordType);
289 }
290 wssConfig.setTimeStampTTL(decodeTimeToLive(reqData, true));
291 wssConfig.setTimeStampFutureTTL(decodeFutureTimeToLive(reqData, true));
292 wssConfig.setUtTTL(decodeTimeToLive(reqData, false));
293 wssConfig.setUtFutureTTL(decodeFutureTimeToLive(reqData, false));
294
295 wssConfig.setHandleCustomPasswordTypes(decodeCustomPasswordTypes(reqData));
296 wssConfig.setPasswordsAreEncoded(decodeUseEncodedPasswords(reqData));
297 wssConfig.setAllowNamespaceQualifiedPasswordTypes(
298 decodeNamespaceQualifiedPasswordTypes(reqData)
299 );
300 wssConfig.setAllowUsernameTokenNoPassword(
301 decodeAllowUsernameTokenNoPassword(reqData)
302 );
303
304 wssConfig.setSecretKeyLength(reqData.getSecretKeyLength());
305 wssConfig.setWsiBSPCompliant(decodeBSPCompliance(reqData));
306 reqData.setWssConfig(wssConfig);
307
308 if (((doAction & WSConstants.SIGN) == WSConstants.SIGN)
309 || ((doAction & WSConstants.ST_SIGNED) == WSConstants.ST_SIGNED)
310 || ((doAction & WSConstants.ST_UNSIGNED) == WSConstants.ST_UNSIGNED)) {
311 decodeSignatureParameter2(reqData);
312 }
313
314 if ((doAction & WSConstants.ENCR) == WSConstants.ENCR) {
315 decodeDecryptionParameter(reqData);
316 }
317 decodeRequireSignedEncryptedDataElements(reqData);
318 }
319
320 protected boolean checkReceiverResults(
321 List<WSSecurityEngineResult> wsResult, List<Integer> actions
322 ) {
323 int size = actions.size();
324 int ai = 0;
325 for (WSSecurityEngineResult result : wsResult) {
326 final Integer actInt = (Integer) result.get(WSSecurityEngineResult.TAG_ACTION);
327 int act = actInt.intValue();
328 if (act == WSConstants.SC || act == WSConstants.BST) {
329 continue;
330 }
331
332 if (ai >= size || actions.get(ai++).intValue() != act) {
333 return false;
334 }
335 }
336
337 if (ai != size) {
338 return false;
339 }
340
341 return true;
342 }
343
344 protected boolean checkReceiverResultsAnyOrder(
345 List<WSSecurityEngineResult> wsResult, List<Integer> actions
346 ) {
347 List<Integer> recordedActions = new ArrayList<Integer>(actions.size());
348 for (Integer action : actions) {
349 recordedActions.add(action);
350 }
351
352 for (WSSecurityEngineResult result : wsResult) {
353 final Integer actInt = (Integer) result.get(WSSecurityEngineResult.TAG_ACTION);
354 int act = actInt.intValue();
355 if (act == WSConstants.SC || act == WSConstants.BST) {
356 continue;
357 }
358
359 if (!recordedActions.remove(actInt)) {
360 return false;
361 }
362 }
363
364 if (!recordedActions.isEmpty()) {
365 return false;
366 }
367
368 return true;
369 }
370
371 @SuppressWarnings("unchecked")
372 protected void checkSignatureConfirmation(
373 RequestData reqData,
374 List<WSSecurityEngineResult> resultList
375 ) throws WSSecurityException{
376 if (doDebug) {
377 log.debug("Check Signature confirmation");
378 }
379
380
381
382 List<byte[]> savedSignatures =
383 (List<byte[]>) getProperty(reqData.getMsgContext(), WSHandlerConstants.SEND_SIGV);
384
385
386
387
388
389 List<WSSecurityEngineResult> sigConf = new ArrayList<WSSecurityEngineResult>();
390 WSSecurityUtil.fetchAllActionResults(resultList, WSConstants.SC, sigConf);
391
392
393
394
395
396
397
398 for (WSSecurityEngineResult result : sigConf) {
399 SignatureConfirmation sc =
400 (SignatureConfirmation)result.get(
401 WSSecurityEngineResult.TAG_SIGNATURE_CONFIRMATION
402 );
403
404 byte[] sigVal = sc.getSignatureValue();
405 if (sigVal != null) {
406 if (savedSignatures == null || savedSignatures.size() == 0) {
407
408
409
410
411 if (sigVal.length != 0) {
412 throw new WSSecurityException(
413 "Received a SignatureConfirmation element, but there are no stored"
414 + " signature values"
415 );
416 }
417 } else {
418 boolean found = false;
419 for (int j = 0; j < savedSignatures.size(); j++) {
420 byte[] storedValue = (byte[]) savedSignatures.get(j);
421 if (Arrays.equals(sigVal, storedValue)) {
422 found = true;
423 savedSignatures.remove(j);
424 break;
425 }
426 }
427 if (!found) {
428 throw new WSSecurityException(
429 "Received a SignatureConfirmation element, but there are no matching"
430 + " stored signature values"
431 );
432 }
433 }
434 }
435 }
436
437
438
439
440
441 if (!reqData.isNoSerialization()) {
442 if (doDebug) {
443 log.debug("Check Signature confirmation - last handler");
444 }
445 if (savedSignatures != null && !savedSignatures.isEmpty()) {
446 throw new WSSecurityException(
447 "Check Signature confirmation: the stored signature values list is not empty"
448 );
449 }
450 }
451 }
452
453 protected void decodeUTParameter(RequestData reqData)
454 throws WSSecurityException {
455 Object mc = reqData.getMsgContext();
456
457 String type = getString(WSHandlerConstants.PASSWORD_TYPE, mc);
458 if (type != null) {
459 if (WSConstants.PW_TEXT.equals(type)) {
460 reqData.setPwType(WSConstants.PASSWORD_TEXT);
461 } else if (WSConstants.PW_DIGEST.equals(type)) {
462 reqData.setPwType(WSConstants.PASSWORD_DIGEST);
463 } else if (WSConstants.PW_NONE.equals(type)) {
464 reqData.setPwType(null);
465 } else {
466 throw new WSSecurityException("Unknown password type encoding: " + type);
467 }
468 }
469
470 String add = getString(WSHandlerConstants.ADD_UT_ELEMENTS, mc);
471 if (add != null) {
472 reqData.setUtElements(StringUtil.split(add, ' '));
473 }
474
475 String derived = getString(WSHandlerConstants.USE_DERIVED_KEY, mc);
476 if (derived != null) {
477 boolean useDerivedKey = Boolean.parseBoolean(derived);
478 reqData.setUseDerivedKey(useDerivedKey);
479 }
480
481 String derivedMAC = getString(WSHandlerConstants.USE_DERIVED_KEY_FOR_MAC, mc);
482 boolean useDerivedKeyForMAC = Boolean.parseBoolean(derivedMAC);
483 if (useDerivedKeyForMAC) {
484 reqData.setUseDerivedKeyForMAC(useDerivedKeyForMAC);
485 }
486
487 String iterations = getString(WSHandlerConstants.DERIVED_KEY_ITERATIONS, mc);
488 if (iterations != null) {
489 int iIterations = Integer.parseInt(iterations);
490 reqData.setDerivedKeyIterations(iIterations);
491 }
492 }
493
494 protected void decodeSignatureParameter(RequestData reqData)
495 throws WSSecurityException {
496 Object mc = reqData.getMsgContext();
497 String signatureUser = getString(WSHandlerConstants.SIGNATURE_USER, mc);
498
499 if (signatureUser != null) {
500 reqData.setSignatureUser(signatureUser);
501 } else {
502 reqData.setSignatureUser(reqData.getUsername());
503 }
504
505 String keyId = getString(WSHandlerConstants.SIG_KEY_ID, mc);
506 if (keyId != null) {
507 Integer id = (Integer) WSHandlerConstants.getKeyIdentifier(keyId);
508 if (id == null) {
509 throw new WSSecurityException(
510 "WSHandler: Signature: unknown key identification"
511 );
512 }
513 int tmp = id.intValue();
514 if (!(tmp == WSConstants.ISSUER_SERIAL
515 || tmp == WSConstants.BST_DIRECT_REFERENCE
516 || tmp == WSConstants.X509_KEY_IDENTIFIER
517 || tmp == WSConstants.SKI_KEY_IDENTIFIER
518 || tmp == WSConstants.THUMBPRINT_IDENTIFIER
519 || tmp == WSConstants.ENCRYPTED_KEY_SHA1_IDENTIFIER
520 || tmp == WSConstants.KEY_VALUE)) {
521 throw new WSSecurityException(
522 "WSHandler: Signature: illegal key identification"
523 );
524 }
525 reqData.setSigKeyId(tmp);
526 }
527 String algo = getString(WSHandlerConstants.SIG_ALGO, mc);
528 reqData.setSigAlgorithm(algo);
529
530 String digestAlgo = getString(WSHandlerConstants.SIG_DIGEST_ALGO, mc);
531 reqData.setSigDigestAlgorithm(digestAlgo);
532
533 String parts = getString(WSHandlerConstants.SIGNATURE_PARTS, mc);
534 if (parts != null) {
535 splitEncParts(parts, reqData.getSignatureParts(), reqData);
536 }
537
538 String secretKeyLength = getString(WSHandlerConstants.WSE_SECRET_KEY_LENGTH, mc);
539 if (secretKeyLength != null) {
540 int iSecretKeyLength = Integer.parseInt(secretKeyLength);
541 reqData.setSecretKeyLength(iSecretKeyLength);
542 }
543
544 boolean useSingleCert = decodeUseSingleCertificate(reqData);
545 reqData.setUseSingleCert(useSingleCert);
546 }
547
548 protected void decodeAlgorithmSuite(RequestData reqData) throws WSSecurityException {
549 Object mc = reqData.getMsgContext();
550 if (mc == null || reqData.getAlgorithmSuite() != null) {
551 return;
552 }
553
554 AlgorithmSuite algorithmSuite = new AlgorithmSuite();
555
556 String signatureAlgorithm = getString(WSHandlerConstants.SIG_ALGO, mc);
557 if (signatureAlgorithm != null && !"".equals(signatureAlgorithm)) {
558 algorithmSuite.addSignatureMethod(signatureAlgorithm);
559 }
560 String signatureDigestAlgorithm = getString(WSHandlerConstants.SIG_DIGEST_ALGO, mc);
561 if (signatureDigestAlgorithm != null && !"".equals(signatureDigestAlgorithm)) {
562 algorithmSuite.addDigestAlgorithm(signatureDigestAlgorithm);
563 }
564
565 String encrAlgorithm = getString(WSHandlerConstants.ENC_SYM_ALGO, mc);
566 if (encrAlgorithm != null && !"".equals(encrAlgorithm)) {
567 algorithmSuite.addEncryptionMethod(encrAlgorithm);
568 }
569 String transportAlgorithm = getString(WSHandlerConstants.ENC_KEY_TRANSPORT, mc);
570 if (transportAlgorithm != null && !"".equals(transportAlgorithm)) {
571 algorithmSuite.addKeyWrapAlgorithm(transportAlgorithm);
572 }
573
574 reqData.setAlgorithmSuite(algorithmSuite);
575 }
576
577 protected void decodeEncryptionParameter(RequestData reqData)
578 throws WSSecurityException {
579 Object mc = reqData.getMsgContext();
580
581
582
583
584
585 String encKeyId = getString(WSHandlerConstants.ENC_KEY_ID, mc);
586 if (encKeyId != null) {
587 Integer id = (Integer) WSHandlerConstants.getKeyIdentifier(encKeyId);
588 if (id == null) {
589 throw new WSSecurityException(
590 "WSHandler: Encryption: unknown key identification"
591 );
592 }
593 int tmp = id.intValue();
594 reqData.setEncKeyId(tmp);
595 if (!(tmp == WSConstants.ISSUER_SERIAL
596 || tmp == WSConstants.X509_KEY_IDENTIFIER
597 || tmp == WSConstants.SKI_KEY_IDENTIFIER
598 || tmp == WSConstants.BST_DIRECT_REFERENCE
599 || tmp == WSConstants.EMBEDDED_KEYNAME
600 || tmp == WSConstants.THUMBPRINT_IDENTIFIER
601 || tmp == WSConstants.ENCRYPTED_KEY_SHA1_IDENTIFIER)) {
602 throw new WSSecurityException(
603 "WSHandler: Encryption: illegal key identification"
604 );
605 }
606 }
607 String encSymAlgo = getString(WSHandlerConstants.ENC_SYM_ALGO, mc);
608 reqData.setEncSymmAlgo(encSymAlgo);
609
610 String encKeyTransport =
611 getString(WSHandlerConstants.ENC_KEY_TRANSPORT, mc);
612 reqData.setEncKeyTransport(encKeyTransport);
613
614 String digestAlgo = getString(WSHandlerConstants.ENC_DIGEST_ALGO, mc);
615 reqData.setEncDigestAlgorithm(digestAlgo);
616
617 String encSymEncKey = getString(WSHandlerConstants.ENC_SYM_ENC_KEY, mc);
618 if (encSymEncKey != null) {
619 boolean encSymEndKeyBoolean = Boolean.parseBoolean(encSymEncKey);
620 reqData.setEncryptSymmetricEncryptionKey(encSymEndKeyBoolean);
621 }
622
623 String encUser = getString(WSHandlerConstants.ENCRYPTION_USER, mc);
624 if (encUser != null) {
625 reqData.setEncUser(encUser);
626 } else {
627 reqData.setEncUser(reqData.getUsername());
628 }
629 if (reqData.getEncryptSymmetricEncryptionKey() && reqData.getEncUser() == null) {
630 throw new WSSecurityException("WSHandler: Encryption: no username");
631 }
632
633
634
635
636
637 handleSpecialUser(reqData);
638
639 String encParts = getString(WSHandlerConstants.ENCRYPTION_PARTS, mc);
640 if (encParts != null) {
641 splitEncParts(encParts, reqData.getEncryptParts(), reqData);
642 }
643 }
644
645
646
647
648
649 public int decodeTimeToLive(RequestData reqData, boolean timestamp) {
650 String tag = WSHandlerConstants.TTL_TIMESTAMP;
651 if (!timestamp) {
652 tag = WSHandlerConstants.TTL_USERNAMETOKEN;
653 }
654 String ttl = getString(tag, reqData.getMsgContext());
655 int defaultTimeToLive = 300;
656 if (ttl != null) {
657 try {
658 int ttlI = Integer.parseInt(ttl);
659 if (ttlI < 0) {
660 return defaultTimeToLive;
661 }
662 return ttlI;
663 } catch (NumberFormatException e) {
664 return defaultTimeToLive;
665 }
666 }
667 return defaultTimeToLive;
668 }
669
670
671
672
673
674 protected int decodeFutureTimeToLive(RequestData reqData, boolean timestamp) {
675 String tag = WSHandlerConstants.TTL_FUTURE_TIMESTAMP;
676 if (!timestamp) {
677 tag = WSHandlerConstants.TTL_FUTURE_USERNAMETOKEN;
678 }
679 String ttl = getString(tag, reqData.getMsgContext());
680 int defaultFutureTimeToLive = 60;
681 if (ttl != null) {
682 try {
683 int ttlI = Integer.parseInt(ttl);
684 if (ttlI < 0) {
685 return defaultFutureTimeToLive;
686 }
687 return ttlI;
688 } catch (NumberFormatException e) {
689 return defaultFutureTimeToLive;
690 }
691 }
692 return defaultFutureTimeToLive;
693 }
694
695 protected boolean decodeBSPCompliance(RequestData reqData)
696 throws WSSecurityException {
697 return decodeBooleanConfigValue(
698 reqData, WSHandlerConstants.IS_BSP_COMPLIANT, true
699 );
700 }
701
702 protected String decodePasswordType(RequestData reqData) throws WSSecurityException {
703 String type = getString(WSHandlerConstants.PASSWORD_TYPE, reqData.getMsgContext());
704 if (type != null) {
705 if (WSConstants.PW_TEXT.equals(type)) {
706 return WSConstants.PASSWORD_TEXT;
707 } else if (WSConstants.PW_DIGEST.equals(type)) {
708 return WSConstants.PASSWORD_DIGEST;
709 }
710 }
711 return null;
712 }
713
714 protected boolean decodeMustUnderstand(RequestData reqData)
715 throws WSSecurityException {
716 return decodeBooleanConfigValue(
717 reqData, WSHandlerConstants.MUST_UNDERSTAND, true
718 );
719 }
720
721 protected boolean decodeEnableSignatureConfirmation(
722 RequestData reqData
723 ) throws WSSecurityException {
724 return decodeBooleanConfigValue(
725 reqData, WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION, false
726 );
727 }
728
729 protected boolean decodeTimestampPrecision(
730 RequestData reqData
731 ) throws WSSecurityException {
732 return decodeBooleanConfigValue(
733 reqData, WSHandlerConstants.TIMESTAMP_PRECISION, true
734 );
735 }
736
737 protected boolean decodeCustomPasswordTypes(
738 RequestData reqData
739 ) throws WSSecurityException {
740 return decodeBooleanConfigValue(
741 reqData, WSHandlerConstants.HANDLE_CUSTOM_PASSWORD_TYPES, false
742 );
743 }
744
745 protected boolean decodeAllowUsernameTokenNoPassword(
746 RequestData reqData
747 ) throws WSSecurityException {
748 return decodeBooleanConfigValue(
749 reqData, WSHandlerConstants.ALLOW_USERNAMETOKEN_NOPASSWORD, false
750 );
751 }
752
753 protected boolean decodeUseEncodedPasswords(RequestData reqData)
754 throws WSSecurityException {
755 return decodeBooleanConfigValue(
756 reqData, WSHandlerConstants.USE_ENCODED_PASSWORDS, false
757 );
758 }
759
760 protected boolean decodeNamespaceQualifiedPasswordTypes(RequestData reqData)
761 throws WSSecurityException {
762 return decodeBooleanConfigValue(
763 reqData, WSHandlerConstants.ALLOW_NAMESPACE_QUALIFIED_PASSWORD_TYPES, false
764 );
765 }
766
767 protected boolean decodeTimestampStrict(RequestData reqData)
768 throws WSSecurityException {
769 return decodeBooleanConfigValue(
770 reqData, WSHandlerConstants.TIMESTAMP_STRICT, true
771 );
772 }
773
774 protected boolean decodePasswordTypeStrict(RequestData reqData)
775 throws WSSecurityException {
776 return decodeBooleanConfigValue(
777 reqData, WSHandlerConstants.PASSWORD_TYPE_STRICT, false
778 );
779 }
780
781 protected boolean decodeUseSingleCertificate(RequestData reqData)
782 throws WSSecurityException {
783 return decodeBooleanConfigValue(
784 reqData, WSHandlerConstants.USE_SINGLE_CERTIFICATE, true
785 );
786 }
787
788 protected void decodeRequireSignedEncryptedDataElements(RequestData reqData)
789 throws WSSecurityException {
790 reqData.setRequireSignedEncryptedDataElements(decodeBooleanConfigValue(
791 reqData, WSHandlerConstants.REQUIRE_SIGNED_ENCRYPTED_DATA_ELEMENTS, false
792 ));
793 }
794
795 protected boolean decodeBooleanConfigValue(
796 RequestData reqData, String configTag, boolean defaultToTrue
797 ) throws WSSecurityException {
798
799 String value = getString(configTag, reqData.getMsgContext());
800
801 if (value == null) {
802 return defaultToTrue;
803 }
804 if ("0".equals(value) || "false".equals(value)) {
805 return false;
806 }
807 if ("1".equals(value) || "true".equals(value)) {
808 return true;
809 }
810
811 throw new WSSecurityException(
812 "WSHandler: illegal " + configTag + " parameter"
813 );
814 }
815
816
817
818
819
820
821
822
823 public Crypto loadSignatureCrypto(RequestData requestData) throws WSSecurityException {
824 return
825 loadCrypto(
826 WSHandlerConstants.SIG_PROP_FILE,
827 WSHandlerConstants.SIG_PROP_REF_ID,
828 requestData
829 );
830 }
831
832
833
834
835
836
837
838
839 protected Crypto loadDecryptionCrypto(RequestData requestData) throws WSSecurityException {
840 return
841 loadCrypto(
842 WSHandlerConstants.DEC_PROP_FILE,
843 WSHandlerConstants.DEC_PROP_REF_ID,
844 requestData
845 );
846 }
847
848
849
850
851
852
853
854
855 protected Crypto loadEncryptionCrypto(RequestData requestData) throws WSSecurityException {
856 return
857 loadCrypto(
858 WSHandlerConstants.ENC_PROP_FILE,
859 WSHandlerConstants.ENC_PROP_REF_ID,
860 requestData
861 );
862 }
863
864
865
866
867
868
869
870
871
872 protected Crypto loadCrypto(
873 String cryptoPropertyFile,
874 String cryptoPropertyRefId,
875 RequestData requestData
876 ) throws WSSecurityException {
877 Object mc = requestData.getMsgContext();
878 Crypto crypto = null;
879
880
881
882
883 String refId = getString(cryptoPropertyRefId, mc);
884 if (refId != null) {
885 crypto = cryptos.get(refId);
886 if (crypto == null) {
887 Object obj = getProperty(mc, refId);
888 if (obj instanceof Properties) {
889 crypto = CryptoFactory.getInstance((Properties)obj);
890 cryptos.put(refId, crypto);
891 } else if (obj instanceof Crypto) {
892 crypto = (Crypto)obj;
893 cryptos.put(refId, crypto);
894 }
895 }
896 }
897
898
899
900
901 if (crypto == null) {
902 String propFile = getString(cryptoPropertyFile, mc);
903 if (propFile != null) {
904 crypto = cryptos.get(propFile);
905 if (crypto == null) {
906 crypto = loadCryptoFromPropertiesFile(propFile, requestData);
907 cryptos.put(propFile, crypto);
908 }
909 }
910 }
911 return crypto;
912 }
913
914
915
916
917
918
919
920
921 protected Crypto loadCryptoFromPropertiesFile(
922 String propFilename,
923 RequestData reqData
924 ) throws WSSecurityException {
925 return
926 CryptoFactory.getInstance(
927 propFilename, this.getClassLoader(reqData.getMsgContext())
928 );
929 }
930
931
932
933
934
935
936
937
938
939
940
941
942 public CallbackHandler getCallbackHandler(
943 String callbackHandlerClass,
944 String callbackHandlerRef,
945 RequestData requestData
946 ) throws WSSecurityException {
947 Object mc = requestData.getMsgContext();
948 CallbackHandler cbHandler = (CallbackHandler) getOption(callbackHandlerRef);
949 if (cbHandler == null) {
950 cbHandler = (CallbackHandler) getProperty(mc, callbackHandlerRef);
951 }
952 if (cbHandler == null) {
953 String callback = getString(callbackHandlerClass, mc);
954 if (callback != null) {
955 cbHandler = loadCallbackHandler(callback, requestData);
956 }
957 }
958 return cbHandler;
959 }
960
961
962
963
964
965
966
967 public CallbackHandler getPasswordCallbackHandler(RequestData reqData)
968 throws WSSecurityException {
969 return
970 getCallbackHandler(
971 WSHandlerConstants.PW_CALLBACK_CLASS,
972 WSHandlerConstants.PW_CALLBACK_REF,
973 reqData
974 );
975 }
976
977
978
979
980
981
982
983
984 private CallbackHandler loadCallbackHandler(
985 String callbackHandlerClass,
986 RequestData requestData
987 ) throws WSSecurityException {
988
989 Class<? extends CallbackHandler> cbClass = null;
990 CallbackHandler cbHandler = null;
991 try {
992 cbClass =
993 Loader.loadClass(getClassLoader(requestData.getMsgContext()),
994 callbackHandlerClass,
995 CallbackHandler.class);
996 } catch (ClassNotFoundException e) {
997 throw new WSSecurityException(
998 "WSHandler: cannot load callback handler class: " + callbackHandlerClass, e
999 );
1000 }
1001 try {
1002 cbHandler = (CallbackHandler) cbClass.newInstance();
1003 } catch (Exception e) {
1004 throw new WSSecurityException(
1005 "WSHandler: cannot create instance of callback handler: " + callbackHandlerClass, e
1006 );
1007 }
1008 return cbHandler;
1009 }
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020 public WSPasswordCallback getPasswordCB(
1021 String username,
1022 int doAction,
1023 CallbackHandler callbackHandler,
1024 RequestData requestData
1025 ) throws WSSecurityException {
1026
1027 if (callbackHandler != null) {
1028 return performPasswordCallback(callbackHandler, username, doAction);
1029 } else {
1030
1031
1032
1033
1034 String password = getPassword(requestData.getMsgContext());
1035 if (password == null) {
1036 String err = "provided null or empty password";
1037 throw new WSSecurityException("WSHandler: application " + err);
1038 }
1039 WSPasswordCallback pwCb = constructPasswordCallback(username, doAction);
1040 pwCb.setPassword(password);
1041 return pwCb;
1042 }
1043 }
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053 private WSPasswordCallback performPasswordCallback(
1054 CallbackHandler cbHandler,
1055 String username,
1056 int doAction
1057 ) throws WSSecurityException {
1058
1059 WSPasswordCallback pwCb = constructPasswordCallback(username, doAction);
1060 Callback[] callbacks = new Callback[1];
1061 callbacks[0] = pwCb;
1062
1063
1064
1065 try {
1066 cbHandler.handle(callbacks);
1067 } catch (Exception e) {
1068 throw new WSSecurityException("WSHandler: password callback failed", e);
1069 }
1070 return pwCb;
1071 }
1072
1073
1074
1075
1076
1077
1078
1079
1080 private WSPasswordCallback constructPasswordCallback(
1081 String username,
1082 int doAction
1083 ) throws WSSecurityException {
1084
1085 int reason = WSPasswordCallback.UNKNOWN;
1086
1087 switch (doAction) {
1088 case WSConstants.UT:
1089 case WSConstants.UT_SIGN:
1090 reason = WSPasswordCallback.USERNAME_TOKEN;
1091 break;
1092 case WSConstants.SIGN:
1093 reason = WSPasswordCallback.SIGNATURE;
1094 break;
1095 case WSConstants.ENCR:
1096 reason = WSPasswordCallback.SECRET_KEY;
1097 break;
1098 }
1099 return new WSPasswordCallback(username, reason);
1100 }
1101
1102 private void splitEncParts(String tmpS, List<WSEncryptionPart> parts, RequestData reqData)
1103 throws WSSecurityException {
1104 WSEncryptionPart encPart = null;
1105 String[] rawParts = StringUtil.split(tmpS, ';');
1106
1107 for (int i = 0; i < rawParts.length; i++) {
1108 String[] partDef = StringUtil.split(rawParts[i], '}');
1109
1110 if (partDef.length == 1) {
1111 if (doDebug) {
1112 log.debug("single partDef: '" + partDef[0] + "'");
1113 }
1114 encPart =
1115 new WSEncryptionPart(partDef[0].trim(),
1116 reqData.getSoapConstants().getEnvelopeURI(),
1117 "Content");
1118 } else if (partDef.length == 3) {
1119 String mode = partDef[0].trim();
1120 if (mode.length() <= 1) {
1121 mode = "Content";
1122 } else {
1123 mode = mode.substring(1);
1124 }
1125 String nmSpace = partDef[1].trim();
1126 if (nmSpace.length() <= 1) {
1127 nmSpace = reqData.getSoapConstants().getEnvelopeURI();
1128 } else {
1129 nmSpace = nmSpace.substring(1);
1130 if (nmSpace.equals(WSConstants.NULL_NS)) {
1131 nmSpace = null;
1132 }
1133 }
1134 String element = partDef[2].trim();
1135 if (doDebug) {
1136 log.debug(
1137 "partDefs: '" + mode + "' ,'" + nmSpace + "' ,'" + element + "'"
1138 );
1139 }
1140 encPart = new WSEncryptionPart(element, nmSpace, mode);
1141 } else {
1142 throw new WSSecurityException("WSHandler: wrong part definition: " + tmpS);
1143 }
1144 parts.add(encPart);
1145 }
1146 }
1147
1148 @SuppressWarnings("unchecked")
1149 private void handleSpecialUser(RequestData reqData) {
1150 if (!WSHandlerConstants.USE_REQ_SIG_CERT.equals(reqData.getEncUser())) {
1151 return;
1152 }
1153 List<WSHandlerResult> results =
1154 (List<WSHandlerResult>) getProperty(
1155 reqData.getMsgContext(), WSHandlerConstants.RECV_RESULTS
1156 );
1157 if (results == null) {
1158 return;
1159 }
1160
1161
1162
1163
1164 for (WSHandlerResult rResult : results) {
1165 String hActor = rResult.getActor();
1166 if (!WSSecurityUtil.isActorEqual(reqData.getActor(), hActor)) {
1167 continue;
1168 }
1169 List<WSSecurityEngineResult> wsSecEngineResults = rResult.getResults();
1170
1171
1172
1173
1174
1175 for (WSSecurityEngineResult wser : wsSecEngineResults) {
1176 int wserAction =
1177 ((java.lang.Integer)wser.get(WSSecurityEngineResult.TAG_ACTION)).intValue();
1178 if (wserAction == WSConstants.SIGN) {
1179 X509Certificate cert =
1180 (X509Certificate)wser.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
1181 reqData.setEncCert(cert);
1182 return;
1183 }
1184 }
1185 }
1186 }
1187
1188 protected void decodeSignatureParameter2(RequestData reqData)
1189 throws WSSecurityException {
1190 if (reqData.getSigCrypto() == null) {
1191 reqData.setSigCrypto(loadSignatureCrypto(reqData));
1192 }
1193 boolean enableRevocation =
1194 decodeBooleanConfigValue(
1195 reqData, WSHandlerConstants.ENABLE_REVOCATION, false
1196 );
1197 reqData.setEnableRevocation(enableRevocation);
1198
1199 String certConstraints =
1200 getString(WSHandlerConstants.SIG_SUBJECT_CERT_CONSTRAINTS, reqData.getMsgContext());
1201 if (certConstraints != null) {
1202 String[] certConstraintsList = certConstraints.split(",");
1203 if (certConstraintsList != null) {
1204 Collection<Pattern> subjectCertConstraints =
1205 new ArrayList<Pattern>(certConstraintsList.length);
1206 for (String certConstraint : certConstraintsList) {
1207 try {
1208 subjectCertConstraints.add(Pattern.compile(certConstraint.trim()));
1209 } catch (PatternSyntaxException ex) {
1210 log.debug(ex.getMessage(), ex);
1211 throw new WSSecurityException(ex.getMessage(), ex);
1212 }
1213 }
1214 reqData.setSubjectCertConstraints(subjectCertConstraints);
1215 }
1216 }
1217 }
1218
1219
1220
1221
1222
1223 protected void decodeDecryptionParameter(RequestData reqData)
1224 throws WSSecurityException {
1225 if (reqData.getDecCrypto() == null) {
1226 reqData.setDecCrypto(loadDecryptionCrypto(reqData));
1227 }
1228 }
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239 public String getString(String key, Object mc) {
1240 if (key == null) {
1241 throw new IllegalArgumentException("Key cannot be null");
1242 }
1243 String s = getStringOption(key);
1244 if (s != null) {
1245 return s;
1246 }
1247 if (mc == null) {
1248 throw new IllegalArgumentException("Message context cannot be null");
1249 }
1250 return (String) getProperty(mc, key);
1251 }
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261 public String getStringOption(String key) {
1262 Object o = getOption(key);
1263 if (o instanceof String){
1264 return (String) o;
1265 } else {
1266 return null;
1267 }
1268 }
1269
1270
1271
1272
1273
1274
1275 public ClassLoader getClassLoader(Object msgCtx) {
1276 try {
1277 return Loader.getTCL();
1278 } catch (Exception ex) {
1279 return null;
1280 }
1281 }
1282
1283 public abstract Object getOption(String key);
1284 public abstract Object getProperty(Object msgContext, String key);
1285
1286 public abstract void setProperty(Object msgContext, String key,
1287 Object value);
1288
1289
1290 public abstract String getPassword(Object msgContext);
1291
1292 public abstract void setPassword(Object msgContext, String password);
1293 }