2 * Licensed to the University Corporation for Advanced Internet
3 * Development, Inc. (UCAID) under one or more contributor license
4 * agreements. See the NOTICE file distributed with this work for
5 * additional information regarding copyright ownership.
7 * UCAID licenses this file to you under the Apache License,
8 * Version 2.0 (the "License"); you may not use this file except
9 * in compliance with the License. You may obtain a copy of the
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17 * either express or implied. See the License for the specific
18 * language governing permissions and limitations under the License.
22 * CredentialCriteria.cpp
24 * Class for specifying criteria by which a CredentialResolver should resolve credentials.
29 #include "XMLToolingConfig.h"
30 #include "security/X509Credential.h"
31 #include "security/CredentialCriteria.h"
32 #include "security/KeyInfoResolver.h"
33 #include "security/SecurityHelper.h"
34 #include "signature/Signature.h"
36 #include <openssl/dsa.h>
37 #include <openssl/rsa.h>
38 #include <xsec/dsig/DSIGKeyInfoList.hpp>
39 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyDSA.hpp>
40 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp>
42 using xmlsignature::KeyInfo;
43 using xmlsignature::Signature;
44 using namespace xmltooling::logging;
45 using namespace xmltooling;
48 CredentialCriteria::CredentialCriteria()
49 : m_keyUsage(Credential::UNSPECIFIED_CREDENTIAL), m_keySize(0), m_maxKeySize(0), m_key(nullptr),
50 m_keyInfo(nullptr), m_nativeKeyInfo(nullptr), m_credential(nullptr)
54 CredentialCriteria::~CredentialCriteria()
59 unsigned int CredentialCriteria::getUsage() const
64 void CredentialCriteria::setUsage(unsigned int usage)
69 const char* CredentialCriteria::getPeerName() const
71 return m_peerName.empty() ? nullptr : m_peerName.c_str();
74 void CredentialCriteria::setPeerName(const char* peerName)
78 m_peerName = peerName;
81 const char* CredentialCriteria::getKeyAlgorithm() const
83 return m_keyAlgorithm.empty() ? nullptr : m_keyAlgorithm.c_str();
86 void CredentialCriteria::setKeyAlgorithm(const char* keyAlgorithm)
88 m_keyAlgorithm.erase();
90 m_keyAlgorithm = keyAlgorithm;
93 unsigned int CredentialCriteria::getKeySize() const
98 void CredentialCriteria::setKeySize(unsigned int keySize)
103 unsigned int CredentialCriteria::getMaxKeySize() const
108 void CredentialCriteria::setMaxKeySize(unsigned int keySize)
110 m_maxKeySize = keySize;
113 void CredentialCriteria::setXMLAlgorithm(const XMLCh* algorithm)
116 pair<const char*,unsigned int> mapped = XMLToolingConfig::getConfig().mapXMLAlgorithmToKeyAlgorithm(algorithm);
117 setKeyAlgorithm(mapped.first);
118 setKeySize(mapped.second);
121 setKeyAlgorithm(nullptr);
126 const set<string>& CredentialCriteria::getKeyNames() const
131 set<string>& CredentialCriteria::getKeyNames()
136 XSECCryptoKey* CredentialCriteria::getPublicKey() const
141 void CredentialCriteria::setPublicKey(XSECCryptoKey* key)
146 const KeyInfo* CredentialCriteria::getKeyInfo() const
151 void CredentialCriteria::setKeyInfo(const KeyInfo* keyInfo, int extraction)
154 m_credential = nullptr;
156 if (!keyInfo || !extraction)
159 int types = (extraction & KEYINFO_EXTRACTION_KEY) ? Credential::RESOLVE_KEYS : 0;
160 types |= (extraction & KEYINFO_EXTRACTION_KEYNAMES) ? X509Credential::RESOLVE_CERTS : 0;
161 m_credential = XMLToolingConfig::getConfig().getKeyInfoResolver()->resolve(keyInfo,types);
163 // Ensure any key names have been sucked out for later if desired.
164 if (extraction & KEYINFO_EXTRACTION_KEYNAMES) {
165 X509Credential* xcred = dynamic_cast<X509Credential*>(m_credential);
171 DSIGKeyInfoList* CredentialCriteria::getNativeKeyInfo() const
173 return m_nativeKeyInfo;
176 void CredentialCriteria::setNativeKeyInfo(DSIGKeyInfoList* keyInfo, int extraction)
179 m_credential = nullptr;
180 m_nativeKeyInfo = keyInfo;
181 if (!keyInfo || !extraction)
184 int types = (extraction & KEYINFO_EXTRACTION_KEY) ? Credential::RESOLVE_KEYS : 0;
185 types |= (extraction & KEYINFO_EXTRACTION_KEYNAMES) ? X509Credential::RESOLVE_CERTS : 0;
186 m_credential = XMLToolingConfig::getConfig().getKeyInfoResolver()->resolve(keyInfo,types);
188 // Ensure any key names have been sucked out for later if desired.
189 if (extraction & KEYINFO_EXTRACTION_KEYNAMES) {
190 X509Credential* xcred = dynamic_cast<X509Credential*>(m_credential);
196 void CredentialCriteria::setSignature(const Signature& sig, int extraction)
198 setXMLAlgorithm(sig.getSignatureAlgorithm());
199 KeyInfo* k = sig.getKeyInfo();
201 return setKeyInfo(k, extraction);
202 DSIGSignature* dsig = sig.getXMLSignature();
204 setNativeKeyInfo(dsig->getKeyInfoList(), extraction);
207 void CredentialCriteria::reset()
209 setUsage(Credential::UNSPECIFIED_CREDENTIAL);
212 setKeyAlgorithm(nullptr);
213 getKeyNames().clear();
215 setNativeKeyInfo(nullptr);
218 bool CredentialCriteria::matches(const Credential& credential) const
220 Category& log = Category::getInstance(XMLTOOLING_LOGCAT".CredentialCriteria");
222 // Usage check, if specified and we have one, compare masks.
223 if (getUsage() != Credential::UNSPECIFIED_CREDENTIAL) {
224 if (credential.getUsage() != Credential::UNSPECIFIED_CREDENTIAL)
225 if ((getUsage() & credential.getUsage()) == 0) {
226 if (log.isDebugEnabled())
227 log.debug("usage didn't match (%u != %u)", getUsage(), credential.getUsage());
232 // Algorithm check, if specified and we have one.
233 const char* alg = getKeyAlgorithm();
235 const char* alg2 = credential.getAlgorithm();
237 if (strcmp(alg,alg2)) {
238 if (log.isDebugEnabled())
239 log.debug("key algorithm didn't match ('%s' != '%s')", getKeyAlgorithm(), credential.getAlgorithm());
245 // KeySize check, if specified and we have one.
246 unsigned int ksize = credential.getKeySize();
248 if (m_keySize > 0 && m_maxKeySize == 0) {
249 if (ksize != m_keySize) {
250 log.debug("key size (%u) didn't match (%u)", ksize, m_keySize);
254 else if (m_keySize > 0 && ksize < m_keySize) {
255 log.debug("key size (%u) smaller than minimum (%u)", ksize, m_keySize);
258 else if (m_maxKeySize > 0 && ksize > m_maxKeySize) {
259 log.debug("key size (%u) larger than maximum (%u)", ksize, m_maxKeySize);
264 // See if we can test key names.
265 set<string> critnames = getKeyNames();
267 critnames.insert(m_credential->getKeyNames().begin(), m_credential->getKeyNames().end());
268 const set<string>& crednames = credential.getKeyNames();
269 if (!critnames.empty() && !crednames.empty()) {
271 for (set<string>::const_iterator n = critnames.begin(); n!=critnames.end(); ++n) {
272 if (crednames.count(*n)>0) {
278 log.debug("credential name(s) didn't overlap");
283 // See if we have to match a specific key.
284 const XSECCryptoKey* key1 = getPublicKey();
285 if (!key1 && m_credential)
286 key1 = m_credential->getPublicKey();
288 return true; // no key to compare against, so we're done
290 const XSECCryptoKey* key2 = credential.getPublicKey();
292 return true; // no key here, so we can't test it
294 if (SecurityHelper::matches(*key1, *key2))
297 log.debug("keys didn't match");