Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | 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 Wed Dec 15 15:08:12 2004 for WvStreams by  doxygen 1.3.9.1