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 = 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 = 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;
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);
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