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 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");
300 X509_REQ_free(certreq);
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");
322 X509_REQ_free(certreq);
324 return WvString::null;
327 int verify_result = X509_REQ_verify(certreq, pk);
328 if (verify_result == 0 || verify_result == -1)
330 debug(WvLog::Warning,
"Self signed request failed");
331 X509_REQ_free(certreq);
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);
351 X509_REQ_free(certreq);
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);
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);
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);
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);
760 set_extension(NID_key_usage, values);
766 return get_extension(NID_key_usage);
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 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 = M_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);
1016 stack.
split(ext,
";\n");
1017 WvStringList::Iter i(stack);
1018 for (i.rewind();i.next();)
1021 if (strstr(stack_entry, prefix))
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 = M_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);
1164 buf.put(ext->value->data, ext->value->length);
1169 void *ext_data = NULL;
1174 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL 1175 const unsigned char * ext_value_data = ext->value->data;
1177 unsigned char *ext_value_data = ext->value->data;
1181 ext_data = ASN1_item_d2i(NULL, &ext_value_data,
1183 ASN1_ITEM_ptr(method->it));
1184 TRACE(
"Applied generic conversion!\n");
1188 ext_data = method->d2i(NULL, &ext_value_data,
1189 ext->value->length);
1190 TRACE(
"Applied method specific conversion!\n");
1195 TRACE(
"String Extension!\n");
1196 char *s = method->i2s(method, ext_data);
1200 else if (method->i2v)
1202 TRACE(
"Stack Extension!\n");
1203 CONF_VALUE *val = NULL;
1204 STACK_OF(CONF_VALUE) *svals = NULL;
1205 svals = method->i2v(method, ext_data, NULL);
1206 if (!sk_CONF_VALUE_num(svals))
1211 for(
int i = 0; i < sk_CONF_VALUE_num(svals); i++)
1213 val = sk_CONF_VALUE_value(svals, i);
1216 else if (!val->value)
1220 WvString pair(
"%s:%s", val->name, val->value);
1224 retval = list.
join(
";\n");
1226 sk_CONF_VALUE_pop_free(svals, X509V3_conf_free);
1228 else if (method->i2r)
1230 TRACE(
"Raw Extension!\n");
1232 BIO *bufbio = BIO_new(BIO_s_mem());
1234 method->i2r(method, ext_data, bufbio, 0);
1235 BIO_get_mem_ptr(bufbio, &bm);
1236 retvalbuf.put(bm->data, bm->length);
1238 retval = retvalbuf.
getstr();
1242 ASN1_item_free((ASN1_VALUE *)ext_data,
1243 ASN1_ITEM_ptr(method->it));
1245 method->ext_free(ext_data);
1252 TRACE(
"Extension not present!\n");
1256 TRACE(
"Returning: %s\n", retval);
1262 void WvX509::set_extension(
int nid,
WvStringParm _values)
1264 CHECK_CERT_EXISTS_SET(
"extension");
1268 int index = X509_get_ext_by_NID(cert, nid, -1);
1271 X509_EXTENSION *ex = X509_delete_ext(cert, index);
1272 X509_EXTENSION_free(ex);
1277 X509_EXTENSION *ex = NULL;
1278 ex = X509V3_EXT_conf_nid(NULL, NULL, nid, values.
edit());
1279 X509_add_ext(cert, ex, -1);
1280 X509_EXTENSION_free(ex);
1299 return "No certificate.";
1301 return WvString::empty;
1309 return verify(buf, signature);
1315 unsigned char sig_buf[4096];
1316 size_t sig_size =
sizeof(sig_buf);
1319 EVP_PKEY *pk = X509_get_pubkey(cert);
1325 EVP_VerifyInit(&sig_ctx, EVP_sha1());
1326 EVP_VerifyUpdate(&sig_ctx, original.
peek(0, original.
used()),
1328 int sig_err = EVP_VerifyFinal(&sig_ctx, sig_buf, sig_size, pk);
1330 EVP_MD_CTX_cleanup(&sig_ctx);
1333 debug(
"Verify failed!\n");
1341 static time_t ASN1_TIME_to_time_t(ASN1_TIME *t)
1346 memset(&d,
'\0',
sizeof(d));
1347 memset(&newtime,
'\0',
sizeof newtime);
1349 if (t->type == V_ASN1_GENERALIZEDTIME)
1357 p = (
char *)t->data;
1358 sscanf(p,
"%2s%2s%2s%2s%2s%2sZ", d, &d[3], &d[6], &d[9], &d[12], &d[15]);
1360 int year = strtol(d, (
char **)NULL, 10);
1366 newtime.tm_year = year;
1367 newtime.tm_mon = strtol(&d[3], (
char **)NULL, 10) - 1;
1368 newtime.tm_mday = strtol(&d[6], (
char **)NULL, 10);
1369 newtime.tm_hour = strtol(&d[9], (
char **)NULL, 10);
1370 newtime.tm_min = strtol(&d[12], (
char **)NULL, 10);
1371 newtime.tm_sec = strtol(&d[15], (
char **)NULL, 10);
1373 return mktime(&newtime);
1379 CHECK_CERT_EXISTS_GET(
"not valid before", 0);
1381 return ASN1_TIME_to_time_t(X509_get_notBefore(cert));
1385 time_t WvX509::get_notvalid_after()
const 1387 CHECK_CERT_EXISTS_GET(
"not valid after", 0);
1389 return ASN1_TIME_to_time_t(X509_get_notAfter(cert));
1395 CHECK_CERT_EXISTS_GET(
"ski", WvString::null);
1397 return get_extension(NID_subject_key_identifier);
1403 CHECK_CERT_EXISTS_GET(
"aki", WvString::null);
1406 parse_stack(get_extension(NID_authority_key_identifier), aki_list,
1408 if (aki_list.count())
1409 return aki_list.
popstr();
1411 return WvString::null;
1417 CHECK_CERT_EXISTS_GET(
"fingerprint", WvString::null);
1420 const EVP_MD *digest = EVP_sha1();
1421 if (mode == FingerMD5)
1424 unsigned char md[EVP_MAX_MD_SIZE];
1426 if (!X509_digest(cert, digest, md, &n))
1429 debug(
"get_fingerprint: Out of memory\n");
1430 return WvString::null;
1437 sprintf(buf,
"%02X", md[i]);
1439 }
while (++i < n && (store.
putch(
':'), 1));
1445 void WvX509::set_ski()
1447 CHECK_CERT_EXISTS_SET(
"ski");
1449 ASN1_OCTET_STRING *oct = M_ASN1_OCTET_STRING_new();
1450 ASN1_BIT_STRING *pk = cert->cert_info->key->public_key;
1451 unsigned char pkey_dig[EVP_MAX_MD_SIZE];
1452 unsigned int diglen;
1454 EVP_Digest(pk->data, pk->length, pkey_dig, &diglen, EVP_sha1(), NULL);
1456 M_ASN1_OCTET_STRING_set(oct, pkey_dig, diglen);
1457 X509_EXTENSION *ext = X509V3_EXT_i2d(NID_subject_key_identifier, 0,
1459 X509_add_ext(cert, ext, -1);
1460 X509_EXTENSION_free(ext);
1461 M_ASN1_OCTET_STRING_free(oct);
1465 void WvX509::set_aki(
const WvX509 &cacert)
1467 CHECK_CERT_EXISTS_SET(
"aki");
1471 ASN1_OCTET_STRING *ikeyid = NULL;
1472 X509_EXTENSION *ext;
1473 int i = X509_get_ext_by_NID(cacert.cert, NID_subject_key_identifier, -1);
1474 if ((i >= 0) && (ext = X509_get_ext(cacert.cert, i)))
1475 ikeyid =
static_cast<ASN1_OCTET_STRING *
>(X509V3_EXT_d2i(ext));
1480 AUTHORITY_KEYID *akeyid = AUTHORITY_KEYID_new();
1481 akeyid->issuer = NULL;
1482 akeyid->serial = NULL;
1483 akeyid->keyid = ikeyid;
1484 ext = X509V3_EXT_i2d(NID_authority_key_identifier, 0, akeyid);
1485 X509_add_ext(cert, ext, -1);
1486 X509_EXTENSION_free(ext);
1487 AUTHORITY_KEYID_free(akeyid);
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
The basic interface which is included by all other XPLC interfaces and objects.
bool flushstrmem(WvStringParm instr, void *outmem, size_t *outlen, bool finish=false)
Flushes data through the encoder from a string to memory.
void set_aia(WvStringList &ca_urls, WvStringList &responders)
Set a list of urls that have the Certificate of the CA that issued this certificate, as well as the list of OCSP responders for this certificate.
void split(WvStringParm s, const char *splitchars=" \\, int limit=0)
split s and form a list ignoring splitchars (except at beginning and end) ie.
void hexify(char *obuf, const void *ibuf, size_t len)
Write the contents of the binary string of length 'len' pointed to by 'ibuf' into the output buffer '...
bool get_policies(WvStringList &policy_oids) const
Get any certificate Policy OIDs.
WvString get_aki() const
Get the Authority key Info.
bool validate(WvX509 *cacert=NULL) const
Function to verify the validity of a certificate that has been placed in cert.
WvString encode(const DumpMode mode) const
Return the information requested by mode.
WvString popstr()
get the first string in the list, or an empty string if the list is empty.
void set_pubkey(WvRSAKey &rsa_pubkey)
Set the public key of the certificate to the public key rsa_pubkey.
WvString get_ski() const
Get the Subject Key Info.
bool issuedbyca(WvX509 &cacert) const
Check to see if the certificate in cert was issued by the CA certificate in cacert.
WvString get_crl_dp() const
get the CRL Distribution points if they exist, WvString::null if they don't.
WvString get_fingerprint(const FprintMode mode=FingerSHA1) const
Get the certHash (fingerprint) of the certificate.
const char * cstr() const
return a (const char *) for this string.
bool get_basic_constraints(bool &ca, int &pathlen) const
Get the values in the basic constraints extension.
virtual void decode(const DumpMode mode, WvStringParm str)
Load the information from the format requested by mode into the class - this overwrites the certifica...
void putch(int ch)
Puts a single character into the buffer as an int.
WvString get_subject() const
get and set the Subject field of the certificate
bool get_policy_constraints(int &require_explicit_policy, int &inhibit_policy_mapping) const
Get the values in the policy constraints extension.
bool operator!() const
The not operator returns true if !isok()
X509 Class to handle certificates and their related functions.
WvString get_issuer() const
Get and set the Certificate Issuer (usually the CA who signed the certificate).
WvString join(const char *joinchars=" ") const
concatenates all elements of the list seperating on joinchars
void get_crl_urls(WvStringList &urls) const
Get a list of URLs that are valid CRL distribution points for this certificate.
#define UUID_MAP_ENTRY(iface)
Add an entry to an interface map.
char * edit()
make the string editable, and return a non-const (char*)
WvString get_key_usage() const
Get and set the keyUsage field.
void get_ca_urls(WvStringList &urls) const
Get a list of urls that have the Certificate of the CA that issued this certificate.
virtual bool isok() const
Is the certificate object valid?
#define UUID_MAP_BEGIN(component)
Start the interface map for "component".
This is a WvList of WvStrings, and is a really handy way to parse strings.
Specialization of WvBufBase for unsigned char type buffers intended for use with raw memory buffers...
size_t used() const
Returns the number of elements in the buffer currently available for reading.
void set_version()
Set the Certificate to use X509v3, since that's all modern PKI uses anyways :)
#define deletev
Remplacement for delete[].
DumpMode
Type for the encode() and decode() methods.
void get_ocsp(WvStringList &responders) const
Get a list of OCSP Responders for this certificate.
bool signedbyca(WvX509 &cacert) const
Check the certificate in cert against the CA certificate in cacert.
const T * peek(int offset, size_t count)
Returns a const pointer into the buffer at the specified offset to the specified number of elements w...
void set_crl_urls(WvStringList &urls)
Set the list of URLs that are valid CRL distribution points for this certificate. ...
Various little string functions.
void set_policy_constraints(int require_explicit_policy, int inhibit_policy_mapping)
Set the values in the policy constraints extension.
void set_policy_mapping(PolicyMapList &list)
Set the policy mappings for this certificate.
WvString get_ext_key_usage() const
Get and set the extendedKeyUsage field.
time_t get_notvalid_before() const
Return the not before and not after in a format we're more able to easily use.
char * trim_string(char *string)
Trims whitespace from the beginning and end of the character string, including carriage return / line...
virtual WvString errstr() const
Returns an error string if isok() is not true.
#define UUID_MAP_END
Marks the end of an interface map.
An RSA public key or public/private key pair that can be used for encryption.
WvString get_nsserver() const
get and set the Netscape SSL Server extension
WvString is an implementation of a simple and efficient printable-string class.
bool verify(WvBuf &original, WvStringParm signature) const
Verify that the contents of data were signed by the certificate currently in cert.
void set_lifetime(long seconds)
Set the lifetime to be used for this certificate...
void putstr(WvStringParm str)
Copies a WvString into the buffer, excluding the null-terminator.
char * strlwr(char *string)
In-place modify a character string so that all contained letters are in lower case.
const T * get(size_t count)
Reads exactly the specified number of elements and returns a pointer to a storage location owned by t...
WvString get_aia() const
Get the authority info access information.
void set_basic_constraints(bool ca, int pathlen)
Set the values in the basic constraints extension.
bool get_policy_mapping(PolicyMapList &list) const
Get the policy mappings for this certificate.
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's...
void unhexify(void *obuf, const char *ibuf)
Reverse the operation performed by hexify().
WvX509()
Initialize a completely empty X509 Object with an X509 certificate that doesn't have anything it it...
static WvString certreq(WvStringParm subject, const WvRSAKey &rsa)
Create a certificate request (PKCS#10) using this function.
WvString getstr()
Returns the entire buffer as a null-terminated WvString.
WvString get_altsubject() const
Return the Subject alt name if it exists, and WvString::null if it doesn't.
virtual ~WvX509()
Destructor.
void set_policies(WvStringList &policy_oids)
Set the Certificate Policy OIDs in the certificate to that of the input array.
WvString get_serial(bool hex=false) const
get and set the serialNumber field of the certificate