View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.wss4j.stax.setup;
20  
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.Collections;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Properties;
27  import java.util.regex.Pattern;
28  import java.util.regex.PatternSyntaxException;
29  
30  import javax.security.auth.callback.CallbackHandler;
31  import javax.xml.namespace.QName;
32  
33  import org.apache.wss4j.common.ConfigurationConstants;
34  import org.apache.wss4j.common.cache.ReplayCache;
35  import org.apache.wss4j.common.crypto.Crypto;
36  import org.apache.wss4j.common.crypto.CryptoFactory;
37  import org.apache.wss4j.common.crypto.JasyptPasswordEncryptor;
38  import org.apache.wss4j.common.crypto.PasswordEncryptor;
39  import org.apache.wss4j.common.ext.WSSecurityException;
40  import org.apache.wss4j.common.util.Loader;
41  import org.apache.wss4j.stax.ext.WSSConstants;
42  import org.apache.wss4j.stax.ext.WSSConstants.UsernameTokenPasswordType;
43  import org.apache.wss4j.stax.ext.WSSSecurityProperties;
44  import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
45  import org.apache.wss4j.stax.validate.Validator;
46  import org.apache.xml.security.stax.ext.SecurePart;
47  import org.apache.xml.security.stax.ext.XMLSecurityConstants.Action;
48  
49  /**
50   * This utility class converts between a Map<String, Object> and a WSSSecurityProperties class
51   */
52  public final class ConfigurationConverter {
53  
54      private static final org.slf4j.Logger LOG =
55          org.slf4j.LoggerFactory.getLogger(ConfigurationConverter.class);
56  
57      private ConfigurationConverter() {
58          // complete
59      }
60  
61      public static WSSSecurityProperties convert(Map<String, Object> config) {
62          WSSSecurityProperties properties = new WSSSecurityProperties();
63  
64          if (config == null) {
65              return properties;
66          }
67  
68          parseActions(config, properties);
69          parseUserProperties(config, properties);
70          parseCallback(config, properties);
71          parseCrypto(config, properties);
72          parseBooleanProperties(config, properties);
73          parseNonBooleanProperties(config, properties);
74  
75          return properties;
76      }
77  
78      public static void parseActions(
79          Map<String, Object> config,
80          WSSSecurityProperties properties
81      ) {
82          String action = getString(ConfigurationConstants.ACTION, config);
83  
84          String actionToParse = action;
85          if (actionToParse == null) {
86              return;
87          }
88          actionToParse = actionToParse.trim();
89          if (actionToParse.length() == 0) {
90              return;
91          }
92          String[] single = actionToParse.split("\\s");
93          List<Action> actions = new ArrayList<>();
94          for (int i = 0; i < single.length; i++) {
95              if (single[i].equals(ConfigurationConstants.USERNAME_TOKEN)) {
96                  actions.add(WSSConstants.USERNAMETOKEN);
97              } else if (single[i].equals(ConfigurationConstants.SIGNATURE)) {
98                  actions.add(WSSConstants.SIGNATURE);
99              } else if (single[i].equals(ConfigurationConstants.ENCRYPT)
100                 || single[i].equals(ConfigurationConstants.ENCRYPTION)) {
101                 actions.add(WSSConstants.ENCRYPTION);
102             } else if (single[i].equals(ConfigurationConstants.SAML_TOKEN_UNSIGNED)) {
103                 actions.add(WSSConstants.SAML_TOKEN_UNSIGNED);
104             } else if (single[i].equals(ConfigurationConstants.SAML_TOKEN_SIGNED)) {
105                 actions.add(WSSConstants.SAML_TOKEN_SIGNED);
106             } else if (single[i].equals(ConfigurationConstants.TIMESTAMP)) {
107                 actions.add(WSSConstants.TIMESTAMP);
108             } else if (single[i].equals(ConfigurationConstants.USERNAME_TOKEN_SIGNATURE)) {
109                 actions.add(WSSConstants.USERNAMETOKEN_SIGNED);
110             } else if (single[i].equals(ConfigurationConstants.SIGNATURE_DERIVED)) {
111                 actions.add(WSSConstants.SIGNATURE_WITH_DERIVED_KEY);
112             } else if (single[i].equals(ConfigurationConstants.ENCRYPT_DERIVED)
113                 || single[i].equals(ConfigurationConstants.ENCRYPTION_DERIVED)) {
114                 actions.add(WSSConstants.ENCRYPTION_WITH_DERIVED_KEY);
115             } else if (single[i].equals(ConfigurationConstants.SIGNATURE_WITH_KERBEROS_TOKEN)) {
116                 actions.add(WSSConstants.SIGNATURE_WITH_KERBEROS_TOKEN);
117             } else if (single[i].equals(ConfigurationConstants.ENCRYPT_WITH_KERBEROS_TOKEN)
118                 || single[i].equals(ConfigurationConstants.ENCRYPTION_WITH_KERBEROS_TOKEN)) {
119                 actions.add(WSSConstants.ENCRYPTION_WITH_KERBEROS_TOKEN);
120             } else if (single[i].equals(ConfigurationConstants.KERBEROS_TOKEN)) {
121                 actions.add(WSSConstants.KERBEROS_TOKEN);
122             } else if (single[i].equals(ConfigurationConstants.CUSTOM_TOKEN)) {
123                 actions.add(WSSConstants.CUSTOM_TOKEN);
124             } /* else if (single[i].equals(ConfigurationConstants.USERNAME_TOKEN_NO_PASSWORD)) {
125                 actions.add(WSConstants.UT_NOPASSWORD);
126             } */
127         }
128 
129         boolean sigConf =
130                 decodeBooleanConfigValue(ConfigurationConstants.ENABLE_SIGNATURE_CONFIRMATION, false, config);
131         if (sigConf) {
132             actions.add(WSSConstants.SIGNATURE_CONFIRMATION);
133         }
134 
135         properties.setActions(actions);
136     }
137 
138     public static void parseUserProperties(
139         Map<String, Object> config,
140         WSSSecurityProperties properties
141     ) {
142         String user = getString(ConfigurationConstants.USER, config);
143         properties.setTokenUser(user);
144 
145         String actor = getString(ConfigurationConstants.ACTOR, config);
146         properties.setActor(actor);
147 
148         String encUser = getString(ConfigurationConstants.ENCRYPTION_USER, config);
149         if (encUser == null) {
150             encUser = user;
151         }
152         properties.setEncryptionUser(encUser);
153         if (ConfigurationConstants.USE_REQ_SIG_CERT.equals(encUser)) {
154             properties.setUseReqSigCertForEncryption(true);
155         }
156 
157         String sigUser = getString(ConfigurationConstants.SIGNATURE_USER, config);
158         if (sigUser == null) {
159             sigUser = user;
160         }
161         properties.setSignatureUser(sigUser);
162     }
163 
164     public static void parseCrypto(
165         Map<String, Object> config,
166         WSSSecurityProperties properties
167     ) {
168         Object passwordEncryptorObj =
169             config.get(ConfigurationConstants.PASSWORD_ENCRYPTOR_INSTANCE);
170         PasswordEncryptor passwordEncryptor = null;
171         if (passwordEncryptorObj instanceof PasswordEncryptor) {
172             passwordEncryptor = (PasswordEncryptor)passwordEncryptorObj;
173         }
174         if (passwordEncryptor == null) {
175             CallbackHandler callbackHandler = properties.getCallbackHandler();
176             if (callbackHandler != null) {
177                 passwordEncryptor = new JasyptPasswordEncryptor(callbackHandler);
178             }
179         }
180 
181         String sigPropRef = getString(ConfigurationConstants.SIG_PROP_REF_ID, config);
182         boolean foundSigRef = false;
183         if (sigPropRef != null) {
184             Object sigRef = config.get(sigPropRef);
185             if (sigRef instanceof Crypto) {
186                 foundSigRef = true;
187                 properties.setSignatureCrypto((Crypto)sigRef);
188             } else if (sigRef instanceof Properties) {
189                 foundSigRef = true;
190                 properties.setSignatureCryptoProperties((Properties)sigRef, passwordEncryptor);
191             }
192             if (foundSigRef && properties.getSignatureUser() == null) {
193                 properties.setSignatureUser(getDefaultX509Identifier(properties, true));
194             }
195         }
196 
197         if (!foundSigRef) {
198             String sigPropFile = getString(ConfigurationConstants.SIG_PROP_FILE, config);
199             if (sigPropFile != null) {
200                 try {
201                     Properties sigProperties =
202                         CryptoFactory.getProperties(sigPropFile, getClassLoader());
203                     properties.setSignatureCryptoProperties(sigProperties, passwordEncryptor);
204                     if (properties.getSignatureUser() == null) {
205                         properties.setSignatureUser(getDefaultX509Identifier(properties, true));
206                     }
207                 } catch (WSSecurityException e) {
208                     LOG.error(e.getMessage(), e);
209                 }
210             }
211         }
212 
213         String sigVerPropRef = getString(ConfigurationConstants.SIG_VER_PROP_REF_ID, config);
214         boolean foundSigVerRef = false;
215         if (sigVerPropRef != null) {
216             Object sigVerRef = config.get(sigVerPropRef);
217             if (sigVerRef instanceof Crypto) {
218                 foundSigVerRef = true;
219                 properties.setSignatureVerificationCrypto((Crypto)sigVerRef);
220             } else if (sigVerRef instanceof Properties) {
221                 foundSigVerRef = true;
222                 properties.setSignatureVerificationCryptoProperties((Properties)sigVerRef, passwordEncryptor);
223             }
224         }
225 
226         if (!foundSigVerRef) {
227             String sigPropFile = getString(ConfigurationConstants.SIG_VER_PROP_FILE, config);
228             if (sigPropFile != null) {
229                 try {
230                     Properties sigProperties =
231                         CryptoFactory.getProperties(sigPropFile, getClassLoader());
232                     properties.setSignatureVerificationCryptoProperties(sigProperties, passwordEncryptor);
233                 } catch (WSSecurityException e) {
234                     LOG.error(e.getMessage(), e);
235                 }
236             }
237         }
238 
239         String encPropRef = getString(ConfigurationConstants.ENC_PROP_REF_ID, config);
240         boolean foundEncRef = false;
241         if (encPropRef != null) {
242             Object encRef = config.get(encPropRef);
243             if (encRef instanceof Crypto) {
244                 foundEncRef = true;
245                 properties.setEncryptionCrypto((Crypto)encRef);
246             } else if (encRef instanceof Properties) {
247                 foundEncRef = true;
248                 properties.setEncryptionCryptoProperties((Properties)encRef, passwordEncryptor);
249             }
250         }
251 
252         if (!foundEncRef) {
253             String encPropFile = getString(ConfigurationConstants.ENC_PROP_FILE, config);
254             if (encPropFile != null) {
255                 try {
256                     Properties encProperties =
257                         CryptoFactory.getProperties(encPropFile, getClassLoader());
258                     properties.setEncryptionCryptoProperties(encProperties, passwordEncryptor);
259                 } catch (WSSecurityException e) {
260                     LOG.error(e.getMessage(), e);
261                 }
262             }
263         }
264 
265         String decPropRef = getString(ConfigurationConstants.DEC_PROP_REF_ID, config);
266         boolean foundDecRef = false;
267         if (decPropRef != null) {
268             Object decRef = config.get(decPropRef);
269             if (decRef instanceof Crypto) {
270                 foundDecRef = true;
271                 properties.setDecryptionCrypto((Crypto)decRef);
272             } else if (decRef instanceof Properties) {
273                 foundDecRef = true;
274                 properties.setDecryptionCryptoProperties((Properties)decRef, passwordEncryptor);
275             }
276         }
277 
278         if (!foundDecRef) {
279             String encPropFile = getString(ConfigurationConstants.DEC_PROP_FILE, config);
280             if (encPropFile != null) {
281                 try {
282                     Properties encProperties =
283                         CryptoFactory.getProperties(encPropFile, getClassLoader());
284                     properties.setDecryptionCryptoProperties(encProperties, passwordEncryptor);
285                 } catch (WSSecurityException e) {
286                     LOG.error(e.getMessage(), e);
287                 }
288             }
289         }
290     }
291 
292     public static String getDefaultX509Identifier(
293         WSSSecurityProperties properties, boolean signature
294     ) {
295         try {
296             Crypto crypto = null;
297             if (signature) {
298                 crypto = properties.getSignatureCrypto();
299             } else {
300                 crypto = properties.getEncryptionCrypto();
301             }
302             if (crypto != null) {
303                 return crypto.getDefaultX509Identifier();
304             }
305         } catch (WSSecurityException e) {
306             LOG.debug(e.getMessage(), e);
307         }
308         return null;
309     }
310 
311     public static void parseCallback(
312         Map<String, Object> config,
313         WSSSecurityProperties properties
314     ) {
315         Object pwPropRef = config.get(ConfigurationConstants.PW_CALLBACK_REF);
316         if (pwPropRef instanceof CallbackHandler) {
317             properties.setCallbackHandler((CallbackHandler)pwPropRef);
318         } else {
319             String pwCallback = getString(ConfigurationConstants.PW_CALLBACK_CLASS, config);
320             if (pwCallback != null) {
321                 try {
322                     CallbackHandler pwCallbackHandler = loadCallbackHandler(pwCallback);
323                     properties.setCallbackHandler(pwCallbackHandler);
324                 } catch (WSSecurityException e) {
325                     LOG.error(e.getMessage(), e);
326                 }
327             }
328         }
329 
330         Object samlPropRef = config.get(ConfigurationConstants.SAML_CALLBACK_REF);
331         if (samlPropRef instanceof CallbackHandler) {
332             properties.setSamlCallbackHandler((CallbackHandler)samlPropRef);
333         } else {
334             String samlCallback = getString(ConfigurationConstants.SAML_CALLBACK_CLASS, config);
335             if (samlCallback != null) {
336                 try {
337                     CallbackHandler samlCallbackHandler = loadCallbackHandler(samlCallback);
338                     properties.setSamlCallbackHandler(samlCallbackHandler);
339                 } catch (WSSecurityException e) {
340                     LOG.error(e.getMessage(), e);
341                 }
342             }
343         }
344     }
345 
346     /**
347      * Load a CallbackHandler instance.
348      * @param callbackHandlerClass The class name of the CallbackHandler instance
349      * @return a CallbackHandler instance
350      * @throws WSSecurityException
351      */
352     public static CallbackHandler loadCallbackHandler(
353         String callbackHandlerClass
354     ) throws WSSecurityException {
355 
356         Class<? extends CallbackHandler> cbClass = null;
357         CallbackHandler cbHandler = null;
358         try {
359             cbClass =
360                 Loader.loadClass(getClassLoader(),
361                                  callbackHandlerClass,
362                                  CallbackHandler.class);
363         } catch (ClassNotFoundException e) {
364             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e,
365                     "empty",
366                     new Object[] {"WSHandler: cannot load callback handler class: "
367                     + callbackHandlerClass}
368             );
369         }
370         try {
371             cbHandler = cbClass.getDeclaredConstructor().newInstance();
372         } catch (Exception e) {
373             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e,
374                     "empty",
375                     new Object[] {"WSHandler: cannot create instance of callback handler: "
376                     + callbackHandlerClass}
377             );
378         }
379         return cbHandler;
380     }
381 
382     private static ClassLoader getClassLoader() {
383         try {
384             return Loader.getTCL();
385         } catch (Exception ex) {
386             return null;
387         }
388     }
389 
390     public static void parseBooleanProperties(
391         Map<String, Object> config,
392         WSSSecurityProperties properties
393     ) {
394         //outbound sigConf is configured as an Action, see parseActions()
395         boolean sigConf =
396             decodeBooleanConfigValue(ConfigurationConstants.ENABLE_SIGNATURE_CONFIRMATION, false, config);
397         properties.setEnableSignatureConfirmationVerification(sigConf);
398 
399         boolean mustUnderstand =
400             decodeBooleanConfigValue(ConfigurationConstants.MUST_UNDERSTAND, true, config);
401         properties.setMustUnderstand(mustUnderstand);
402 
403         boolean bspCompliant =
404             decodeBooleanConfigValue(ConfigurationConstants.IS_BSP_COMPLIANT, true, config);
405         properties.setDisableBSPEnforcement(!bspCompliant);
406 
407         boolean inclPrefixes =
408             decodeBooleanConfigValue(ConfigurationConstants.ADD_INCLUSIVE_PREFIXES, true, config);
409         properties.setAddExcC14NInclusivePrefixes(inclPrefixes);
410 
411         boolean nonce =
412             decodeBooleanConfigValue(ConfigurationConstants.ADD_USERNAMETOKEN_NONCE, false, config);
413         properties.setAddUsernameTokenNonce(nonce);
414 
415         boolean created =
416             decodeBooleanConfigValue(ConfigurationConstants.ADD_USERNAMETOKEN_CREATED, false, config);
417         properties.setAddUsernameTokenCreated(created);
418 
419         boolean customPasswordTypes =
420             decodeBooleanConfigValue(ConfigurationConstants.HANDLE_CUSTOM_PASSWORD_TYPES, false, config);
421         properties.setHandleCustomPasswordTypes(customPasswordTypes);
422 
423         boolean allowNoPassword =
424             decodeBooleanConfigValue(ConfigurationConstants.ALLOW_USERNAMETOKEN_NOPASSWORD, false, config);
425         properties.setAllowUsernameTokenNoPassword(allowNoPassword);
426 
427         boolean enableRevocation =
428             decodeBooleanConfigValue(ConfigurationConstants.ENABLE_REVOCATION, false, config);
429         properties.setEnableRevocation(enableRevocation);
430 
431         boolean singleCert =
432             decodeBooleanConfigValue(ConfigurationConstants.USE_SINGLE_CERTIFICATE, true, config);
433         properties.setUseSingleCert(singleCert);
434 
435         boolean derivedKeyMAC =
436             decodeBooleanConfigValue(ConfigurationConstants.USE_DERIVED_KEY_FOR_MAC, true, config);
437         properties.setUseDerivedKeyForMAC(derivedKeyMAC);
438 
439         boolean timestampStrict =
440             decodeBooleanConfigValue(ConfigurationConstants.TIMESTAMP_STRICT, true, config);
441         properties.setStrictTimestampCheck(timestampStrict);
442 
443         boolean allowRSA15 =
444             decodeBooleanConfigValue(ConfigurationConstants.ALLOW_RSA15_KEY_TRANSPORT_ALGORITHM, false, config);
445         properties.setAllowRSA15KeyTransportAlgorithm(allowRSA15);
446 
447         boolean validateSamlSubjectConf =
448             decodeBooleanConfigValue(ConfigurationConstants.VALIDATE_SAML_SUBJECT_CONFIRMATION, true, config);
449         properties.setValidateSamlSubjectConfirmation(validateSamlSubjectConf);
450 
451         boolean includeSignatureToken =
452             decodeBooleanConfigValue(ConfigurationConstants.INCLUDE_SIGNATURE_TOKEN, false, config);
453         properties.setIncludeSignatureToken(includeSignatureToken);
454 
455         boolean includeEncryptionToken =
456             decodeBooleanConfigValue(ConfigurationConstants.INCLUDE_ENCRYPTION_TOKEN, false, config);
457         properties.setIncludeEncryptionToken(includeEncryptionToken);
458 
459         boolean encryptSymmetricEncryptionKey =
460             decodeBooleanConfigValue(ConfigurationConstants.ENC_SYM_ENC_KEY, true, config);
461         properties.setEncryptSymmetricEncryptionKey(encryptSymmetricEncryptionKey);
462 
463         boolean use200512Namespace =
464             decodeBooleanConfigValue(ConfigurationConstants.USE_2005_12_NAMESPACE, true, config);
465         properties.setUse200512Namespace(use200512Namespace);
466 
467         boolean requireTimestampExpires =
468             decodeBooleanConfigValue(ConfigurationConstants.REQUIRE_TIMESTAMP_EXPIRES, false, config);
469         properties.setRequireTimestampExpires(requireTimestampExpires);
470     }
471 
472     public static void parseNonBooleanProperties(
473         Map<String, Object> config,
474         WSSSecurityProperties properties
475     ) {
476         String pwType = getString(ConfigurationConstants.PASSWORD_TYPE, config);
477         if ("PasswordDigest".equals(pwType)) {
478             properties.setUsernameTokenPasswordType(UsernameTokenPasswordType.PASSWORD_DIGEST);
479         } else if ("PasswordText".equals(pwType)) {
480             properties.setUsernameTokenPasswordType(UsernameTokenPasswordType.PASSWORD_TEXT);
481         } else if ("PasswordNone".equals(pwType)) {
482             properties.setUsernameTokenPasswordType(UsernameTokenPasswordType.PASSWORD_NONE);
483         }
484 
485         String signatureKeyIdentifier = getString(ConfigurationConstants.SIG_KEY_ID, config);
486         WSSecurityTokenConstants.KeyIdentifier convSigKeyIdentifier =
487             convertKeyIdentifier(signatureKeyIdentifier);
488         if (convSigKeyIdentifier != null) {
489             properties.setSignatureKeyIdentifier(convSigKeyIdentifier);
490         }
491 
492         String sigAlgo = getString(ConfigurationConstants.SIG_ALGO, config);
493         properties.setSignatureAlgorithm(sigAlgo);
494 
495         String sigDigestAlgo = getString(ConfigurationConstants.SIG_DIGEST_ALGO, config);
496         properties.setSignatureDigestAlgorithm(sigDigestAlgo);
497 
498         String sigC14nAlgo = getString(ConfigurationConstants.SIG_C14N_ALGO, config);
499         properties.setSignatureCanonicalizationAlgorithm(sigC14nAlgo);
500 
501         Object sigParts = config.get(ConfigurationConstants.SIGNATURE_PARTS);
502         configureParts(sigParts, properties, sigDigestAlgo, true, true);
503 
504         sigParts = config.get(ConfigurationConstants.OPTIONAL_SIGNATURE_PARTS);
505         configureParts(sigParts, properties, sigDigestAlgo, false, true);
506 
507         String iterations = getString(ConfigurationConstants.DERIVED_KEY_ITERATIONS, config);
508         if (iterations != null) {
509             int iIterations = Integer.parseInt(iterations);
510             properties.setDerivedKeyIterations(iIterations);
511         }
512 
513         String encKeyIdentifier = getString(ConfigurationConstants.ENC_KEY_ID, config);
514         WSSecurityTokenConstants.KeyIdentifier convEncKeyIdentifier =
515             convertKeyIdentifier(encKeyIdentifier);
516         if (convEncKeyIdentifier != null) {
517             properties.setEncryptionKeyIdentifier(convEncKeyIdentifier);
518         }
519 
520         Object encParts = config.get(ConfigurationConstants.ENCRYPTION_PARTS);
521         configureParts(encParts, properties, null, true, false);
522 
523         encParts = config.get(ConfigurationConstants.OPTIONAL_ENCRYPTION_PARTS);
524         configureParts(encParts, properties, null, false, false);
525 
526         String encSymcAlgo = getString(ConfigurationConstants.ENC_SYM_ALGO, config);
527         properties.setEncryptionSymAlgorithm(encSymcAlgo);
528 
529         String encKeyTransport = getString(ConfigurationConstants.ENC_KEY_TRANSPORT, config);
530         properties.setEncryptionKeyTransportAlgorithm(encKeyTransport);
531 
532         String encDigestAlgo = getString(ConfigurationConstants.ENC_DIGEST_ALGO, config);
533         properties.setEncryptionKeyTransportDigestAlgorithm(encDigestAlgo);
534 
535         String encMGFAlgo = getString(ConfigurationConstants.ENC_MGF_ALGO, config);
536         properties.setEncryptionKeyTransportMGFAlgorithm(encMGFAlgo);
537 
538         // Subject Cert Constraints
539         String certConstraints =
540             getString(ConfigurationConstants.SIG_SUBJECT_CERT_CONSTRAINTS, config);
541         if (certConstraints != null) {
542             String certConstraintsSeparator =
543                 getString(ConfigurationConstants.SIG_CERT_CONSTRAINTS_SEPARATOR, config);
544             if (certConstraintsSeparator == null || certConstraintsSeparator.isEmpty()) {
545                 certConstraintsSeparator = ",";
546             }
547             Collection<Pattern> subjectCertConstraints =
548                 getCertConstraints(certConstraints, certConstraintsSeparator);
549             properties.setSubjectCertConstraints(subjectCertConstraints);
550         }
551         // Subject Cert Constraints
552         String issuerCertConstraintsString =
553             getString(ConfigurationConstants.SIG_ISSUER_CERT_CONSTRAINTS, config);
554         if (issuerCertConstraintsString != null) {
555             String certConstraintsSeparator =
556                 getString(ConfigurationConstants.SIG_CERT_CONSTRAINTS_SEPARATOR, config);
557             if (certConstraintsSeparator == null || certConstraintsSeparator.isEmpty()) {
558                 certConstraintsSeparator = ",";
559             }
560             Collection<Pattern> issuerCertConstraints =
561                 getCertConstraints(certConstraints, certConstraintsSeparator);
562             properties.setIssuerDNConstraints(issuerCertConstraints);
563         }
564 
565         properties.setUtTTL(decodeTimeToLive(config, false));
566         properties.setUtFutureTTL(decodeFutureTimeToLive(config, false));
567         properties.setTimestampTTL(decodeTimeToLive(config, true));
568         properties.setTimeStampFutureTTL(decodeFutureTimeToLive(config, true));
569 
570         @SuppressWarnings("unchecked")
571         final Map<QName, Validator> validatorMap =
572             (Map<QName, Validator>)config.get(ConfigurationConstants.VALIDATOR_MAP);
573         if (validatorMap != null) {
574             for (Map.Entry<QName, Validator> entry : validatorMap.entrySet()) {
575                 properties.addValidator(entry.getKey(), entry.getValue());
576             }
577         }
578 
579         ReplayCache nonceCache =    //NOPMD
580             (ReplayCache)config.get(ConfigurationConstants.NONCE_CACHE_INSTANCE);
581         if (nonceCache != null) {
582             properties.setNonceReplayCache(nonceCache);
583         }
584 
585         ReplayCache timestampCache = //NOPMD
586             (ReplayCache)config.get(ConfigurationConstants.TIMESTAMP_CACHE_INSTANCE);
587         if (timestampCache != null) {
588             properties.setTimestampReplayCache(timestampCache);
589         }
590 
591         ReplayCache samlOneTimeUseCache = //NOPMD
592             (ReplayCache)config.get(ConfigurationConstants.SAML_ONE_TIME_USE_CACHE_INSTANCE);
593         if (samlOneTimeUseCache != null) {
594             properties.setSamlOneTimeUseReplayCache(samlOneTimeUseCache);
595         }
596 
597         String derivedSignatureKeyLength = getString(ConfigurationConstants.DERIVED_SIGNATURE_KEY_LENGTH, config);
598         if (derivedSignatureKeyLength != null) {
599             int sigLength = Integer.parseInt(derivedSignatureKeyLength);
600             properties.setDerivedSignatureKeyLength(sigLength);
601         }
602 
603         String derivedEncryptionKeyLength = getString(ConfigurationConstants.DERIVED_ENCRYPTION_KEY_LENGTH, config);
604         if (derivedEncryptionKeyLength != null) {
605             int encLength = Integer.parseInt(derivedEncryptionKeyLength);
606             properties.setDerivedEncryptionKeyLength(encLength);
607         }
608 
609         String derivedTokenReference = getString(ConfigurationConstants.DERIVED_TOKEN_REFERENCE, config);
610         WSSConstants.DerivedKeyTokenReference convertedDerivedTokenReference =
611             convertDerivedReference(derivedTokenReference);
612         if (convertedDerivedTokenReference != null) {
613             properties.setDerivedKeyTokenReference(convertedDerivedTokenReference);
614         }
615 
616         String derivedKeyIdentifier = getString(ConfigurationConstants.DERIVED_TOKEN_KEY_ID, config);
617         WSSecurityTokenConstants.KeyIdentifier convertedDerivedKeyIdentifier =
618             convertKeyIdentifier(derivedKeyIdentifier);
619         if (convertedDerivedKeyIdentifier != null) {
620             properties.setDerivedKeyKeyIdentifier(convertedDerivedKeyIdentifier);
621         }
622     }
623 
624     private static Collection<Pattern> getCertConstraints(String certConstraints, String certConstraintsSeparator) {
625         String[] certConstraintsList = certConstraints.split(certConstraintsSeparator);
626         if (certConstraintsList != null && certConstraintsList.length > 0) {
627             Collection<Pattern> certConstraintsCollection =
628                 new ArrayList<>(certConstraintsList.length);
629             for (String certConstraint : certConstraintsList) {
630                 try {
631                     certConstraintsCollection.add(Pattern.compile(certConstraint.trim()));
632                 } catch (PatternSyntaxException ex) {
633                     LOG.error(ex.getMessage(), ex);
634                 }
635             }
636 
637             return certConstraintsCollection;
638         }
639         return Collections.emptyList();
640     }
641 
642     private static void configureParts(Object secureParts, WSSSecurityProperties properties,
643                                        String digestAlgo, boolean required, boolean signature) {
644         if (secureParts != null) {
645             if (secureParts instanceof String) {
646                 List<SecurePart> parts = new ArrayList<>();
647                 splitEncParts((String)secureParts, parts, WSSConstants.NS_SOAP11);
648                 for (SecurePart part : parts) {
649                     part.setRequired(required);
650                     if (signature) {
651                         part.setDigestMethod(digestAlgo);
652                         properties.addSignaturePart(part);
653                     } else {
654                         properties.addEncryptionPart(part);
655                     }
656                 }
657             } else if (secureParts instanceof List<?>) {
658                 List<?> sigPartsList = (List<?>)secureParts;
659                 for (Object obj : sigPartsList) {
660                     if (obj instanceof SecurePart) {
661                         SecurePart securePart = (SecurePart)obj;
662                         securePart.setRequired(required);
663                         if (signature) {
664                             securePart.setDigestMethod(digestAlgo);
665                             properties.addSignaturePart(securePart);
666                         } else {
667                             properties.addEncryptionPart(securePart);
668                         }
669                     }
670                 }
671             }
672         }
673     }
674 
675     public static WSSConstants.DerivedKeyTokenReference convertDerivedReference(String derivedTokenReference) {
676         if ("EncryptedKey".equals(derivedTokenReference)) {
677            return WSSConstants.DerivedKeyTokenReference.EncryptedKey;
678         } else if ("DirectReference".equals(derivedTokenReference)) {
679             return WSSConstants.DerivedKeyTokenReference.DirectReference;
680         } else if ("SecurityContextToken".equals(derivedTokenReference)) {
681             return WSSConstants.DerivedKeyTokenReference.SecurityContextToken;
682         }
683         return null;
684     }
685 
686     public static WSSecurityTokenConstants.KeyIdentifier convertKeyIdentifier(String keyIdentifier) {
687         if ("IssuerSerial".equals(keyIdentifier)) {
688            return WSSecurityTokenConstants.KeyIdentifier_IssuerSerial;
689         } else if ("DirectReference".equals(keyIdentifier)) {
690             return WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE;
691         } else if ("X509KeyIdentifier".equals(keyIdentifier)) {
692             return WSSecurityTokenConstants.KeyIdentifier_X509KeyIdentifier;
693         } else if ("Thumbprint".equals(keyIdentifier)) {
694             return WSSecurityTokenConstants.KEYIDENTIFIER_THUMBPRINT_IDENTIFIER;
695         } else if ("SKIKeyIdentifier".equals(keyIdentifier)) {
696             return WSSecurityTokenConstants.KeyIdentifier_SkiKeyIdentifier;
697         } else if ("EncryptedKeySHA1".equals(keyIdentifier)) {
698             return WSSecurityTokenConstants.KEYIDENTIFIER_ENCRYPTED_KEY_SHA1_IDENTIFIER;
699         } else if ("EncryptedKey".equals(keyIdentifier)) {
700             return WSSecurityTokenConstants.KeyIdentifier_EncryptedKey;
701         } else if ("KeyValue".equals(keyIdentifier)) {
702             return WSSecurityTokenConstants.KeyIdentifier_KeyValue;
703         } else if ("KerberosSHA1".equals(keyIdentifier)) {
704             return WSSecurityTokenConstants.KEYIDENTIFIER_KERBEROS_SHA1_IDENTIFIER;
705         }
706         return null;
707     }
708 
709     private static int decodeTimeToLive(Map<String, Object> config, boolean timestamp) {
710         String tag = ConfigurationConstants.TTL_TIMESTAMP;
711         if (!timestamp) {
712             tag = ConfigurationConstants.TTL_USERNAMETOKEN;
713         }
714         String ttl = getString(tag, config);
715         int defaultTimeToLive = 300;
716         if (ttl != null) {
717             try {
718                 int ttlI = Integer.parseInt(ttl);
719                 if (ttlI < 0) {
720                     return defaultTimeToLive;
721                 }
722                 return ttlI;
723             } catch (NumberFormatException e) {
724                 return defaultTimeToLive;
725             }
726         }
727         return defaultTimeToLive;
728     }
729 
730     private static int decodeFutureTimeToLive(Map<String, Object> config, boolean timestamp) {
731         String tag = ConfigurationConstants.TTL_FUTURE_TIMESTAMP;
732         if (!timestamp) {
733             tag = ConfigurationConstants.TTL_FUTURE_USERNAMETOKEN;
734         }
735         String ttl = getString(tag, config);
736         int defaultFutureTimeToLive = 60;
737         if (ttl != null) {
738             try {
739                 int ttlI = Integer.parseInt(ttl);
740                 if (ttlI < 0) {
741                     return defaultFutureTimeToLive;
742                 }
743                 return ttlI;
744             } catch (NumberFormatException e) {
745                 return defaultFutureTimeToLive;
746             }
747         }
748         return defaultFutureTimeToLive;
749     }
750 
751     private static String getString(String tag, Map<String, Object> config) {
752         Object value = config.get(tag);
753         if (value instanceof String) {
754             return (String)value;
755         }
756         return null;
757     }
758 
759     private static boolean decodeBooleanConfigValue(
760         String tag, boolean defaultToTrue, Map<String, Object> config
761     ) {
762         String value = getString(tag, config);
763 
764         if ("0".equals(value) || "false".equals(value)) {
765             return false;
766         }
767         if ("1".equals(value) || "true".equals(value)) {
768             return true;
769         }
770 
771         return defaultToTrue;
772     }
773 
774     private static void splitEncParts(String tmpS, List<SecurePart> parts, String soapNS) {
775         SecurePart encPart = null;
776         String[] rawParts = tmpS.split(";");
777 
778         for (int i = 0; i < rawParts.length; i++) {
779             String[] partDef = rawParts[i].split("}");
780 
781             if (partDef.length == 1) {
782                 QName qname = new QName(soapNS, partDef[0].trim());
783                 encPart = new SecurePart(qname, SecurePart.Modifier.Content);
784             } else if (partDef.length == 2) {
785                 String mode = partDef[0].trim().substring(1);
786                 String element = partDef[1].trim();
787 
788                 if ("Content".equals(mode)) {
789                     encPart = new SecurePart(element, SecurePart.Modifier.Content);
790                 } else {
791                     encPart = new SecurePart(element, SecurePart.Modifier.Element);
792                 }
793             } else if (partDef.length == 3) {
794                 String mode = partDef[0].trim();
795                 if (mode.length() <= 1) {
796                     mode = "Content";
797                 } else {
798                     mode = mode.substring(1);
799                 }
800                 String nmSpace = partDef[1].trim();
801                 if (nmSpace.length() <= 1) {
802                     nmSpace = soapNS;
803                 } else {
804                     nmSpace = nmSpace.substring(1);
805                     if ("Null".equals(nmSpace)) {
806                         nmSpace = null;
807                     }
808                 }
809                 String element = partDef[2].trim();
810 
811                 QName qname = new QName(nmSpace, element);
812                 if ("Content".equals(mode)) {
813                     encPart = new SecurePart(qname, SecurePart.Modifier.Content);
814                 } else {
815                     encPart = new SecurePart(qname, SecurePart.Modifier.Element);
816                 }
817             }
818 
819             parts.add(encPart);
820         }
821     }
822 
823 }