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  
20  package org.apache.wss4j.dom.validate;
21  
22  import java.security.PublicKey;
23  import java.security.cert.X509Certificate;
24  import java.util.Collection;
25  import java.util.regex.Pattern;
26  
27  import org.apache.wss4j.common.crypto.Crypto;
28  import org.apache.wss4j.common.ext.WSSecurityException;
29  import org.apache.wss4j.dom.handler.RequestData;
30  
31  /**
32   * This class verifies trust in a credential used to verify a signature, which is extracted
33   * from the Credential passed to the validate method.
34   */
35  public class SignatureTrustValidator implements Validator {
36  
37      private static final org.slf4j.Logger LOG =
38          org.slf4j.LoggerFactory.getLogger(SignatureTrustValidator.class);
39  
40      /**
41       * Validate the credential argument. It must contain a non-null X509Certificate chain
42       * or a PublicKey. A Crypto implementation is also required to be set.
43       *
44       * This implementation first attempts to verify trust on the certificate (chain). If
45       * this is not successful, then it will attempt to verify trust on the Public Key.
46       *
47       * @param credential the Credential to be validated
48       * @param data the RequestData associated with the request
49       * @throws WSSecurityException on a failed validation
50       */
51      public Credential validate(Credential credential, RequestData data) throws WSSecurityException {
52          if (credential == null) {
53              throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noCredential");
54          }
55          X509Certificate[] certs = credential.getCertificates();
56          PublicKey publicKey = credential.getPublicKey();
57          Crypto crypto = getCrypto(data);
58  
59          if (certs != null && certs.length > 0) {
60              validateCertificates(certs);
61              if (crypto == null) {
62                  throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noSigCryptoFile");
63              }
64              verifyTrustInCerts(certs, crypto, data, data.isRevocationEnabled());
65              return credential;
66          }
67          if (publicKey != null) {
68              if (crypto == null) {
69                  throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noSigCryptoFile");
70              }
71              validatePublicKey(publicKey, crypto);
72              return credential;
73          }
74          throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
75      }
76  
77  
78      protected Crypto getCrypto(RequestData data) {
79          return data.getSigVerCrypto();
80      }
81  
82      /**
83       * Validate the certificates by checking the validity of each cert
84       * @throws WSSecurityException
85       */
86      protected void validateCertificates(X509Certificate[] certificates)
87          throws WSSecurityException {
88          // Nothing
89      }
90  
91      /**
92       * Evaluate whether the given certificate chain should be trusted.
93       *
94       * @param certificates the certificate chain that should be validated against the keystore
95       * @param crypto A Crypto instance
96       * @param data A RequestData instance
97       * @param enableRevocation Whether revocation is enabled or not
98       * @throws WSSecurityException if the certificate chain is not trusted
99       */
100     protected void verifyTrustInCerts(
101         X509Certificate[] certificates,
102         Crypto crypto,
103         RequestData data,
104         boolean enableRevocation
105     ) throws WSSecurityException {
106         //
107         // Use the validation method from the crypto to check whether the subjects'
108         // certificate was really signed by the issuer stated in the certificate
109         //
110         Collection<Pattern> subjectCertConstraints = data.getSubjectCertConstraints();
111         Collection<Pattern> issuerCertConstraints = data.getIssuerDNPatterns();
112         crypto.verifyTrust(certificates, enableRevocation, subjectCertConstraints, issuerCertConstraints);
113         String subjectString = certificates[0].getSubjectX500Principal().getName();
114         LOG.debug(
115             "Certificate path has been verified for certificate with subject {}", subjectString
116         );
117     }
118 
119     /**
120      * Validate a public key
121      * @throws WSSecurityException
122      */
123     protected void validatePublicKey(PublicKey publicKey, Crypto crypto)
124         throws WSSecurityException {
125         crypto.verifyTrust(publicKey);
126     }
127 
128 }