Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

wvx509.cc

Go to the documentation of this file.
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * X.509 certificate management classes. 00006 */ 00007 #include "wvx509.h" 00008 #include "wvsslhacks.h" 00009 #include "wvdiriter.h" 00010 #include "wvcrypto.h" 00011 #include "wvstringlist.h" 00012 #include "strutils.h" 00013 00014 #include <openssl/pem.h> 00015 #include <openssl/x509v3.h> 00016 #include <openssl/err.h> 00017 #include <openssl/sha.h> 00018 #include <openssl/pkcs12.h> 00019 00020 static int ssl_init_count = 0; 00021 00022 void wvssl_init() 00023 { 00024 if (!ssl_init_count) 00025 { 00026 OpenSSL_add_all_algorithms(); 00027 ERR_load_crypto_strings(); 00028 } 00029 00030 ssl_init_count++; 00031 } 00032 00033 00034 void wvssl_free() 00035 { 00036 // HACK: never allow this function to actually free stuff, because I 00037 // think we're doing it wrong. 00038 if (ssl_init_count >= 2) 00039 ssl_init_count--; 00040 00041 if (!ssl_init_count) 00042 { 00043 assert(0); 00044 ERR_free_strings(); 00045 EVP_cleanup(); 00046 } 00047 } 00048 00049 00050 WvString wvssl_errstr() 00051 { 00052 char buf[256]; 00053 ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); 00054 buf[sizeof(buf)-1] = 0; 00055 return buf; 00056 } 00057 00058 00059 WvX509Mgr::WvX509Mgr(X509 *_cert) 00060 : debug("X509", WvLog::Debug5), pkcs12pass(WvString::null) 00061 { 00062 wvssl_init(); 00063 cert = _cert; 00064 rsa = NULL; 00065 if (cert) 00066 { 00067 char buffer[1024]; 00068 00069 X509_NAME_oneline(X509_get_subject_name(cert), buffer, sizeof(buffer)); 00070 buffer[sizeof(buffer)-1] = 0; 00071 dname = buffer; 00072 00073 EVP_PKEY *pk; 00074 pk = X509_get_pubkey(cert); 00075 00076 if ((pk = X509_get_pubkey(cert)) != NULL) 00077 { 00078 size_t size; 00079 unsigned char *keybuf, *iend; 00080 WvString tmppub; 00081 00082 size = i2d_RSAPublicKey(pk->pkey.rsa, NULL); 00083 iend = keybuf = new unsigned char[size]; 00084 i2d_RSAPublicKey(pk->pkey.rsa, &iend); 00085 00086 tmppub.setsize(size * 2 + 1); 00087 ::hexify(tmppub.edit(), keybuf, size); 00088 rsa = new WvRSAKey(tmppub, false); 00089 00090 delete[] keybuf; 00091 } 00092 } 00093 } 00094 00095 00096 WvX509Mgr::WvX509Mgr(WvStringParm hexified_cert, 00097 WvStringParm hexified_rsa) 00098 : debug("X509", WvLog::Debug5), pkcs12pass(WvString::null) 00099 { 00100 wvssl_init(); 00101 00102 cert = NULL; 00103 rsa = new WvRSAKey(hexified_rsa, true); 00104 if (!rsa->isok()) 00105 { 00106 seterr("RSA Error: %s\n", rsa->errstr()); 00107 return; 00108 } 00109 00110 unhexify(hexified_cert); 00111 00112 if (cert) 00113 { 00114 char buffer[1024]; 00115 00116 X509_NAME_oneline(X509_get_subject_name(cert), buffer, sizeof(buffer)); 00117 buffer[sizeof(buffer)-1] = 0; 00118 dname = buffer; 00119 } 00120 } 00121 00122 00123 WvX509Mgr::WvX509Mgr(WvStringParm _dname, WvRSAKey *_rsa) 00124 : dname(_dname), debug("X509", WvLog::Debug5), pkcs12pass(WvString::null) 00125 { 00126 assert(_rsa); 00127 00128 wvssl_init(); 00129 debug("Creating new certificate for %s\n", dname); 00130 cert = NULL; 00131 rsa = _rsa; 00132 create_selfsigned(); 00133 } 00134 00135 00136 WvX509Mgr::WvX509Mgr(WvStringParm _dname, int bits) 00137 : dname(_dname), debug("X509", WvLog::Debug5) 00138 { 00139 wvssl_init(); 00140 debug("Creating new certificate for %s\n", dname); 00141 cert = NULL; 00142 rsa = new WvRSAKey(bits); 00143 create_selfsigned(); 00144 } 00145 00146 00147 WvX509Mgr::~WvX509Mgr() 00148 { 00149 if (rsa) 00150 delete rsa; 00151 X509_free(cert); 00152 wvssl_free(); 00153 } 00154 00155 00156 // The people who designed this garbage should be shot! 00157 // Support old versions of openssl... 00158 #ifndef NID_domainComponent 00159 #define NID_domainComponent 391 00160 #endif 00161 00162 #ifndef NID_Domain 00163 #define NID_Domain 392 00164 #endif 00165 00166 00167 // returns some approximation of the server's fqdn, or an empty string. 00168 static WvString set_name_entry(X509_NAME *name, WvStringParm dn) 00169 { 00170 WvString fqdn(""), force_fqdn(""); 00171 X509_NAME_ENTRY *ne = NULL; 00172 int count = 0, nid; 00173 00174 WvStringList l; 00175 l.split(dn, ","); 00176 00177 // dn is of the form: c=ca,o=foo organization,dc=foo,dc=com 00178 // (ie. name=value pairs separated by commas) 00179 WvStringList::Iter i(l); 00180 for (i.rewind(); i.next(); ) 00181 { 00182 WvString s(*i), sid; 00183 char *cptr, *value; 00184 00185 cptr = s.edit(); 00186 value = strchr(cptr, '='); 00187 if (value) 00188 *value++ = 0; 00189 else 00190 value = "NULL"; 00191 00192 sid = strlwr(trim_string(cptr)); 00193 00194 if (sid == "c") 00195 nid = NID_countryName; 00196 else if (sid == "st") 00197 nid = NID_stateOrProvinceName; 00198 else if (sid == "l") 00199 nid = NID_localityName; 00200 else if (sid == "o") 00201 nid = NID_organizationName; 00202 else if (sid == "ou") 00203 nid = NID_organizationalUnitName; 00204 else if (sid == "cn") 00205 { 00206 nid = NID_commonName; 00207 force_fqdn = value; 00208 } 00209 else if (sid == "dc") 00210 { 00211 nid = NID_domainComponent; 00212 if (!!fqdn) 00213 fqdn.append("."); 00214 fqdn.append(value); 00215 } 00216 else if (sid == "domain") 00217 { 00218 nid = NID_Domain; 00219 force_fqdn = value; 00220 } 00221 else 00222 nid = NID_domainComponent; 00223 00224 if (!ne) 00225 ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, 00226 V_ASN1_APP_CHOOSE, (unsigned char *)value, -1); 00227 else 00228 X509_NAME_ENTRY_create_by_NID(&ne, nid, 00229 V_ASN1_APP_CHOOSE, (unsigned char *)value, -1); 00230 if (!ne) 00231 continue; 00232 X509_NAME_add_entry(name, ne, count++, 0); 00233 } 00234 00235 X509_NAME_ENTRY_free(ne); 00236 00237 if (!!force_fqdn) 00238 return force_fqdn; 00239 00240 return fqdn; 00241 } 00242 00243 00244 void WvX509Mgr::create_selfsigned() 00245 { 00246 EVP_PKEY *pk = NULL; 00247 X509_NAME *name = NULL; 00248 X509_EXTENSION *ex = NULL; 00249 00250 // RFC2459 says that this number must be unique for each certificate 00251 // issued by a CA. It may be that some web browsers get confused if 00252 // more than one cert with the same name has the same serial number, so 00253 // let's be careful. 00254 srand(time(NULL)); 00255 int serial = rand(); 00256 00257 WvString serverfqdn; 00258 00259 assert(rsa); 00260 00261 // double check RSA key 00262 if (RSA_check_key(rsa->rsa) == 1) 00263 debug("RSA Key is fine.\n"); 00264 else 00265 { 00266 seterr("RSA Key is bad!\n"); 00267 return; 00268 } 00269 00270 if ((pk=EVP_PKEY_new()) == NULL) 00271 { 00272 seterr("Error creating key handler for new certificate"); 00273 return; 00274 } 00275 if ((cert=X509_new()) == NULL) 00276 { 00277 seterr("Error creating new X509 object"); 00278 return; 00279 } 00280 00281 // Assign RSA Key from WvRSAKey into stupid package that OpenSSL needs 00282 if (!EVP_PKEY_assign_RSA(pk, rsa->rsa)) 00283 { 00284 seterr("Error adding RSA keys to certificate"); 00285 return; 00286 } 00287 00288 // Completely broken in my mind - this sets the version 00289 // string to '3' (I guess version starts at 0) 00290 X509_set_version(cert, 0x2); 00291 00292 // Set the Serial Number for the certificate 00293 ASN1_INTEGER_set(X509_get_serialNumber(cert), serial); 00294 00295 // Set the NotBefore time to now. 00296 X509_gmtime_adj(X509_get_notBefore(cert), 0); 00297 00298 // Now + 10 years... should be shorter, but since we don't currently 00299 // have a set of routines to refresh the certificates, make it 00300 // REALLY long. 00301 X509_gmtime_adj(X509_get_notAfter(cert), (long)60*60*24*3650); 00302 X509_set_pubkey(cert, pk); 00303 00304 name = X509_get_subject_name(cert); 00305 serverfqdn = set_name_entry(name, dname); 00306 00307 if (!serverfqdn) 00308 serverfqdn = "null.noname.null"; 00309 00310 X509_set_issuer_name(cert, name); 00311 X509_set_subject_name(cert, name); 00312 00313 // Add in the netscape-specific server extension 00314 ex = X509V3_EXT_conf_nid(NULL, NULL, NID_netscape_cert_type, "server"); 00315 X509_add_ext(cert, ex, -1); 00316 X509_EXTENSION_free(ex); 00317 00318 debug("Setting Netscape SSL server name extension to %s\n", serverfqdn); 00319 00320 // Set the netscape server name extension to our server name 00321 ex = X509V3_EXT_conf_nid(NULL, NULL, NID_netscape_ssl_server_name, 00322 serverfqdn.edit()); 00323 X509_add_ext(cert, ex, -1); 00324 X509_EXTENSION_free(ex); 00325 00326 // Set the RFC2459-mandated keyUsage field to critical, and restrict 00327 // the usage of this cert to digital signature and key encipherment. 00328 ex = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, 00329 "critical,digitalSignature,keyEncipherment,keyCertSign"); 00330 X509_add_ext(cert, ex, -1); 00331 X509_EXTENSION_free(ex); 00332 00333 #if 0 00334 // This still causes Netscape to barf... 00335 ex = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, 00336 "critical,CA:FALSE"); 00337 X509_add_ext(cert, ex, -1); 00338 X509_EXTENSION_free(ex); 00339 #endif 00340 00341 ex = X509V3_EXT_conf_nid(NULL, NULL, NID_ext_key_usage, 00342 "TLS Web Server Authentication,TLS Web Client Authentication"); 00343 X509_add_ext(cert, ex, -1); 00344 X509_EXTENSION_free(ex); 00345 00346 // Sign the certificate with our own key ("Self Sign") 00347 if (!X509_sign(cert, pk, EVP_sha1())) 00348 { 00349 seterr("Could not self sign the certificate"); 00350 X509_free(cert); 00351 EVP_PKEY_free(pk); 00352 return; 00353 } 00354 00355 debug("Certificate for %s created\n", dname); 00356 } 00357 00358 00359 static FILE *file_hack_start() 00360 { 00361 return tmpfile(); 00362 } 00363 00364 00365 static WvString file_hack_end(FILE *f) 00366 { 00367 WvDynBuf b; 00368 size_t len; 00369 00370 rewind(f); 00371 while ((len = fread(b.alloc(1024), 1, 1024, f)) > 0) 00372 b.unalloc(1024 - len); 00373 b.unalloc(1024 - len); 00374 fclose(f); 00375 00376 return b.getstr(); 00377 } 00378 00379 00380 WvString WvX509Mgr::certreq() 00381 { 00382 EVP_PKEY *pk; 00383 X509_NAME *name = NULL; 00384 X509_REQ *certreq; 00385 00386 FILE *stupid = file_hack_start(); 00387 00388 assert(rsa); 00389 assert(dname); 00390 00391 // double check RSA key 00392 if (RSA_check_key(rsa->rsa) == 1) 00393 debug("RSA Key is fine.\n"); 00394 else 00395 { 00396 seterr("RSA Key is bad!\n"); 00397 return WvString::null; 00398 } 00399 00400 if ((pk=EVP_PKEY_new()) == NULL) 00401 { 00402 seterr("Error creating key handler for new certificate"); 00403 return WvString::null; 00404 } 00405 00406 if ((certreq=X509_REQ_new()) == NULL) 00407 { 00408 seterr("Error creating new PKCS#10 object"); 00409 EVP_PKEY_free(pk); 00410 return WvString::null; 00411 } 00412 00413 WvRSAKey rsa2(*rsa); 00414 if (!EVP_PKEY_assign_RSA(pk, rsa2.rsa)) 00415 { 00416 seterr("Error adding RSA keys to certificate"); 00417 X509_REQ_free(certreq); 00418 EVP_PKEY_free(pk); 00419 return WvString::null; 00420 } 00421 00422 X509_REQ_set_version(certreq, 0); /* version 1 */ 00423 00424 X509_REQ_set_pubkey(certreq, pk); 00425 00426 name = X509_REQ_get_subject_name(certreq); 00427 00428 debug("Creating Certificate request for %s\n", dname); 00429 set_name_entry(name, dname); 00430 X509_REQ_set_subject_name(certreq, name); 00431 debug("SubjectDN: %s\n", 00432 X509_NAME_oneline(X509_REQ_get_subject_name(certreq), 0, 0)); 00433 00434 if (!X509_REQ_sign(certreq, pk, EVP_sha1())) 00435 { 00436 seterr("Could not self sign the request"); 00437 X509_REQ_free(certreq); 00438 EVP_PKEY_free(pk); 00439 return WvString::null; 00440 } 00441 00442 int verify_result = X509_REQ_verify(certreq, pk); 00443 if (verify_result == 0) 00444 { 00445 seterr("Self Signed Request failed!"); 00446 X509_REQ_free(certreq); 00447 EVP_PKEY_free(pk); 00448 return WvString::null; 00449 } 00450 else 00451 { 00452 debug("Self Signed Certificate Request verifies OK!\n"); 00453 } 00454 00455 // don't let rsa2 free its own RSA key... the certificate will do that 00456 // for us. 00457 rsa2.rsa = NULL; 00458 00459 // Horribly involuted hack to get around the fact that the 00460 // OpenSSL people are too braindead to have a PEM_write function 00461 // that returns a char * 00462 PEM_write_X509_REQ(stupid, certreq); 00463 X509_REQ_free(certreq); 00464 EVP_PKEY_free(pk); 00465 00466 return file_hack_end(stupid); 00467 } 00468 00469 00470 bool WvX509Mgr::test() 00471 { 00472 bool bad = false; 00473 00474 EVP_PKEY *pk = EVP_PKEY_new(); 00475 00476 if (!cert) 00477 { 00478 seterr("no Certificate in X509 Manager!"); 00479 bad = true; 00480 } 00481 00482 if (rsa && pk) 00483 { 00484 WvRSAKey tmpkey(*rsa); 00485 00486 if (!EVP_PKEY_assign_RSA(pk, tmpkey.rsa)) 00487 { 00488 seterr("Error setting RSA keys"); 00489 bad = true; 00490 } 00491 else if (!bad) 00492 { 00493 int verify_return = X509_verify(cert, pk); 00494 if (verify_return != 1) // only '1' means okay 00495 { 00496 seterr("Certificate test failed: %s\n", wvssl_errstr()); 00497 bad = true; 00498 } 00499 } 00500 00501 tmpkey.rsa = NULL; 00502 } 00503 else 00504 { 00505 seterr("no RSA keypair in X509 manager"); 00506 bad = true; 00507 } 00508 00509 if (pk) 00510 EVP_PKEY_free(pk); 00511 00512 return !bad; 00513 } 00514 00515 00516 void WvX509Mgr::unhexify(WvStringParm encodedcert) 00517 { 00518 int hexbytes = strlen(encodedcert.cstr()); 00519 int bufsize = hexbytes/2; 00520 unsigned char *certbuf = new unsigned char[bufsize]; 00521 unsigned char *cp = certbuf; 00522 X509 *tmpcert; 00523 00524 if (cert) 00525 X509_free(cert); 00526 00527 ::unhexify(certbuf, encodedcert); 00528 tmpcert = cert = X509_new(); 00529 cert = wv_d2i_X509(&tmpcert, &cp, hexbytes/2); 00530 00531 // make sure that the cert is valid 00532 if (cert && !test()) 00533 { 00534 X509_free(cert); 00535 cert = NULL; 00536 } 00537 00538 if (!cert) 00539 seterr("X.509 certificate decode failed!"); 00540 00541 delete[] certbuf; 00542 } 00543 00544 00545 WvString WvX509Mgr::hexify() 00546 { 00547 size_t size; 00548 unsigned char *keybuf, *iend; 00549 WvString enccert; 00550 00551 size = i2d_X509(cert, NULL); 00552 iend = keybuf = new unsigned char[size]; 00553 i2d_X509(cert, &iend); 00554 00555 enccert.setsize(size * 2 +1); 00556 ::hexify(enccert.edit(), keybuf, size); 00557 00558 delete[] keybuf; 00559 return enccert; 00560 } 00561 00562 00563 bool WvX509Mgr::validate() 00564 { 00565 if (cert != NULL) 00566 { 00567 debug("Peer Certificate:\n"); 00568 debug("Issuer: %s\n", 00569 X509_NAME_oneline(X509_get_issuer_name(cert),0,0)); 00570 00571 // Check and make sure that the certificate is still valid 00572 if (X509_cmp_current_time(X509_get_notAfter(cert)) == -1) 00573 { 00574 seterr("Peer certificate has expired!"); 00575 return false; 00576 } 00577 00578 // Kind of a placeholder thing right now... 00579 // Later on, do CRL, and certificate validity checks here.. 00580 // Actually, break these out in signedbyvalidCA(), and isinCRL() 00581 // Maybe have them here and activated by bool values as parameters 00582 // to validate. 00583 } 00584 else 00585 debug("Peer doesn't have a certificate.\n"); 00586 00587 return true; 00588 } 00589 00590 00591 bool WvX509Mgr::signedbyCAinfile(WvStringParm certfile) 00592 { 00593 X509_STORE *cert_ctx = NULL; 00594 X509_STORE_CTX csc; 00595 X509_LOOKUP *lookup = NULL; 00596 int result = 0; 00597 00598 cert_ctx = X509_STORE_new(); 00599 if (cert_ctx == NULL) 00600 { 00601 seterr("Unable to create Certificate Store Context"); 00602 return false; 00603 } 00604 00605 lookup=X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file()); 00606 if (lookup == NULL) 00607 { 00608 seterr("Can't add lookup method...\n"); 00609 return false; 00610 } 00611 00612 if (!X509_LOOKUP_load_file(lookup, certfile, X509_FILETYPE_PEM)) 00613 X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); 00614 00615 X509_STORE_CTX_init(&csc, cert_ctx, cert, NULL); 00616 result = X509_verify_cert(&csc); 00617 X509_STORE_CTX_cleanup(&csc); 00618 00619 X509_STORE_free(cert_ctx); 00620 00621 if (result == 1) 00622 return true; 00623 else 00624 return false; 00625 } 00626 00627 00628 bool WvX509Mgr::signedbyCAindir(WvStringParm certdir) 00629 { 00630 WvDirIter i(certdir,false); 00631 for (i.rewind(); i.next(); ) 00632 { 00633 if (!signedbyCAinfile(i->fullname)) 00634 return false; 00635 } 00636 return true; 00637 } 00638 00639 00640 bool WvX509Mgr::isinCRL() 00641 { 00642 return false; 00643 } 00644 00645 00646 WvString WvX509Mgr::encode(const DumpMode mode) 00647 { 00648 FILE *stupid; 00649 const EVP_CIPHER *enc; 00650 WvString nil; 00651 00652 stupid = file_hack_start(); 00653 00654 if (stupid) 00655 { 00656 switch(mode) 00657 { 00658 case CertPEM: 00659 debug("Dumping X509 certificate.\n"); 00660 PEM_write_X509(stupid, cert); 00661 break; 00662 00663 case RsaPEM: 00664 debug("Dumping RSA keypair.\n"); 00665 enc = EVP_get_cipherbyname("rsa"); 00666 PEM_write_RSAPrivateKey(stupid, rsa->rsa, enc, 00667 NULL, 0, NULL, NULL); 00668 break; 00669 00670 case RsaRaw: 00671 debug("Dumping raw RSA keypair.\n"); 00672 RSA_print_fp(stupid, rsa->rsa, 0); 00673 break; 00674 00675 default: 00676 seterr("Unknown Mode\n"); 00677 return nil; 00678 } 00679 00680 return file_hack_end(stupid); 00681 } 00682 else 00683 { 00684 debug(WvLog::Error, "Can't create temp file in WvX509Mgr::encode!\n"); 00685 return nil; 00686 } 00687 } 00688 00689 void WvX509Mgr::decode(DumpMode mode, WvStringParm pemEncoded) 00690 { 00691 // Let the fun begin... ;) 00692 FILE *stupid; 00693 const EVP_CIPHER *enc; 00694 WvString outstring = pemEncoded; 00695 00696 stupid = file_hack_start(); 00697 00698 if (stupid) 00699 { 00700 // I HATE OpenSSL... this is SO Stupid!!! 00701 rewind(stupid); 00702 unsigned int written = fwrite(outstring.edit(), 1, outstring.len(), stupid); 00703 if (written != outstring.len()) 00704 { 00705 debug(WvLog::Error,"Couldn't write full amount to temp file!\n"); 00706 fclose(stupid); 00707 return; 00708 } 00709 rewind(stupid); 00710 switch(mode) 00711 { 00712 case CertPEM: 00713 debug("Importing X509 certificate.\n"); 00714 if(cert) 00715 { 00716 X509_free(cert); 00717 cert = NULL; 00718 } 00719 cert = PEM_read_X509(stupid, NULL, NULL, NULL); 00720 break; 00721 00722 case RsaPEM: 00723 debug("Importing RSA keypair.\n"); 00724 debug("Make sure that you load or generate a new Certificate!\n"); 00725 enc = EVP_get_cipherbyname("rsa"); 00726 rsa->rsa = PEM_read_RSAPrivateKey(stupid, NULL, NULL, NULL); 00727 break; 00728 00729 case RsaRaw: 00730 debug("Importing raw RSA keypair not supported.\n"); 00731 break; 00732 00733 default: 00734 seterr("Unknown Mode\n"); 00735 } 00736 fclose(stupid); 00737 } 00738 else 00739 { 00740 debug(WvLog::Error, "Can't create temp file in WvX509Mgr::decode!\n"); 00741 return; 00742 } 00743 } 00744 00745 void WvX509Mgr::write_p12(WvStringParm filename) 00746 { 00747 debug("Dumping RSA Key and X509 Cert to PKCS12 structure.\n"); 00748 00749 FILE *fp = fopen(filename, "w"); 00750 00751 if (!fp) 00752 { 00753 seterr("Unable to create: %s\n", filename); 00754 return; 00755 } 00756 00757 if (!!pkcs12pass) 00758 { 00759 EVP_PKEY *pk = EVP_PKEY_new(); 00760 if (!pk) 00761 { 00762 seterr("Unable to create PKEY object.\n"); 00763 return; 00764 } 00765 00766 if (rsa && cert) 00767 { 00768 WvRSAKey tmpkey(*rsa); 00769 00770 if (!EVP_PKEY_assign_RSA(pk, tmpkey.rsa)) 00771 { 00772 seterr("Error setting RSA keys.\n"); 00773 return; 00774 } 00775 else 00776 { 00777 PKCS12 *pkg = PKCS12_create(pkcs12pass.edit(), "foo", pk, 00778 cert, NULL, 0, 0, 0, 0, 0); 00779 if (pkg) 00780 { 00781 debug("Write the PKCS12 object out...\n"); 00782 i2d_PKCS12_fp(fp, pkg); 00783 PKCS12_free(pkg); 00784 } 00785 else 00786 { 00787 seterr("Unable to create PKCS12 object.\n"); 00788 return; 00789 } 00790 } 00791 } 00792 else 00793 { 00794 seterr("Either the RSA key or the Certificate is not present\n"); 00795 return; 00796 } 00797 } 00798 else 00799 { 00800 seterr("No Password specified for PKCS12 dump\n"); 00801 return; 00802 } 00803 } 00804 00805 void WvX509Mgr::read_p12(WvStringParm filename) 00806 { 00807 debug("Reading Certificate and Private Key from PKCS12 file: %s\n", filename); 00808 00809 FILE *fp = fopen(filename, "r"); 00810 00811 if (!fp) 00812 { 00813 seterr("Unable to read from: %s\n", filename); 00814 return; 00815 } 00816 00817 if (!!pkcs12pass) 00818 { 00819 PKCS12 *pkg = d2i_PKCS12_fp(fp, NULL); 00820 if (pkg) 00821 { 00822 EVP_PKEY *pk = EVP_PKEY_new(); 00823 if (!pk) 00824 { 00825 seterr("Unable to create PKEY object.\n"); 00826 return; 00827 } 00828 00829 // Parse out the bits out the PKCS12 package. 00830 PKCS12_parse(pkg, pkcs12pass, &pk, &cert, NULL); 00831 PKCS12_free(pkg); 00832 00833 // Now, cert should be OK, let's try and set up the RSA stuff 00834 // since we've essentially got a PKEY, and not a WvRSAKey 00835 // We need to create a new WvRSAKey from the PKEY... 00836 rsa = new WvRSAKey(pk->pkey.rsa, true); 00837 00838 // Now that we have both, check to make sure that they match 00839 if (!rsa || !cert || test()) 00840 { 00841 seterr("Could not fill in RSA and Cert with matching values.\n"); 00842 return; 00843 } 00844 // We don't free pk here because the WvRSAKey object now 00845 // owns the key value and should delete it in the constructor. 00846 } 00847 else 00848 { 00849 seterr("Read in of PKCS12 file '%s' failed - aborting!\n", filename); 00850 return; 00851 } 00852 } 00853 else 00854 { 00855 seterr("No Password specified for PKCS12 file - aborting!\n"); 00856 return; 00857 } 00858 } 00859 00860 00861 WvString WvX509Mgr::get_issuer() 00862 { 00863 return WvString(X509_NAME_oneline(X509_get_issuer_name(cert),0,0)); 00864 } 00865 00866 00867 WvString WvX509Mgr::get_subject() 00868 { 00869 return WvString(X509_NAME_oneline(X509_get_subject_name(cert),0,0)); 00870 } 00871 00872 00873 WvString WvX509Mgr::get_crl_dp() 00874 { 00875 WvDynBuf *buf = get_extension(NID_crl_distribution_points); 00876 if (buf) 00877 { 00878 WvString retval(buf->getstr()); 00879 delete buf; 00880 return retval; 00881 } 00882 else 00883 return WvString::null; 00884 } 00885 00886 00887 WvString WvX509Mgr::get_cp_oid() 00888 { 00889 WvDynBuf *buf = get_extension(NID_certificate_policies); 00890 if (buf) 00891 { 00892 WvString retval(buf->getstr()); 00893 delete buf; 00894 return retval; 00895 } 00896 else 00897 return WvString::null; 00898 } 00899 00900 00901 WvString WvX509Mgr::get_altsubject() 00902 { 00903 WvDynBuf *buf = get_extension(NID_subject_alt_name); 00904 if (buf) 00905 { 00906 WvString retval(buf->getstr()); 00907 delete buf; 00908 return retval; 00909 } 00910 else 00911 return WvString::null; 00912 00913 } 00914 00915 WvDynBuf *WvX509Mgr::get_extension(int nid) 00916 { 00917 int index = X509_get_ext_by_NID(cert, nid, -1); 00918 if (index >= 0) 00919 { 00920 X509_EXTENSION *ext = X509_get_ext(cert, index); 00921 if (ext) 00922 { 00923 WvDynBuf *buf = new WvDynBuf(); 00924 buf->put(ext->value->data, ext->value->length); 00925 return buf; 00926 } 00927 } 00928 return NULL; 00929 } 00930

Generated on Tue Oct 5 01:09:21 2004 for WvStreams by doxygen 1.3.7