Package fixes.
[shibboleth/cpp-xmltooling.git] / xmltooling / security / impl / BasicX509Credential.cpp
1 /*
2  *  Copyright 2001-2007 Internet2
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * BasicX509Credential.cpp
19  * 
20  * Wraps an X.509-based Credential by storing key/cert objects inside. 
21  */
22
23 #include "internal.h"
24 #include "security/BasicX509Credential.h"
25 #include "signature/KeyInfo.h"
26
27 #include <algorithm>
28 #include <openssl/x509v3.h>
29 #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
30
31 using namespace xmlsignature;
32 using namespace xmltooling;
33 using namespace std;
34
35 BasicX509Credential::~BasicX509Credential()
36 {
37     delete m_key;
38     if (m_ownCerts)
39         for_each(m_xseccerts.begin(), m_xseccerts.end(), xmltooling::cleanup<XSECCryptoX509>());
40     delete m_crl;
41     delete m_keyInfo;
42     delete m_compactKeyInfo;
43 }
44
45 void BasicX509Credential::initKeyInfo()
46 {
47     delete m_keyInfo;
48     m_keyInfo = NULL;
49     delete m_compactKeyInfo;
50     m_compactKeyInfo = NULL;
51
52     const set<string>& names = getKeyNames();
53     if (!names.empty()) {
54         m_compactKeyInfo = KeyInfoBuilder::buildKeyInfo();
55         VectorOf(KeyName) knames = m_compactKeyInfo->getKeyNames();
56         for (set<string>::const_iterator n = names.begin(); n!=names.end(); ++n) {
57             if (*n == m_subjectName)
58                 continue;
59             auto_ptr_XMLCh wide(n->c_str());
60             KeyName* kname = KeyNameBuilder::buildKeyName();
61             kname->setName(wide.get());
62             knames.push_back(kname);
63         }
64     }
65
66     if (!m_subjectName.empty() || (!m_issuerName.empty() && !m_serial.empty())) {
67         if (!m_compactKeyInfo)
68             m_compactKeyInfo = KeyInfoBuilder::buildKeyInfo();
69         X509Data* x509Data=X509DataBuilder::buildX509Data();
70         m_compactKeyInfo->getX509Datas().push_back(x509Data);
71         if (!m_subjectName.empty()) {
72             X509SubjectName* sn = X509SubjectNameBuilder::buildX509SubjectName();
73             auto_ptr_XMLCh wide(m_subjectName.c_str());
74             sn->setName(wide.get());
75             x509Data->getX509SubjectNames().push_back(sn);
76         }
77         
78         if (!m_issuerName.empty() && !m_serial.empty()) {
79             X509IssuerSerial* is = X509IssuerSerialBuilder::buildX509IssuerSerial();
80             X509IssuerName* in = X509IssuerNameBuilder::buildX509IssuerName();
81             auto_ptr_XMLCh wide(m_issuerName.c_str());
82             in->setName(wide.get());
83             is->setX509IssuerName(in);
84             X509SerialNumber* ser = X509SerialNumberBuilder::buildX509SerialNumber();
85             auto_ptr_XMLCh wide2(m_serial.c_str());
86             ser->setSerialNumber(wide2.get());
87             is->setX509SerialNumber(ser);
88             x509Data->getX509IssuerSerials().push_back(is);
89         }
90     }
91     
92     if (!m_xseccerts.empty()) {
93         m_keyInfo = m_compactKeyInfo ? m_compactKeyInfo->cloneKeyInfo() : KeyInfoBuilder::buildKeyInfo();
94         if (m_keyInfo->getX509Datas().empty())
95             m_keyInfo->getX509Datas().push_back(X509DataBuilder::buildX509Data());
96         for (vector<XSECCryptoX509*>::const_iterator x = m_xseccerts.begin(); x!=m_xseccerts.end(); ++x) {
97             safeBuffer& buf=(*x)->getDEREncodingSB();
98             X509Certificate* x509=X509CertificateBuilder::buildX509Certificate();
99             x509->setValue(buf.sbStrToXMLCh());
100             m_keyInfo->getX509Datas().front()->getX509Certificates().push_back(x509);
101         }
102     }
103 }
104
105 void BasicX509Credential::extract()
106 {
107     XSECCryptoX509* x509 = m_xseccerts.empty() ? NULL : m_xseccerts.front();
108     if (!x509 || x509->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL)
109         return;
110     X509* cert = static_cast<OpenSSLCryptoX509*>(x509)->getOpenSSLX509();
111     if (!cert)
112         return;
113
114     BIO* b;
115     int len;
116     char buf[256];
117
118     X509_NAME* issuer=X509_get_issuer_name(cert);
119     if (issuer) {
120         memset(buf,0,sizeof(buf));
121         b = BIO_new(BIO_s_mem());
122         BIO_set_mem_eof_return(b, 0);
123         len=X509_NAME_print_ex(b,issuer,0,XN_FLAG_RFC2253);
124         BIO_flush(b);
125         m_issuerName.erase();
126         while ((len = BIO_read(b, buf, 255)) > 0) {
127             buf[len] = '\0';
128             m_issuerName+=buf;
129         }
130         BIO_free(b);
131     }
132
133     ASN1_INTEGER* serialASN = X509_get_serialNumber(cert);
134     BIGNUM* serialBN = ASN1_INTEGER_to_BN(serialASN, NULL);
135     if (serialBN) {
136         char* serial = BN_bn2dec(serialBN);
137         if (serial) {
138             m_serial = serial;
139             free(serial);
140         }
141         BN_free(serialBN);
142     }
143     
144     X509_NAME* subject=X509_get_subject_name(cert);
145     if (subject) {
146         memset(buf,0,sizeof(buf));
147         b = BIO_new(BIO_s_mem());
148         BIO_set_mem_eof_return(b, 0);
149         len=X509_NAME_print_ex(b,subject,0,XN_FLAG_RFC2253);
150         BIO_flush(b);
151         m_subjectName.erase();
152         while ((len = BIO_read(b, buf, 255)) > 0) {
153             buf[len] = '\0';
154             m_subjectName+=buf;
155         }
156         m_keyNames.insert(m_subjectName);
157         BIO_free(b);
158
159         memset(buf,0,sizeof(buf));
160         if (X509_NAME_get_text_by_NID(subject,NID_commonName,buf,255)>0)
161             m_keyNames.insert(buf);
162
163         STACK_OF(GENERAL_NAME)* altnames=(STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
164         if (altnames) {
165             string alt;
166             int numalts = sk_GENERAL_NAME_num(altnames);
167             for (int an=0; an<numalts; an++) {
168                 const GENERAL_NAME* check = sk_GENERAL_NAME_value(altnames, an);
169                 if (check->type==GEN_DNS || check->type==GEN_URI) {
170                     const char* altptr = (char*)ASN1_STRING_data(check->d.ia5);
171                     const int altlen = ASN1_STRING_length(check->d.ia5);
172                     if (altlen>0) {
173                         alt.erase();
174                         alt.append(altptr,altlen);
175                         m_keyNames.insert(alt);
176                     }
177                 }
178             }
179         }
180         GENERAL_NAMES_free(altnames);
181     }
182 }
183
184 const char* BasicX509Credential::getAlgorithm() const
185 {
186     if (m_key) {
187         switch (m_key->getKeyType()) {
188             case XSECCryptoKey::KEY_RSA_PRIVATE:
189             case XSECCryptoKey::KEY_RSA_PUBLIC:
190             case XSECCryptoKey::KEY_RSA_PAIR:
191                 return "RSA";
192
193             case XSECCryptoKey::KEY_DSA_PRIVATE:
194             case XSECCryptoKey::KEY_DSA_PUBLIC:
195             case XSECCryptoKey::KEY_DSA_PAIR:
196                 return "DSA";
197             
198             case XSECCryptoKey::KEY_HMAC:
199                 return "HMAC";
200
201             case XSECCryptoKey::KEY_SYMMETRIC: {
202                 switch (static_cast<XSECCryptoSymmetricKey*>(m_key)->getSymmetricKeyType()) {
203                     case XSECCryptoSymmetricKey::KEY_3DES_192:
204                         return "DESede";
205                     case XSECCryptoSymmetricKey::KEY_AES_128:
206                         return "AES";
207                     case XSECCryptoSymmetricKey::KEY_AES_192:
208                         return "AES";
209                     case XSECCryptoSymmetricKey::KEY_AES_256:
210                         return "AES";
211                 }
212             }
213         }
214     }
215     return NULL;
216 }
217
218 unsigned int BasicX509Credential::getKeySize() const
219 {
220     if (m_key) {
221         switch (m_key->getKeyType()) {
222             case XSECCryptoKey::KEY_RSA_PRIVATE:
223             case XSECCryptoKey::KEY_RSA_PUBLIC:
224             case XSECCryptoKey::KEY_RSA_PAIR: {
225                 XSECCryptoKeyRSA* rkey = static_cast<XSECCryptoKeyRSA*>(m_key);
226                 return rkey->getLength();
227             }
228
229             case XSECCryptoKey::KEY_SYMMETRIC: {
230                 switch (static_cast<XSECCryptoSymmetricKey*>(m_key)->getSymmetricKeyType()) {
231                     case XSECCryptoSymmetricKey::KEY_3DES_192:
232                         return 192;
233                     case XSECCryptoSymmetricKey::KEY_AES_128:
234                         return 128;
235                     case XSECCryptoSymmetricKey::KEY_AES_192:
236                         return 192;
237                     case XSECCryptoSymmetricKey::KEY_AES_256:
238                         return 256;
239                 }
240             }
241         }
242     }
243     return 0;
244 }