9 #include "wvsslhacks.h"
11 #include "wvstringlist.h"
14 #include "wvautoconf.h"
16 #include <openssl/pem.h>
17 #include <openssl/x509v3.h>
18 #include <openssl/err.h>
19 #include <openssl/sha.h>
20 #include <openssl/ssl.h>
25 # define TRACE(x, y...) debug(x, ## y);
28 # define TRACE(x, y...)
36 static const char * warning_str_set
37 =
"Tried to set %s, but certificate not ok.\n";
38 static const char * warning_str_get
39 =
"Tried to get %s, but certificate not ok.\n";
40 #define CHECK_CERT_EXISTS_SET(x) \
42 debug(WvLog::Warning, warning_str_set, x); \
45 #define CHECK_CERT_EXISTS_GET(x, y) \
47 debug(WvLog::Warning, warning_str_get, x); \
56 static int ssl_init_count = 0;
58 #if !HAVE_OPENSSL_POLICY_MAPPING
80 #endif // !HAVE_OPENSSL_POLICY_MAPPING
88 SSL_load_error_strings();
89 ERR_load_BIO_strings();
90 ERR_load_crypto_strings();
91 OpenSSL_add_all_algorithms();
92 OpenSSL_add_all_ciphers();
93 OpenSSL_add_all_digests();
102 assert(ssl_init_count >= 1);
103 if (ssl_init_count >= 1)
117 ERR_error_string_n(ERR_get_error(), buf,
sizeof(buf));
118 buf[
sizeof(buf)-1] = 0;
124 : debug(
"X509",
WvLog::Debug5)
132 : debug(
"X509",
WvLog::Debug5)
140 : debug(
"X509",
WvLog::Debug5)
144 cert = X509_dup(x509.cert);
152 TRACE(
"Deleting.\n");
164 #ifndef NID_domainComponent
165 #define NID_domainComponent 391
169 #define NID_Domain 392
174 static WvString set_name_entry(X509_NAME *name, WvStringParm dn)
177 X509_NAME_ENTRY *ne = NULL;
185 WvStringList::Iter i(l);
186 for (i.rewind(); i.next(); )
192 value = strchr(cptr,
'=');
196 value = (
char*)
"NULL";
201 nid = NID_countryName;
202 else if (sid ==
"st")
203 nid = NID_stateOrProvinceName;
205 nid = NID_localityName;
207 nid = NID_organizationName;
208 else if (sid ==
"ou")
209 nid = NID_organizationalUnitName;
210 else if (sid ==
"cn")
212 nid = NID_commonName;
215 else if (sid ==
"dc")
217 nid = NID_domainComponent;
222 else if (sid ==
"domain")
227 else if (sid ==
"email")
228 nid = NID_pkcs9_emailAddress;
230 nid = NID_domainComponent;
237 ne = X509_NAME_ENTRY_create_by_NID(NULL, nid,
238 V_ASN1_APP_CHOOSE, (
unsigned char *)value, -1);
240 X509_NAME_ENTRY_create_by_NID(&ne, nid,
241 V_ASN1_APP_CHOOSE, (
unsigned char *)value, -1);
245 X509_NAME_add_entry(name, ne, count++, 0);
248 X509_NAME_ENTRY_free(ne);
257 WvRSAKey *WvX509::get_rsa_pub()
const
259 EVP_PKEY *pkcert = X509_get_pubkey(cert);
260 RSA *certrsa = EVP_PKEY_get1_RSA(pkcert);
261 EVP_PKEY_free(pkcert);
262 return new WvRSAKey(certrsa,
false);
268 WvLog debug(
"X509::certreq", WvLog::Debug5);
271 X509_NAME *name = NULL;
276 debug(
"RSA Key is fine.\n");
279 debug(WvLog::Warning,
"RSA Key is bad");
280 return WvString::null;
283 if ((pk=EVP_PKEY_new()) == NULL)
285 debug(WvLog::Warning,
286 "Error creating key handler for new certificate");
287 return WvString::null;
290 if ((
certreq=X509_REQ_new()) == NULL)
292 debug(WvLog::Warning,
"Error creating new PKCS#10 object");
294 return WvString::null;
297 if (!EVP_PKEY_set1_RSA(pk, rsa.rsa))
299 debug(WvLog::Warning,
"Error adding RSA keys to certificate");
302 return WvString::null;
305 X509_REQ_set_version(
certreq, 0);
307 X509_REQ_set_pubkey(
certreq, pk);
309 name = X509_REQ_get_subject_name(
certreq);
311 debug(
"Creating Certificate request for %s\n", subject);
312 set_name_entry(name, subject);
313 X509_REQ_set_subject_name(
certreq, name);
314 char *sub_name = X509_NAME_oneline(X509_REQ_get_subject_name(
certreq),
316 debug(
"SubjectDN: %s\n", sub_name);
317 OPENSSL_free(sub_name);
319 if (!X509_REQ_sign(
certreq, pk, EVP_sha1()))
321 debug(WvLog::Warning,
"Could not self sign the request");
324 return WvString::null;
327 int verify_result = X509_REQ_verify(
certreq, pk);
328 if (verify_result == 0)
330 debug(WvLog::Warning,
"Self signed request failed");
333 return WvString::null;
337 debug(
"Self Signed Certificate Request verifies OK!\n");
344 BIO *bufbio = BIO_new(BIO_s_mem());
347 PEM_write_bio_X509_REQ(bufbio,
certreq);
348 BIO_get_mem_ptr(bufbio, &bm);
349 retval.put(bm->data, bm->length);
363 debug(WvLog::Warning,
"Tried to validate certificate against CA, but "
364 "certificate is blank!\n");
371 if (X509_cmp_current_time(X509_get_notAfter(cert)) < 0)
373 debug(
"Certificate has expired.\n");
377 if (X509_cmp_current_time(X509_get_notBefore(cert)) > 0)
379 debug(
"Certificate is not yet valid.\n");
395 if (!cert || !cacert.cert)
397 debug(WvLog::Warning,
"Tried to determine if certificate was signed "
398 "by CA, but either client or CA certificate (or both) are "
403 EVP_PKEY *pkey = X509_get_pubkey(cacert.cert);
404 int result = X509_verify(cert, pkey);
409 debug(
"Can't determine if we were signed by CA %s: %s\n",
413 bool issigned = (result > 0);
415 debug(
"Certificate was%s signed by CA %s.\n", issigned ?
"" :
" NOT",
424 if (!cert || !cacert.cert)
426 debug(WvLog::Warning,
"Tried to determine if certificate was issued "
427 "by CA, but either client or CA certificate (or both) are "
432 int ret = X509_check_issued(cacert.cert, cert);
433 debug(
"issuedbyca: %s==X509_V_OK(%s)\n", ret, X509_V_OK);
434 if (ret != X509_V_OK)
451 if (mode == CertFileDER || mode == CertFilePEM)
456 debug(WvLog::Warning,
"Tried to encode certificate, but certificate "
461 debug(
"Encoding X509 certificate.\n");
466 unsigned char *keybuf, *iend;
469 size = i2d_X509(cert, NULL);
470 iend = keybuf =
new unsigned char[size];
471 i2d_X509(cert, &iend);
473 enccert.setsize(size * 2 +1);
481 BIO *bufbio = BIO_new(BIO_s_mem());
485 PEM_write_bio_X509(bufbio, cert);
486 else if (mode == CertDER)
487 i2d_X509_bio(bufbio, cert);
489 debug(WvLog::Warning,
"Tried to encode certificate with unknown "
492 BIO_get_mem_ptr(bufbio, &bm);
493 buf.put(bm->data, bm->length);
503 debug(
"Replacing an already existant X509 certificate.\n");
508 if (mode == CertFileDER)
510 BIO *bio = BIO_new(BIO_s_file());
512 if (BIO_read_filename(bio, str.cstr()) <= 0)
514 debug(WvLog::Warning,
"Open '%s': %s\n", str, wvssl_errstr());
519 if (!(cert = d2i_X509_bio(bio, NULL)))
520 debug(WvLog::Warning,
"Import DER from '%s': %s\n",
521 str, wvssl_errstr());
526 else if (mode == CertFilePEM)
528 FILE *fp = fopen(str,
"rb");
532 debug(
"Open '%s': %s\n", str, strerror(errnum));
536 if (!(cert = PEM_read_X509(fp, NULL, NULL, NULL)))
537 debug(WvLog::Warning,
"Import PEM from '%s': %s\n",
538 str, wvssl_errstr());
543 else if (mode == CertHex)
545 int hexbytes = str.len();
546 int bufsize = hexbytes/2;
547 unsigned char *certbuf =
new unsigned char[bufsize];
548 unsigned char *cp = certbuf;
552 tmpcert = cert = X509_new();
553 cert = wv_d2i_X509(&tmpcert, &cp, bufsize);
569 debug(
"Replacing an already existant X509 certificate.\n");
574 if (mode == CertHex || mode == CertFileDER || mode == CertFilePEM)
578 BIO *membuf = BIO_new(BIO_s_mem());
579 BIO_write(membuf, encoded.
get(encoded.
used()), encoded.
used());
582 cert = PEM_read_bio_X509(membuf, NULL, NULL, NULL);
583 else if (mode == CertDER)
584 cert = d2i_X509_bio(membuf, NULL);
586 debug(WvLog::Warning,
"Tried to decode certificate with unknown "
589 BIO_free_all(membuf);
596 CHECK_CERT_EXISTS_GET(
"issuer", WvString::null);
598 char *name = X509_NAME_oneline(X509_get_issuer_name(cert),0,0);
605 void WvX509::set_issuer(WvStringParm issuer)
607 CHECK_CERT_EXISTS_SET(
"issuer");
609 X509_NAME *name = X509_get_issuer_name(cert);
610 set_name_entry(name, issuer);
611 X509_set_issuer_name(cert, name);
615 void WvX509::set_issuer(
const WvX509 &cacert)
617 CHECK_CERT_EXISTS_SET(
"issuer");
619 X509_NAME *casubj = X509_get_subject_name(cacert.cert);
620 X509_set_issuer_name(cert, casubj);
626 CHECK_CERT_EXISTS_GET(
"subject", WvString::null);
628 char *name = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
635 void WvX509::set_subject(WvStringParm subject)
637 CHECK_CERT_EXISTS_SET(
"subject");
639 X509_NAME *name = X509_get_subject_name(cert);
640 set_name_entry(name, subject);
641 X509_set_subject_name(cert, name);
645 void WvX509::set_subject(X509_NAME *name)
647 CHECK_CERT_EXISTS_SET(
"subject");
649 X509_set_subject_name(cert, name);
655 CHECK_CERT_EXISTS_SET(
"pubkey");
657 EVP_PKEY *pk = EVP_PKEY_new();
661 if (!EVP_PKEY_set1_RSA(pk, _rsa.rsa))
663 debug(
"Error adding RSA keys to certificate.\n");
667 X509_set_pubkey(cert, pk);
674 void WvX509::set_nsserver(WvStringParm servername)
676 CHECK_CERT_EXISTS_SET(
"nsserver");
682 if (strchr(servername,
'='))
683 fqdn = set_name_entry(NULL, servername);
688 fqdn =
"null.noname.null";
690 debug(
"Setting Netscape SSL server name extension to '%s'.\n", fqdn);
693 set_extension(NID_netscape_cert_type,
"server");
694 set_extension(NID_netscape_ssl_server_name, fqdn);
700 return get_extension(NID_netscape_ssl_server_name);
706 CHECK_CERT_EXISTS_GET(
"serial", WvString::null);
708 BIGNUM *bn = BN_new();
709 bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), bn);
724 CHECK_CERT_EXISTS_SET(
"version");
726 X509_set_version(cert, 0x2);
730 void WvX509::set_serial(
long serial)
732 CHECK_CERT_EXISTS_SET(
"serial");
734 ASN1_INTEGER_set(X509_get_serialNumber(cert), serial);
740 return get_extension(NID_crl_distribution_points);
746 CHECK_CERT_EXISTS_SET(
"lifetime");
749 X509_gmtime_adj(X509_get_notBefore(cert), 0);
754 X509_gmtime_adj(X509_get_notAfter(cert), seconds);
758 void WvX509::set_key_usage(WvStringParm values)
760 set_extension(NID_key_usage, values);
766 return get_extension(NID_key_usage);
770 void WvX509::set_ext_key_usage(WvStringParm values)
772 set_extension(NID_ext_key_usage, values);
778 return get_extension(NID_ext_key_usage);
784 return get_extension(NID_subject_alt_name);
790 CHECK_CERT_EXISTS_GET(
"basic constraints",
false);
792 BASIC_CONSTRAINTS *constraints = NULL;
795 constraints =
static_cast<BASIC_CONSTRAINTS *
>
796 (X509_get_ext_d2i(cert, NID_basic_constraints, &i, NULL));
799 ca = constraints->ca;
800 if (constraints->pathlen)
802 if ((constraints->pathlen->type == V_ASN1_NEG_INTEGER) || !ca)
804 debug(
"Path length type not valid when getting basic "
806 BASIC_CONSTRAINTS_free(constraints);
811 pathlen = ASN1_INTEGER_get(constraints->pathlen);
816 BASIC_CONSTRAINTS_free(constraints);
820 debug(
"Basic constraints extension not present.\n");
827 CHECK_CERT_EXISTS_SET(
"basic constraints");
829 BASIC_CONSTRAINTS *constraints = BASIC_CONSTRAINTS_new();
831 constraints->ca =
static_cast<int>(ca);
834 ASN1_INTEGER *i = ASN1_INTEGER_new();
835 ASN1_INTEGER_set(i, pathlen);
836 constraints->pathlen = i;
839 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_basic_constraints, 0,
841 while (
int idx = X509_get_ext_by_NID(cert, NID_basic_constraints, 0) >= 0)
843 debug(
"Found extension at idx %s\n", idx);
844 X509_EXTENSION *tmpex = X509_delete_ext(cert, idx);
845 X509_EXTENSION_free(tmpex);
848 X509_add_ext(cert, ex, NID_basic_constraints);
849 X509_EXTENSION_free(ex);
850 BASIC_CONSTRAINTS_free(constraints);
858 #ifdef HAVE_OPENSSL_POLICY_MAPPING
861 int &inhibit_policy_mapping)
const
863 CHECK_CERT_EXISTS_GET(
"policy constraints",
false);
865 POLICY_CONSTRAINTS *constraints = NULL;
868 constraints =
static_cast<POLICY_CONSTRAINTS *
>(X509_get_ext_d2i(
869 cert, NID_policy_constraints,
873 if (constraints->requireExplicitPolicy)
874 require_explicit_policy = ASN1_INTEGER_get(
875 constraints->requireExplicitPolicy);
877 require_explicit_policy = (-1);
879 if (constraints->inhibitPolicyMapping)
880 inhibit_policy_mapping = ASN1_INTEGER_get(
881 constraints->inhibitPolicyMapping);
883 inhibit_policy_mapping = (-1);
884 POLICY_CONSTRAINTS_free(constraints);
893 int inhibit_policy_mapping)
895 CHECK_CERT_EXISTS_SET(
"policy constraints");
897 POLICY_CONSTRAINTS *constraints = POLICY_CONSTRAINTS_new();
899 ASN1_INTEGER *i = ASN1_INTEGER_new();
900 ASN1_INTEGER_set(i, require_explicit_policy);
901 constraints->requireExplicitPolicy = i;
902 i = ASN1_INTEGER_new();
903 ASN1_INTEGER_set(i, inhibit_policy_mapping);
904 constraints->inhibitPolicyMapping = i;
906 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_policy_constraints, 0,
908 X509_add_ext(cert, ex, -1);
909 X509_EXTENSION_free(ex);
910 POLICY_CONSTRAINTS_free(constraints);
916 CHECK_CERT_EXISTS_GET(
"policy mapping",
false);
918 POLICY_MAPPINGS *mappings = NULL;
919 POLICY_MAPPING *map = NULL;
922 mappings =
static_cast<POLICY_MAPPINGS *
>(X509_get_ext_d2i(
923 cert, NID_policy_mappings,
928 const int POLICYID_MAXLEN = 80;
931 for(
int j = 0; j < sk_POLICY_MAPPING_num(mappings); j++)
933 map = sk_POLICY_MAPPING_value(mappings, j);
934 OBJ_obj2txt(tmp1, POLICYID_MAXLEN, map->issuerDomainPolicy,
true);
935 OBJ_obj2txt(tmp2, POLICYID_MAXLEN, map->subjectDomainPolicy,
true);
936 list.append(
new PolicyMap(tmp1, tmp2),
true);
939 sk_POLICY_MAPPING_pop_free(mappings, POLICY_MAPPING_free);
947 CHECK_CERT_EXISTS_SET(
"policy mapping");
949 POLICY_MAPPINGS *maps = sk_POLICY_MAPPING_new_null();
951 PolicyMapList::Iter i(list);
952 for (i.rewind(); i.next();)
954 POLICY_MAPPING *map = POLICY_MAPPING_new();
955 map->issuerDomainPolicy = OBJ_txt2obj(i().issuer_domain.cstr(), 0);
956 map->subjectDomainPolicy = OBJ_txt2obj(i().subject_domain.cstr(), 0);
957 sk_POLICY_MAPPING_push(maps, map);
961 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_policy_mappings, 0, maps);
962 X509_add_ext(cert, ex, -1);
963 X509_EXTENSION_free(ex);
964 sk_POLICY_MAPPING_pop_free(maps, POLICY_MAPPING_free);
967 #endif // HAVE_OPENSSL_POLICY_MAPPING
970 static void add_aia(WvStringParm type,
WvString identifier,
971 AUTHORITY_INFO_ACCESS *ainfo)
973 ACCESS_DESCRIPTION *acc = ACCESS_DESCRIPTION_new();
974 sk_ACCESS_DESCRIPTION_push(ainfo, acc);
975 acc->method = OBJ_txt2obj(type.cstr(), 0);
976 acc->location->type = GEN_URI;
977 acc->location->d.ia5 = ASN1_IA5STRING_new();
978 unsigned char *cident
979 =
reinterpret_cast<unsigned char *
>(identifier.
edit());
980 ASN1_STRING_set(acc->location->d.ia5, cident, identifier.len());
987 CHECK_CERT_EXISTS_SET(
"aia");
989 AUTHORITY_INFO_ACCESS *ainfo = sk_ACCESS_DESCRIPTION_new_null();
991 WvStringList::Iter i(ca_urls);
992 for (i.rewind(); i.next();)
993 add_aia(
"caIssuers", i(), ainfo);
995 WvStringList::Iter j(responders);
996 for (j.rewind(); j.next();)
997 add_aia(
"OCSP", j(), ainfo);
999 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_info_access, 0, ainfo);
1000 X509_add_ext(cert, ex, -1);
1001 X509_EXTENSION_free(ex);
1002 sk_ACCESS_DESCRIPTION_pop_free(ainfo, ACCESS_DESCRIPTION_free);
1008 return get_extension(NID_info_access);
1012 static void parse_stack(WvStringParm ext,
WvStringList &list,
1013 WvStringParm prefix)
1016 stack.
split(ext,
";\n");
1017 WvStringList::Iter i(stack);
1018 for (i.rewind();i.next();)
1021 if (strstr(stack_entry, prefix))
1023 WvString uri(stack_entry.edit() + prefix.len());
1032 parse_stack(
get_aia(), responders,
"OCSP - URI:");
1038 parse_stack(
get_aia(), urls,
"CA Issuers - URI:");
1050 CHECK_CERT_EXISTS_SET(
"CRL urls");
1052 STACK_OF(DIST_POINT) *crldp = sk_DIST_POINT_new_null();
1053 WvStringList::Iter i(urls);
1054 for (i.rewind(); i.next();)
1056 DIST_POINT *point = DIST_POINT_new();
1057 sk_DIST_POINT_push(crldp, point);
1059 GENERAL_NAMES *uris = GENERAL_NAMES_new();
1060 GENERAL_NAME *uri = GENERAL_NAME_new();
1061 uri->type = GEN_URI;
1062 uri->d.ia5 = ASN1_IA5STRING_new();
1063 unsigned char *cident
1064 =
reinterpret_cast<unsigned char *
>(i().edit());
1065 ASN1_STRING_set(uri->d.ia5, cident, i().len());
1066 sk_GENERAL_NAME_push(uris, uri);
1068 point->distpoint = DIST_POINT_NAME_new();
1069 point->distpoint->name.fullname = uris;
1070 point->distpoint->type = 0;
1073 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_crl_distribution_points, 0, crldp);
1074 X509_add_ext(cert, ex, -1);
1075 X509_EXTENSION_free(ex);
1076 sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
1082 CHECK_CERT_EXISTS_GET(
"policies",
false);
1085 CERTIFICATEPOLICIES * policies =
static_cast<CERTIFICATEPOLICIES *
>(
1086 X509_get_ext_d2i(cert, NID_certificate_policies, &critical, NULL));
1089 for (
int i = 0; i < sk_POLICYINFO_num(policies); i++)
1091 POLICYINFO * policy = sk_POLICYINFO_value(policies, i);
1092 const int POLICYID_MAXLEN = 80;
1094 char policyid[POLICYID_MAXLEN];
1095 OBJ_obj2txt(policyid, POLICYID_MAXLEN, policy->policyid,
1097 policy_oids.append(policyid);
1100 sk_POLICYINFO_pop_free(policies, POLICYINFO_free);
1110 CHECK_CERT_EXISTS_SET(
"policies");
1112 STACK_OF(POLICYINFO) *sk_pinfo = sk_POLICYINFO_new_null();
1114 WvStringList::Iter i(policy_oids);
1115 for (i.rewind(); i.next();)
1117 ASN1_OBJECT *pobj = OBJ_txt2obj(i(), 0);
1118 POLICYINFO *pol = POLICYINFO_new();
1119 pol->policyid = pobj;
1120 sk_POLICYINFO_push(sk_pinfo, pol);
1126 POLICYQUALINFO *qual = NULL;
1130 pol->qualifiers = sk_POLICYQUALINFO_new_null();
1131 qual = POLICYQUALINFO_new();
1132 qual->pqualid = OBJ_nid2obj(NID_id_qt_cps);
1133 qual->d.cpsouri = M_ASN1_IA5STRING_new();
1134 ASN1_STRING_set(qual->d.cpsuri, url.
edit(), url.len());
1135 sk_POLICYQUALINFO_push(pol->qualifiers, qual);
1139 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_certificate_policies, 0,
1141 X509_add_ext(cert, ex, -1);
1142 X509_EXTENSION_free(ex);
1143 sk_POLICYINFO_pop_free(sk_pinfo, POLICYINFO_free);
1147 WvString WvX509::get_extension(
int nid)
const
1149 CHECK_CERT_EXISTS_GET(
"extension", WvString::null);
1153 int index = X509_get_ext_by_NID(cert, nid, -1);
1156 X509_EXTENSION *ext = X509_get_ext(cert, index);
1160 X509V3_EXT_METHOD *method = (X509V3_EXT_METHOD *) X509V3_EXT_get(ext);
1161 ASN1_OCTET_STRING *ext_data_str = X509_EXTENSION_get_data(ext);
1165 buf.put(ext_data_str->data, ext_data_str->length);
1170 void *ext_data = NULL;
1175 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
1176 const unsigned char * ext_value_data = ext_data_str->data;
1178 unsigned char *ext_value_data = ext->value->data;
1182 ext_data = ASN1_item_d2i(NULL, &ext_value_data,
1183 ext_data_str->length,
1184 ASN1_ITEM_ptr(method->it));
1185 TRACE(
"Applied generic conversion!\n");
1189 ext_data = method->d2i(NULL, &ext_value_data,
1190 ext_data_str->length);
1191 TRACE(
"Applied method specific conversion!\n");
1196 TRACE(
"String Extension!\n");
1197 char *s = method->i2s(method, ext_data);
1201 else if (method->i2v)
1203 TRACE(
"Stack Extension!\n");
1204 CONF_VALUE *val = NULL;
1205 STACK_OF(CONF_VALUE) *svals = NULL;
1206 svals = method->i2v(method, ext_data, NULL);
1207 if (!sk_CONF_VALUE_num(svals))
1212 for(
int i = 0; i < sk_CONF_VALUE_num(svals); i++)
1214 val = sk_CONF_VALUE_value(svals, i);
1217 else if (!val->value)
1221 WvString pair(
"%s:%s", val->name, val->value);
1225 retval = list.
join(
";\n");
1227 sk_CONF_VALUE_pop_free(svals, X509V3_conf_free);
1229 else if (method->i2r)
1231 TRACE(
"Raw Extension!\n");
1233 BIO *bufbio = BIO_new(BIO_s_mem());
1235 method->i2r(method, ext_data, bufbio, 0);
1236 BIO_get_mem_ptr(bufbio, &bm);
1237 retvalbuf.put(bm->data, bm->length);
1239 retval = retvalbuf.
getstr();
1243 ASN1_item_free((ASN1_VALUE *)ext_data,
1244 ASN1_ITEM_ptr(method->it));
1246 method->ext_free(ext_data);
1253 TRACE(
"Extension not present!\n");
1257 TRACE(
"Returning: %s\n", retval);
1263 void WvX509::set_extension(
int nid, WvStringParm _values)
1265 CHECK_CERT_EXISTS_SET(
"extension");
1269 int index = X509_get_ext_by_NID(cert, nid, -1);
1272 X509_EXTENSION *ex = X509_delete_ext(cert, index);
1273 X509_EXTENSION_free(ex);
1278 X509_EXTENSION *ex = NULL;
1279 ex = X509V3_EXT_conf_nid(NULL, NULL, nid, values.edit());
1280 X509_add_ext(cert, ex, -1);
1281 X509_EXTENSION_free(ex);
1300 return "No certificate.";
1302 return WvString::empty;
1306 bool WvX509::verify(WvStringParm original, WvStringParm signature)
const
1310 return verify(buf, signature);
1316 unsigned char sig_buf[4096];
1317 size_t sig_size =
sizeof(sig_buf);
1320 EVP_PKEY *pk = X509_get_pubkey(cert);
1325 EVP_MD_CTX *sig_ctx = EVP_MD_CTX_new();
1326 EVP_VerifyInit(sig_ctx, EVP_sha1());
1327 EVP_VerifyUpdate(sig_ctx, original.
peek(0, original.
used()),
1329 int sig_err = EVP_VerifyFinal(sig_ctx, sig_buf, sig_size, pk);
1331 EVP_MD_CTX_free(sig_ctx);
1334 debug(
"Verify failed!\n");
1342 static time_t ASN1_TIME_to_time_t(ASN1_TIME *t)
1347 memset(&d,
'\0',
sizeof(d));
1348 memset(&newtime,
'\0',
sizeof newtime);
1350 if (t->type == V_ASN1_GENERALIZEDTIME)
1358 p = (
char *)t->data;
1359 sscanf(p,
"%2s%2s%2s%2s%2s%2sZ", d, &d[3], &d[6], &d[9], &d[12], &d[15]);
1361 int year = strtol(d, (
char **)NULL, 10);
1367 newtime.tm_year = year;
1368 newtime.tm_mon = strtol(&d[3], (
char **)NULL, 10) - 1;
1369 newtime.tm_mday = strtol(&d[6], (
char **)NULL, 10);
1370 newtime.tm_hour = strtol(&d[9], (
char **)NULL, 10);
1371 newtime.tm_min = strtol(&d[12], (
char **)NULL, 10);
1372 newtime.tm_sec = strtol(&d[15], (
char **)NULL, 10);
1374 return mktime(&newtime);
1380 CHECK_CERT_EXISTS_GET(
"not valid before", 0);
1382 return ASN1_TIME_to_time_t(X509_get_notBefore(cert));
1386 time_t WvX509::get_notvalid_after()
const
1388 CHECK_CERT_EXISTS_GET(
"not valid after", 0);
1390 return ASN1_TIME_to_time_t(X509_get_notAfter(cert));
1396 CHECK_CERT_EXISTS_GET(
"ski", WvString::null);
1398 return get_extension(NID_subject_key_identifier);
1404 CHECK_CERT_EXISTS_GET(
"aki", WvString::null);
1407 parse_stack(get_extension(NID_authority_key_identifier), aki_list,
1409 if (aki_list.count())
1410 return aki_list.
popstr();
1412 return WvString::null;
1418 CHECK_CERT_EXISTS_GET(
"fingerprint", WvString::null);
1421 const EVP_MD *digest = EVP_sha1();
1422 if (mode == FingerMD5)
1425 unsigned char md[EVP_MAX_MD_SIZE];
1427 if (!X509_digest(cert, digest, md, &n))
1430 debug(
"get_fingerprint: Out of memory\n");
1431 return WvString::null;
1438 sprintf(buf,
"%02X", md[i]);
1440 }
while (++i < n && (store.
putch(
':'), 1));
1446 void WvX509::set_ski()
1448 CHECK_CERT_EXISTS_SET(
"ski");
1450 ASN1_OCTET_STRING *oct = ASN1_OCTET_STRING_new();
1451 ASN1_BIT_STRING *pk = X509_get0_pubkey_bitstr(cert);
1452 unsigned char pkey_dig[EVP_MAX_MD_SIZE];
1453 unsigned int diglen;
1455 EVP_Digest(pk->data, pk->length, pkey_dig, &diglen, EVP_sha1(), NULL);
1457 ASN1_OCTET_STRING_set(oct, pkey_dig, diglen);
1458 X509_EXTENSION *ext = X509V3_EXT_i2d(NID_subject_key_identifier, 0,
1460 X509_add_ext(cert, ext, -1);
1461 X509_EXTENSION_free(ext);
1462 ASN1_OCTET_STRING_free(oct);
1466 void WvX509::set_aki(
const WvX509 &cacert)
1468 CHECK_CERT_EXISTS_SET(
"aki");
1472 ASN1_OCTET_STRING *ikeyid = NULL;
1473 X509_EXTENSION *ext;
1474 int i = X509_get_ext_by_NID(cacert.cert, NID_subject_key_identifier, -1);
1475 if ((i >= 0) && (ext = X509_get_ext(cacert.cert, i)))
1476 ikeyid =
static_cast<ASN1_OCTET_STRING *
>(X509V3_EXT_d2i(ext));
1481 AUTHORITY_KEYID *akeyid = AUTHORITY_KEYID_new();
1482 akeyid->issuer = NULL;
1483 akeyid->serial = NULL;
1484 akeyid->keyid = ikeyid;
1485 ext = X509V3_EXT_i2d(NID_authority_key_identifier, 0, akeyid);
1486 X509_add_ext(cert, ext, -1);
1487 X509_EXTENSION_free(ext);
1488 AUTHORITY_KEYID_free(akeyid);