wvx509.cc

00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2005 Net Integration Technologies, Inc.
00004  * 
00005  * X.509 certificate management classes.
00006  */ 
00007 #include "wvx509.h"
00008 #include "wvrsa.h"
00009 #include "wvcrl.h"
00010 #include "wvsslhacks.h"
00011 #include "wvdiriter.h"
00012 #include "wvcrypto.h"
00013 #include "wvstringlist.h"
00014 #include "wvbase64.h"
00015 #include "wvstrutils.h"
00016 #include "wvfileutils.h"
00017 
00018 #include <openssl/pem.h>
00019 #include <openssl/x509v3.h>
00020 #include <openssl/err.h>
00021 #include <openssl/ssl.h>
00022 #include <openssl/sha.h>
00023 #include <openssl/pkcs12.h>
00024 
00025 UUID_MAP_BEGIN(WvX509Mgr)
00026   UUID_MAP_ENTRY(IObject)
00027   UUID_MAP_END
00028 
00029 static int ssl_init_count = 0;
00030 
00031 namespace {
00032 class AutoClose {
00033 public:
00034     AutoClose(FILE *fp): fp(fp) { }
00035     ~AutoClose()
00036     {
00037         if (fp)
00038             fclose(fp);
00039     }
00040     
00041     operator FILE *() const
00042     {
00043         return fp;
00044     }
00045     
00046 private:
00047     FILE *fp;
00048 };
00049 } // anomymous namespace...
00050 
00051 
00052 
00053 void wvssl_init()
00054 {
00055     if (!ssl_init_count)
00056     {
00057         OpenSSL_add_all_algorithms();
00058         OpenSSL_add_ssl_algorithms();
00059         ERR_load_crypto_strings();
00060     }
00061     
00062     ssl_init_count++;
00063 }
00064 
00065 
00066 void wvssl_free()
00067 {
00068     // HACK: never allow this function to actually free stuff, because I
00069     // think we're doing it wrong.
00070     if (ssl_init_count >= 2)
00071         ssl_init_count--;
00072 
00073     if (!ssl_init_count)
00074     {
00075         assert(0);
00076         ERR_free_strings();
00077         EVP_cleanup();
00078     }
00079 }
00080 
00081 
00082 WvString wvssl_errstr()
00083 {
00084     char buf[256];
00085     ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
00086     buf[sizeof(buf)-1] = 0;
00087     return buf;
00088 }
00089 
00090 
00091 WvX509Mgr::WvX509Mgr(X509 *_cert)
00092     : debug("X509", WvLog::Debug5), pkcs12pass(WvString::null)
00093 {
00094     wvssl_init();
00095     cert = _cert;
00096     rsa = NULL;
00097     if (cert)
00098     {
00099         filldname();
00100         rsa = fillRSAPubKey();
00101         if (!rsa->isok())
00102             seterr("RSA Public Key Error: %s", rsa->errstr());
00103     }
00104     else
00105         ;
00106         // This isn't an error, or a mistake...
00107         // so this is one case where 
00108         // cert == NULL && rsa == NULL && errstr == NULL
00109         // That the programmer should be doing something about.
00110 }
00111 
00112 
00113 WvX509Mgr::WvX509Mgr()
00114     : debug("X509", WvLog::Debug5), pkcs12pass(WvString::null)
00115 {
00116     wvssl_init();
00117     cert = NULL;
00118     rsa = NULL;
00119 }
00120 
00121 
00122 WvX509Mgr::WvX509Mgr(WvStringParm hexified_cert,
00123                      WvStringParm hexified_rsa)
00124     : debug("X509", WvLog::Debug5), pkcs12pass(WvString::null)
00125 {
00126     wvssl_init();
00127     
00128     cert = NULL;
00129     rsa = new WvRSAKey(hexified_rsa, true);
00130     if (!rsa->isok())
00131     {
00132         seterr("RSA Error: %s\n", rsa->errstr());
00133         return;
00134     }
00135 
00136     if (!!hexified_cert)
00137         unhexify(hexified_cert);
00138     else
00139     {
00140         seterr("No Hexified Cert.. aborting!\n");
00141         return;
00142     }
00143 
00144     if (cert)
00145         filldname();
00146 }
00147 
00148 
00149 WvX509Mgr::WvX509Mgr(WvStringParm _dname, WvRSAKey *_rsa)
00150     : dname(_dname), debug("X509", WvLog::Debug5), pkcs12pass(WvString::null)
00151 {
00152     assert(_rsa);
00153     
00154     wvssl_init();
00155     debug("Creating new certificate for %s\n", dname);
00156     cert = NULL;
00157     rsa = _rsa;
00158     create_selfsigned();
00159 }
00160 
00161 
00162 WvX509Mgr::WvX509Mgr(WvStringParm _dname, int bits)
00163     : dname(_dname), debug("X509", WvLog::Debug5)
00164 {
00165     wvssl_init();
00166     debug("Creating new certificate for %s\n", dname);
00167     cert = NULL;
00168     rsa = NULL;
00169     
00170     if (!!dname)
00171     {
00172         rsa = new WvRSAKey(bits);
00173         create_selfsigned();
00174     }
00175     else
00176         seterr("Sorry, can't create an anonymous Certificate\n");
00177 }
00178 
00179 
00180 WvX509Mgr::~WvX509Mgr()
00181 {
00182     debug("Deleting.\n");
00183     
00184     if (rsa)
00185         delete rsa;
00186 
00187     if (cert)
00188         X509_free(cert);
00189 
00190     wvssl_free();
00191 }
00192 
00193 
00194 bool WvX509Mgr::bind_ssl(SSL_CTX *ctx)
00195 {
00196     if (SSL_CTX_use_certificate(ctx, cert) <= 0)
00197     {
00198         return false;
00199     }
00200     debug("Certificate activated.\n");
00201     
00202     if (SSL_CTX_use_RSAPrivateKey(ctx, rsa->rsa) <= 0)
00203     {
00204         return false;
00205     }
00206     debug("RSA private key activated.\n");
00207     return true;
00208 }
00209 
00210 
00211 const WvRSAKey &WvX509Mgr::get_rsa()
00212 {
00213     assert(rsa);
00214 
00215     return *rsa;
00216 }
00217 
00218 
00219 // The people who designed this garbage should be shot!
00220 // Support old versions of openssl...
00221 #ifndef NID_domainComponent
00222 #define NID_domainComponent 391
00223 #endif
00224 
00225 #ifndef NID_Domain
00226 #define NID_Domain 392
00227 #endif
00228 
00229 
00230 // returns some approximation of the server's fqdn, or an empty string.
00231 static WvString set_name_entry(X509_NAME *name, WvStringParm dn)
00232 {
00233     WvString fqdn(""), force_fqdn("");
00234     X509_NAME_ENTRY *ne = NULL;
00235     int count = 0, nid;
00236     
00237     WvStringList l;
00238     l.split(dn, ",");
00239     
00240     // dn is of the form: c=ca,o=foo organization,dc=foo,dc=com
00241     // (ie. name=value pairs separated by commas)
00242     WvStringList::Iter i(l);
00243     for (i.rewind(); i.next(); )
00244     {
00245         WvString s(*i), sid;
00246         char *cptr, *value;
00247         
00248         cptr = s.edit();
00249         value = strchr(cptr, '=');
00250         if (value)
00251             *value++ = 0;
00252         else
00253             value = "NULL";
00254         
00255         sid = strlwr(trim_string(cptr));
00256         
00257         if (sid == "c")
00258             nid = NID_countryName;
00259         else if (sid == "st")
00260             nid = NID_stateOrProvinceName;
00261         else if (sid == "l")
00262             nid = NID_localityName;
00263         else if (sid == "o")
00264             nid = NID_organizationName;
00265         else if (sid == "ou")
00266             nid = NID_organizationalUnitName;
00267         else if (sid == "cn")
00268         {
00269             nid = NID_commonName;
00270             force_fqdn = value;
00271         }
00272         else if (sid == "dc")
00273         {
00274             nid = NID_domainComponent;
00275             if (!!fqdn)
00276                 fqdn.append(".");
00277             fqdn.append(value);
00278         }
00279         else if (sid == "domain")
00280         {
00281             nid = NID_Domain;
00282             force_fqdn = value;
00283         }
00284         else if (sid == "email")
00285             nid = NID_pkcs9_emailAddress;
00286         else
00287             nid = NID_domainComponent;
00288         
00289         // Sometimes we just want to parse dn into fqdn.
00290         if (name == NULL)
00291             continue;
00292         
00293         if (!ne)
00294             ne = X509_NAME_ENTRY_create_by_NID(NULL, nid,
00295                                V_ASN1_APP_CHOOSE, (unsigned char *)value, -1);
00296         else
00297             X509_NAME_ENTRY_create_by_NID(&ne, nid,
00298                                V_ASN1_APP_CHOOSE, (unsigned char *)value, -1);
00299         if (!ne)
00300             continue;
00301         
00302         X509_NAME_add_entry(name, ne, count++, 0);
00303     }
00304     
00305     X509_NAME_ENTRY_free(ne);
00306     
00307     if (!!force_fqdn)
00308         return force_fqdn;
00309 
00310     return fqdn;
00311 }
00312 
00313 
00314 void WvX509Mgr::create_selfsigned(bool is_ca)
00315 {
00316     assert(rsa);
00317 
00318     if (cert)
00319     {
00320         debug("Replacing already existant certificate...\n");
00321         X509_free(cert);
00322         cert = NULL;
00323     }
00324     
00325     // double check RSA key
00326     if (rsa->isok())
00327         debug("RSA Key is fine.\n");
00328     else
00329     {
00330         seterr("RSA Key is bad!\n");
00331         return;
00332     }
00333 
00334     if ((cert = X509_new()) == NULL)
00335     {
00336         seterr("Error creating new X509 object");
00337         return;
00338     }
00339 
00340     // Completely broken in my mind - this sets the version
00341     // string to '3'  (I guess version starts at 0)
00342     set_version();
00343 
00344     // RFC2459 says that this number must be unique for each certificate
00345     // issued by a CA.  It may be that some web browsers get confused if
00346     // more than one cert with the same name has the same serial number, so
00347     // let's be careful.
00348     srand(time(NULL));
00349     int serial = rand();
00350     set_serial(serial);
00351     
00352     // 10 years...
00353     set_lifetime(60*60*24*3650);
00354     
00355     set_pubkey(rsa);
00356                                        
00357     set_issuer(dname);
00358     set_subject(dname);
00359     
00360     if (is_ca)
00361     {
00362         debug("Setting Extensions with CA Parameters.\n");
00363         debug("Setting Key Usage.\n");
00364         set_key_usage("critical, keyCertSign, cRLSign");
00365         debug("Setting Basic Constraints.\n");
00366         set_extension(NID_basic_constraints, "critical, CA:TRUE");
00367         debug("Setting Netscape Certificate Type.\n");
00368         set_extension(NID_netscape_cert_type, "SSL CA, S/MIME CA, Object Signing CA");
00369 //      debug("Setting Constraints.\n");
00370 //      set_constraints("requireExplicitPolicy");
00371     }
00372     else
00373     {
00374         debug("Setting Key Usage with normal server parameters\n");
00375         set_nsserver(dname);
00376         set_key_usage("critical, digitalSignature, keyEncipherment, keyAgreement");
00377         set_extension(NID_basic_constraints, "CA:FALSE");
00378         set_ext_key_usage("TLS Web Server Authentication,"
00379                           "TLS Web Client Authentication");
00380     }
00381     
00382     debug("Ok - Parameters set... now signing certificate.\n");
00383     signcert(cert);
00384     
00385     debug("Certificate for %s created\n", dname);
00386 }
00387 
00388 
00389 void WvX509Mgr::filldname()
00390 {
00391     assert(cert);
00392     
00393     char *name = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
00394     dname = name;
00395     OPENSSL_free(name);
00396 }
00397 
00398 
00399 // FIXME: This is EVIL!!!
00400 WvRSAKey *WvX509Mgr::fillRSAPubKey()
00401 {
00402     EVP_PKEY *pkcert = X509_get_pubkey(cert);
00403     RSA *certrsa = EVP_PKEY_get1_RSA(pkcert);
00404     EVP_PKEY_free(pkcert);
00405     return new WvRSAKey(certrsa, false); 
00406 }
00407 
00408 
00409 WvString WvX509Mgr::certreq()
00410 {
00411     EVP_PKEY *pk = NULL;
00412     X509_NAME *name = NULL;
00413     X509_REQ *certreq = NULL;
00414 
00415     assert(rsa);
00416     assert(dname);
00417 
00418     // double check RSA key
00419     if (rsa->isok())
00420         debug("RSA Key is fine.\n");
00421     else
00422     {
00423         seterr("RSA Key is bad!\n");
00424         return WvString::null;
00425     }
00426 
00427     if ((pk=EVP_PKEY_new()) == NULL)
00428     {
00429         seterr("Error creating key handler for new certificate");
00430         return WvString::null;
00431     }
00432     
00433     if ((certreq=X509_REQ_new()) == NULL)
00434     {
00435         seterr("Error creating new PKCS#10 object");
00436         EVP_PKEY_free(pk);
00437         return WvString::null;
00438     }
00439 
00440     if (!EVP_PKEY_set1_RSA(pk, rsa->rsa))
00441     {
00442         seterr("Error adding RSA keys to certificate");
00443         X509_REQ_free(certreq);
00444         EVP_PKEY_free(pk);
00445         return WvString::null;
00446     }
00447     
00448     X509_REQ_set_version(certreq, 0); /* version 1 */
00449 
00450     X509_REQ_set_pubkey(certreq, pk);
00451 
00452     name = X509_REQ_get_subject_name(certreq);
00453 
00454     debug("Creating Certificate request for %s\n", dname);
00455     set_name_entry(name, dname);
00456     X509_REQ_set_subject_name(certreq, name);
00457     char *sub_name = X509_NAME_oneline(X509_REQ_get_subject_name(certreq), 
00458                                        0, 0);
00459     debug("SubjectDN: %s\n", sub_name);
00460     OPENSSL_free(sub_name);
00461     
00462     if (!X509_REQ_sign(certreq, pk, EVP_sha1()))
00463     {
00464         seterr("Could not self sign the request");
00465         X509_REQ_free(certreq);
00466         EVP_PKEY_free(pk);
00467         return WvString::null;
00468     }
00469 
00470     int verify_result = X509_REQ_verify(certreq, pk);
00471     if (verify_result == 0)
00472     {
00473         seterr("Self Signed Request failed!");
00474         X509_REQ_free(certreq);
00475         EVP_PKEY_free(pk);
00476         return WvString::null;
00477     }
00478     else
00479     {
00480         debug("Self Signed Certificate Request verifies OK!\n");
00481     }
00482 
00483     // Horribly involuted hack to get around the fact that the
00484     // OpenSSL people are too braindead to have a PEM_write function
00485     // that returns a char *
00486     WvDynBuf retval;
00487     BIO *bufbio = BIO_new(BIO_s_mem());
00488     BUF_MEM *bm;
00489     
00490     PEM_write_bio_X509_REQ(bufbio, certreq);
00491     BIO_get_mem_ptr(bufbio, &bm);
00492     retval.put(bm->data, bm->length);
00493     
00494     X509_REQ_free(certreq);
00495     EVP_PKEY_free(pk);
00496     BIO_free(bufbio);
00497 
00498     return retval.getstr();
00499 }
00500 
00501 
00502 WvString WvX509Mgr::signreq(WvStringParm pkcs10req)
00503 {
00504     assert(rsa);
00505     assert(cert);
00506     debug("Signing a certificate request with : %s\n", get_subject());
00507     
00508     // Break this next part out into a de-pemify section, since that is what
00509     // this part up until the FIXME: is about.
00510     WvString pkcs10(pkcs10req);
00511     
00512     char *begin = strstr(pkcs10.edit(), "\nMII");
00513     if (!begin)
00514     {
00515         debug("This doesn't look like PEM Encoded information...\n");
00516         return WvString::null;
00517     }
00518     char *end = strstr(begin + 1, "\n---");
00519     if (!end)
00520     {
00521         debug("Is this a complete certificate request?\n");
00522         return WvString::null;
00523     }
00524     *++end = '\0';
00525     WvString body(begin); // just the PKCS#10 request, 
00526                           // without the ---BEGIN and ---END
00527     
00528     WvDynBuf reqbuf;
00529     WvBase64Decoder dec;
00530     dec.flushstrbuf(body, reqbuf, true);
00531     
00532     // FIXME: Duplicates code from cert_selfsign
00533     size_t reqlen = reqbuf.used();
00534     const unsigned char *req = reqbuf.get(reqlen);
00535     X509_REQ *certreq = wv_d2i_X509_REQ(NULL, &req, reqlen);
00536     if (certreq)
00537     {
00538         WvX509Mgr newcert;
00539 
00540         newcert.set_subject(X509_REQ_get_subject_name(certreq));
00541         newcert.set_version();
00542         
00543         // Set the Serial Number for the certificate
00544         srand(time(NULL));
00545         int serial = rand();
00546         newcert.set_serial(serial);
00547         
00548         newcert.set_lifetime(60*60*24*3650);
00549         
00550         // The public key of the new cert should be the same as that from 
00551         // the request.
00552         EVP_PKEY *pk = X509_REQ_get_pubkey(certreq);
00553         X509_set_pubkey(newcert.get_cert(), pk);
00554         EVP_PKEY_free(pk);
00555         
00556         // The Issuer name is the subject name of the current cert
00557         newcert.set_issuer(get_subject());
00558         
00559         X509_EXTENSION *ex = NULL;
00560         // Set the RFC2459-mandated keyUsage field to critical, and restrict
00561         // the usage of this cert to digital signature and key encipherment.
00562         newcert.set_key_usage("critical, digitalSignature, keyEncipherment");
00563     
00564         // This could cause Netscape to barf because if we set basicConstraints 
00565         // to critical, we break RFC2459 compliance. Why they chose to enforce 
00566         // that bit, and not the rest is beyond me... but oh well...
00567         ex = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints,
00568                                  "CA:FALSE");
00569         
00570         X509_add_ext(newcert.get_cert(), ex, -1);
00571         X509_EXTENSION_free(ex);
00572 
00573         newcert.set_ext_key_usage("critical, TLS Web Client Authentication");
00574 
00575         signcert(newcert.get_cert());
00576         
00577         X509_REQ_free(certreq);
00578         return WvString(newcert.encode(CertPEM));
00579     }
00580     else
00581     {
00582         debug("Can't decode Certificate Request\n");
00583         return WvString::null;
00584     }
00585 }
00586 
00587 
00588 bool WvX509Mgr::test()
00589 {
00590     bool bad = false;
00591     
00592     EVP_PKEY *pk = EVP_PKEY_new();
00593     
00594     if (!cert)
00595     {
00596         seterr("no Certificate in X509 Manager!");
00597         bad = true;
00598     }
00599     
00600     if (rsa && pk)
00601     {
00602         if (!EVP_PKEY_set1_RSA(pk, rsa->rsa))
00603         {
00604             seterr("Error setting RSA keys");
00605             bad = true;
00606         }
00607         else if (!bad)
00608         {
00609             int verify_return = X509_verify(cert, pk);
00610             if (verify_return != 1) // only '1' means okay
00611             {
00612                 // However let's double check:
00613                 WvString rsapub = encode(RsaPubPEM);
00614                 WvRSAKey *temprsa = fillRSAPubKey();
00615                 WvString certpub = temprsa->getpem(false);
00616                 delete temprsa;
00617                 // debug("rsapub:\n%s\n", rsapub);
00618                 // debug("certpub:\n%s\n", certpub);
00619                 if (certpub == rsapub)
00620                     ; // do nothing, since OpenSSL is lying
00621                 else
00622                 {
00623                     // I guess that it really did fail.
00624                     seterr("Certificate test failed: %s\n", wvssl_errstr());
00625                     bad = true;
00626                 }
00627             }
00628         }
00629     }
00630     else
00631     {
00632         seterr("no RSA keypair in X509 manager");
00633         bad = true;
00634     }
00635     
00636     if (pk)
00637         EVP_PKEY_free(pk);
00638     
00639     return !bad;
00640 }
00641 
00642 
00643 void WvX509Mgr::unhexify(WvStringParm encodedcert)
00644 {
00645     if (!encodedcert)
00646     {
00647         seterr("X.509 certificate can't be decoded from nothing!\n");
00648         return;
00649     }
00650     
00651     int hexbytes = strlen(encodedcert.cstr());
00652     int bufsize = hexbytes/2;
00653     unsigned char *certbuf = new unsigned char[bufsize];
00654     unsigned char *cp = certbuf;
00655     X509 *tmpcert;
00656     
00657     if (cert)
00658         X509_free(cert);
00659 
00660     ::unhexify(certbuf, encodedcert);
00661     tmpcert = cert = X509_new();
00662     cert = wv_d2i_X509(&tmpcert, &cp, hexbytes/2);
00663 
00664     // make sure that the cert is valid
00665     if (cert && !test())
00666     {
00667         X509_free(cert);
00668         cert = NULL;
00669     }
00670     
00671     if (!cert)
00672         seterr("X.509 certificate decode failed!");
00673     
00674     deletev certbuf;
00675 }
00676 
00677 
00678 WvString WvX509Mgr::hexify()
00679 {
00680     size_t size;
00681     unsigned char *keybuf, *iend;
00682     WvString enccert;
00683 
00684     size = i2d_X509(cert, NULL);
00685     iend = keybuf = new unsigned char[size];
00686     i2d_X509(cert, &iend);
00687 
00688     enccert.setsize(size * 2 +1);
00689     ::hexify(enccert.edit(), keybuf, size);
00690 
00691     deletev keybuf;
00692     return enccert;
00693 }
00694 
00695 
00696 bool WvX509Mgr::validate(WvX509Mgr *cacert, X509_CRL *crl)
00697 {
00698     bool retval = true;
00699     
00700     if (cert != NULL)
00701     {
00702         // Check and make sure that the certificate is still valid
00703         if (X509_cmp_current_time(X509_get_notAfter(cert)) == -1)
00704         {
00705             seterr("Certificate has expired!");
00706             retval = false;
00707         }
00708         
00709         if (cacert)
00710             retval &= signedbyCA(cacert);
00711 
00712         // Kind of a placeholder thing right now...
00713         // Later on, do CRL, and certificate validity checks here..
00714         // Actually, break these out in signedbyvalidCA(), and isinCRL()
00715         // Maybe have them here and activated by bool values as parameters 
00716         // to validate.
00717     }
00718     else
00719         debug("Peer doesn't have a certificate.\n");
00720     
00721     return retval;
00722 }
00723 
00724 
00725 bool WvX509Mgr::signedbyCAinfile(WvStringParm certfile)
00726 {
00727     X509_STORE *cert_ctx = NULL;
00728     X509_STORE_CTX csc;
00729     X509_LOOKUP *lookup = NULL;
00730     int result = 0;
00731 
00732     cert_ctx = X509_STORE_new();
00733     if (cert_ctx == NULL)
00734     {
00735         seterr("Unable to create Certificate Store Context");
00736         return false;
00737     }
00738 
00739     lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file());
00740     if (lookup == NULL)
00741     {
00742         seterr("Can't add lookup method...\n");
00743         return false;
00744     }  
00745 
00746     if (!X509_LOOKUP_load_file(lookup, certfile, X509_FILETYPE_PEM))
00747         X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
00748 
00749     X509_STORE_CTX_init(&csc, cert_ctx, cert, NULL);
00750     result = X509_verify_cert(&csc);
00751     X509_STORE_CTX_cleanup(&csc);
00752     
00753     X509_STORE_free(cert_ctx);
00754 
00755     if (result == 1)
00756         return true;
00757     else
00758         return false;
00759 }
00760 
00761 
00762 #ifndef _WIN32
00763 bool WvX509Mgr::signedbyCAindir(WvStringParm certdir)
00764 {
00765     WvDirIter i(certdir,false);
00766     for (i.rewind(); i.next(); )
00767     {
00768         if (!signedbyCAinfile(i->fullname))
00769             return false;
00770     }    
00771     return true;
00772 }
00773 #endif
00774 
00775 
00776 bool WvX509Mgr::signedbyCA(WvX509Mgr *cacert)
00777 {
00778     int ret = X509_check_issued(cacert->cert, cert);
00779     if (ret == X509_V_OK)
00780         return true;
00781     else
00782         return false;
00783 }
00784 
00785 
00786 WvString WvX509Mgr::encode(const DumpMode mode)
00787 {
00788     WvString nil;
00789     WvDynBuf retval;
00790     BIO *bufbio = BIO_new(BIO_s_mem());
00791     BUF_MEM *bm;
00792     
00793     switch(mode)
00794     {
00795     case CertPEM:
00796         debug("Dumping X509 certificate.\n");
00797         PEM_write_bio_X509(bufbio, cert);
00798         break;
00799         
00800     case CertDER:
00801         debug("Dumping X509 certificate in DER format\n");
00802         i2d_X509_bio(bufbio, cert);
00803         break;
00804         
00805     case RsaPEM:
00806         debug("Dumping RSA keypair.\n");
00807         BIO_free(bufbio);
00808         return rsa->getpem(true);
00809         break;
00810         
00811     case RsaPubPEM:
00812         debug("Dumping RSA Public Key!\n");
00813         BIO_free(bufbio);
00814         return rsa->getpem(false);
00815         break;
00816 
00817     case RsaRaw:
00818         debug("Dumping raw RSA keypair.\n");
00819         RSA_print(bufbio, rsa->rsa, 0);
00820         break;
00821         
00822     default:
00823         seterr("Unknown Mode\n");
00824         return nil;
00825     }
00826 
00827     BIO_get_mem_ptr(bufbio, &bm);
00828     retval.put(bm->data, bm->length);
00829     BIO_free(bufbio);
00830     if (mode == CertDER)
00831     {
00832         WvBase64Encoder enc;
00833         WvString output;
00834         enc.flushbufstr(retval, output, true);
00835         return output;
00836     }
00837     else
00838         return retval.getstr();
00839 }
00840 
00841 void WvX509Mgr::decode(const DumpMode mode, WvStringParm pemEncoded)
00842 {
00843     if (!pemEncoded)
00844     {
00845         debug(WvLog::Error, "Not decoding an empty string. - Sorry!\n");
00846         return;
00847     }
00848     
00849     // Let the fun begin... ;)
00850     AutoClose stupid(tmpfile());
00851     WvString outstring = pemEncoded;
00852     
00853     // I HATE OpenSSL... this is SO Stupid!!!
00854     rewind(stupid);
00855     unsigned int written = fwrite(outstring.edit(), 1, outstring.len(), stupid);
00856     if (written != outstring.len())
00857     {
00858         debug(WvLog::Error,"Couldn't write full amount to temp file!\n");
00859         return;
00860     }
00861     rewind(stupid);
00862     switch(mode)
00863     {
00864     case CertPEM:
00865         debug("Importing X509 certificate.\n");
00866         if(cert)
00867         {
00868             debug("Replacing an already existant X509 Certificate!\n");
00869             X509_free(cert);
00870             cert = NULL;
00871         }
00872         cert = PEM_read_X509(stupid, NULL, NULL, NULL);
00873         if (cert)
00874         {
00875             filldname();
00876             if (!rsa)
00877                 rsa = fillRSAPubKey();
00878         }
00879         else
00880             seterr("Certificate failed to import!");
00881         break;
00882     case RsaPEM:
00883         debug("Importing RSA keypair.\n");
00884         debug("Make sure that you load or generate a new Certificate!\n");
00885         if (rsa) delete rsa;
00886 
00887         rsa = new WvRSAKey(PEM_read_RSAPrivateKey(stupid, NULL, NULL, NULL), 
00888                            true);
00889         if (!rsa->isok())
00890             seterr("RSA Key failed to import\n");
00891         break;
00892     case RsaPubPEM:
00893         debug("Importing RSA Public Key.\n");
00894         debug("Are you REALLY sure that you want to do this?\n");
00895         if (rsa) delete rsa;
00896         rsa = new WvRSAKey(PEM_read_RSAPublicKey(stupid, NULL, NULL, NULL), 
00897                            true);
00898         if (!rsa->isok())
00899             seterr("RSA Public Key failed to import\n");
00900         break;
00901     case RsaRaw:
00902         debug("Importing raw RSA keypair not supported.\n");
00903         break;
00904         
00905     default:
00906         seterr("Unknown Mode\n");
00907     }
00908 }
00909 
00910 
00911 void WvX509Mgr::write_p12(WvStringParm filename)
00912 {
00913     debug("Dumping RSA Key and X509 Cert to PKCS12 structure.\n");
00914 
00915     AutoClose fp = fopen(filename, "wb");
00916 
00917     if (!fp)
00918     {
00919         seterr("Unable to create: %s\n", filename);
00920         return;
00921     }
00922 
00923     if (!!pkcs12pass)
00924     {
00925         if (rsa && cert)
00926         {
00927             EVP_PKEY *pk = EVP_PKEY_new();
00928             if (!pk)
00929             {
00930                 seterr("Unable to create PKEY object.\n");
00931                 return;
00932             }
00933 
00934             if (!EVP_PKEY_set1_RSA(pk, rsa->rsa))
00935             {
00936                 seterr("Error setting RSA keys.\n");
00937                 EVP_PKEY_free(pk);
00938                 return;
00939             }
00940             else
00941             {
00942                 PKCS12 *pkg = PKCS12_create(pkcs12pass.edit(), "foo", pk, 
00943                                             cert, NULL, 0, 0, 0, 0, 0);
00944                 if (pkg)
00945                 {
00946                     debug("Write the PKCS12 object out...\n");
00947                     i2d_PKCS12_fp(fp, pkg);
00948                     PKCS12_free(pkg);
00949                     EVP_PKEY_free(pk);
00950                 }
00951                 else
00952                 {
00953                     seterr("Unable to create PKCS12 object.\n");
00954                     EVP_PKEY_free(pk);
00955                     return;
00956                 }
00957             }
00958         }
00959         else
00960         {
00961             seterr("Either the RSA key or the Certificate is not present\n");
00962             return;
00963         }
00964     }
00965     else
00966     {
00967         seterr("No Password specified for PKCS12 dump\n");
00968         return; 
00969     }
00970 }
00971 
00972 void WvX509Mgr::read_p12(WvStringParm filename)
00973 {
00974     debug("Reading Certificate and Private Key from PKCS12 file: %s\n", filename);
00975 
00976     AutoClose fp = fopen(filename, "r");
00977 
00978     if (!fp)
00979     {
00980         seterr("Unable to read from: %s\n", filename);
00981         return;
00982     }
00983 
00984     if (!!pkcs12pass)
00985     {
00986         PKCS12 *pkg = d2i_PKCS12_fp(fp, NULL);
00987         if (pkg)
00988         {
00989             EVP_PKEY *pk = EVP_PKEY_new();
00990             if (!pk)
00991             {
00992                 seterr("Unable to create PKEY object.\n");
00993                 return;
00994             }
00995             
00996             // Parse out the bits out the PKCS12 package.
00997             PKCS12_parse(pkg, pkcs12pass, &pk, &cert, NULL);
00998             PKCS12_free(pkg);
00999             
01000             // Now, cert should be OK, let's try and set up the RSA stuff
01001             // since we've essentially got a PKEY, and not a WvRSAKey
01002             // We need to create a new WvRSAKey from the PKEY...
01003             rsa = new WvRSAKey(EVP_PKEY_get1_RSA(pk), true);
01004             
01005             // Now that we have both, check to make sure that they match
01006             if (!rsa || !cert || test())
01007             {
01008                 seterr("Could not fill in RSA and Cert with matching values.\n");
01009                 return;
01010             }
01011             EVP_PKEY_free(pk);
01012         }
01013         else
01014         {
01015             seterr("Read in of PKCS12 file '%s' failed - aborting!\n", filename);
01016             return;
01017         }
01018     }
01019     else
01020     {
01021         seterr("No Password specified for PKCS12 file - aborting!\n");
01022         return;
01023     }
01024 }
01025 
01026 
01027 WvString WvX509Mgr::get_issuer()
01028 { 
01029     if (cert)
01030     {
01031         char *name = X509_NAME_oneline(X509_get_issuer_name(cert),0,0);
01032         WvString retval(name);
01033         OPENSSL_free(name);
01034         return retval;
01035     }
01036     else
01037         return WvString::null;
01038 }
01039 
01040 
01041 void WvX509Mgr::set_issuer(WvStringParm issuer)
01042 {
01043     assert(cert);
01044     X509_NAME *name = X509_get_issuer_name(cert);
01045     set_name_entry(name, issuer);
01046     X509_set_issuer_name(cert, name);
01047 }
01048 
01049 
01050 WvString WvX509Mgr::get_subject()
01051 {
01052     if (cert)
01053     {
01054         char *name = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
01055         WvString retval(name);
01056         OPENSSL_free(name);
01057         return retval;
01058     }
01059     else
01060         return WvString::null;
01061 }
01062 
01063 
01064 void WvX509Mgr::set_subject(WvStringParm subject)
01065 {
01066     assert(cert);
01067     X509_NAME *name = X509_get_subject_name(cert);
01068     set_name_entry(name, subject);
01069     X509_set_subject_name(cert, name);
01070 }
01071 
01072 
01073 void WvX509Mgr::set_subject(X509_NAME *name)
01074 {
01075     X509_set_subject_name(cert, name);
01076 }
01077 
01078 
01079 void WvX509Mgr::set_pubkey(WvRSAKey *_rsa)
01080 {
01081     EVP_PKEY *pk = NULL;
01082 
01083     if ((pk = EVP_PKEY_new()) == NULL)
01084     {
01085         seterr("Error creating key handler for new certificate");
01086         return;
01087     }
01088 
01089     // Assign RSA Key from WvRSAKey into stupid package that OpenSSL needs
01090     if (!EVP_PKEY_set1_RSA(pk, rsa->rsa))
01091     {
01092         seterr("Error adding RSA keys to certificate");
01093         return;
01094     }
01095     
01096     X509_set_pubkey(cert, pk);
01097 
01098     if (pk)
01099         EVP_PKEY_free(pk);
01100 }
01101 
01102 
01103 
01104 void WvX509Mgr::set_nsserver(WvStringParm servername)
01105 {
01106     assert(cert);
01107     
01108     WvString fqdn;
01109     
01110     // FQDN cannot have a = in it, therefore it
01111     // must be a distinguished name :)
01112     if (strchr(servername, '='))
01113         fqdn = set_name_entry(NULL, servername);
01114     else
01115         fqdn = servername;
01116     
01117     if (!fqdn)
01118         fqdn = "null.noname.null";
01119     
01120     debug("Setting Netscape SSL server name extension to '%s'.\n", fqdn);
01121 
01122     // Add in the netscape-specific server extension
01123     set_extension(NID_netscape_cert_type, "server");
01124     set_extension(NID_netscape_ssl_server_name, fqdn);
01125 }
01126 
01127 
01128 WvString WvX509Mgr::get_nsserver()
01129 {
01130     return get_extension(NID_netscape_ssl_server_name);
01131 }
01132 
01133 
01134 WvString WvX509Mgr::get_serial()
01135 {
01136     if (cert)
01137     {
01138         return WvString(ASN1_INTEGER_get(X509_get_serialNumber(cert)));
01139     }
01140     else
01141         return WvString::null;
01142 }
01143 
01144 
01145 void WvX509Mgr::set_version()
01146 {
01147         X509_set_version(cert, 0x2);
01148 }
01149 
01150 
01151 void WvX509Mgr::set_serial(long serial)
01152 {
01153     assert(cert);
01154     ASN1_INTEGER_set(X509_get_serialNumber(cert), serial);
01155 }
01156 
01157 
01158 WvString WvX509Mgr::get_crl_dp()
01159 {
01160     return get_extension(NID_crl_distribution_points);
01161 }
01162 
01163 
01164 WvString WvX509Mgr::get_cp_oid()
01165 {
01166     return get_extension(NID_certificate_policies);
01167 }
01168 
01169 void WvX509Mgr::set_cp_oid(WvStringParm oid, WvStringParm _url)
01170 {
01171     assert(cert);
01172     WvString url(_url);
01173     ASN1_OBJECT *pobj = OBJ_txt2obj(oid, 0);
01174     POLICYINFO *pol = POLICYINFO_new();
01175     POLICYQUALINFO *qual = NULL;
01176     STACK_OF(POLICYINFO) *sk_pinfo = sk_POLICYINFO_new_null();
01177     pol->policyid = pobj;
01178     if (!!url)
01179     {
01180         pol->qualifiers = sk_POLICYQUALINFO_new_null();
01181         qual = POLICYQUALINFO_new();
01182         qual->pqualid = OBJ_nid2obj(NID_id_qt_cps);
01183         qual->d.cpsuri = M_ASN1_IA5STRING_new();
01184         ASN1_STRING_set(qual->d.cpsuri, url.edit(), url.len());
01185         sk_POLICYQUALINFO_push(pol->qualifiers, qual);
01186     }
01187     sk_POLICYINFO_push(sk_pinfo, pol);
01188     X509_EXTENSION *ex = X509V3_EXT_i2d(NID_certificate_policies, 0, 
01189                                         sk_pinfo);
01190     X509_add_ext(cert, ex, -1);
01191     X509_EXTENSION_free(ex);
01192     sk_POLICYINFO_free(sk_pinfo);
01193 }
01194 
01195 
01196 void WvX509Mgr::set_lifetime(long seconds)
01197 {
01198     // Set the NotBefore time to now.
01199     X509_gmtime_adj(X509_get_notBefore(cert), 0);
01200     
01201     // Now + 10 years... should be shorter, but since we don't currently
01202     // have a set of routines to refresh the certificates, make it
01203     // REALLY long.
01204     X509_gmtime_adj(X509_get_notAfter(cert), seconds);
01205 }
01206 
01207 
01208 void WvX509Mgr::set_key_usage(WvStringParm values)
01209 {
01210     set_extension(NID_key_usage, values);
01211 }
01212 
01213 
01214 WvString WvX509Mgr::get_key_usage()
01215 {
01216     return get_extension(NID_key_usage);
01217 }
01218 
01219 
01220 void WvX509Mgr::set_ext_key_usage(WvStringParm values)
01221 {
01222     set_extension(NID_ext_key_usage, values);
01223 }
01224 
01225 
01226 WvString WvX509Mgr::get_ext_key_usage()
01227 {
01228     return get_extension(NID_ext_key_usage);
01229 }
01230 
01231 
01232 WvString WvX509Mgr::get_altsubject()
01233 {
01234     return get_extension(NID_subject_alt_name);
01235 }
01236 
01237 
01238 WvString WvX509Mgr::get_constraints()
01239 {
01240     return get_extension(NID_policy_constraints);
01241 }
01242 
01243 
01244 void WvX509Mgr::set_constraints(WvStringParm constraint)
01245 {
01246     assert(cert);
01247     set_extension(NID_policy_constraints, constraint);
01248 }
01249 
01250 
01251 void WvX509Mgr::set_aia(WvStringParm _identifier)
01252 {
01253     WvString identifier(_identifier);
01254     unsigned char *list;
01255     list = reinterpret_cast<unsigned char *>(identifier.edit());
01256     AUTHORITY_INFO_ACCESS *ainfo = sk_ACCESS_DESCRIPTION_new_null();
01257     ACCESS_DESCRIPTION *acc = ACCESS_DESCRIPTION_new();
01258     sk_ACCESS_DESCRIPTION_push(ainfo, acc);
01259     GENERAL_NAME_free(acc->location);
01260     i2d_GENERAL_NAME(acc->location, &list);
01261 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
01262     const unsigned char** plist = const_cast<const unsigned char**>(&list);
01263 #else
01264     unsigned char** plist = &list;
01265 #endif
01266     d2i_GENERAL_NAME(&acc->location, plist, identifier.len());
01267     X509_EXTENSION *ex = X509V3_EXT_i2d(NID_info_access, 0, ainfo);
01268     X509_add_ext(cert, ex, -1);
01269     X509_EXTENSION_free(ex);
01270     sk_ACCESS_DESCRIPTION_free(ainfo);
01271 }
01272 
01273 WvString WvX509Mgr::get_aia()
01274 {
01275     return get_extension(NID_info_access);
01276 }
01277 
01278 WvString WvX509Mgr::get_extension(int nid)
01279 {
01280     WvString retval = WvString::null;
01281     
01282     if (cert)
01283     {
01284         int index = X509_get_ext_by_NID(cert, nid, -1);
01285         if (index >= 0)
01286         {
01287             X509_EXTENSION *ext = X509_get_ext(cert, index);
01288             if (ext)
01289             {
01290                 X509V3_EXT_METHOD *method = X509V3_EXT_get(ext);
01291                 if (!method)
01292                 {
01293                     WvDynBuf buf;
01294                     buf.put(ext->value->data, ext->value->length);
01295                     retval = buf.getstr();
01296                 }
01297                 else
01298                 {
01299                     void *ext_data = NULL;
01300 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
01301                     const unsigned char **ext_value_data;
01302                     ext_value_data = (const_cast<const unsigned char **>
01303                                       (&ext->value->data));
01304 #else
01305                     unsigned char **ext_value_data = &ext->value->data;
01306 #endif
01307                     if (method->it) 
01308                         ext_data = ASN1_item_d2i(NULL, ext_value_data,
01309                                                 ext->value->length, 
01310                                                 ASN1_ITEM_ptr(method->it));
01311                     else
01312                         ext_data = method->d2i(NULL, ext_value_data,
01313                                               ext->value->length);
01314                     
01315                     if (method->i2s)
01316                     {
01317                         retval = method->i2s(method, ext_data);
01318                         if (method->it)
01319                             ASN1_item_free((ASN1_VALUE *)ext_data, ASN1_ITEM_ptr(method->it));
01320                         else
01321                             method->ext_free(ext_data);
01322                     }
01323                     else if (method->i2v)
01324                         retval = "Stack type!";
01325                     else if (method->i2r)
01326                     {
01327                         WvDynBuf retvalbuf;
01328                         BIO *bufbio = BIO_new(BIO_s_mem());
01329                         BUF_MEM *bm;
01330                         method->i2r(method, ext_data, bufbio, 0);
01331                         BIO_get_mem_ptr(bufbio, &bm);
01332                         retvalbuf.put(bm->data, bm->length);
01333                         BIO_free(bufbio);
01334                         retval = retvalbuf.getstr();
01335                         if (method->it)
01336                             ASN1_item_free((ASN1_VALUE *)ext_data, 
01337                                            ASN1_ITEM_ptr(method->it));
01338                     }
01339                 }
01340             }
01341         }
01342     }
01343 
01344     if (!!retval)
01345         return retval;
01346     else
01347         return WvString::null;
01348 }
01349 
01350 void WvX509Mgr::set_extension(int nid, WvStringParm _values)
01351 {
01352     WvString values(_values);
01353     X509_EXTENSION *ex = NULL;
01354     ex = X509V3_EXT_conf_nid(NULL, NULL, nid, values.edit());
01355     X509_add_ext(cert, ex, -1);
01356     X509_EXTENSION_free(ex);
01357 }
01358 
01359 
01360 bool WvX509Mgr::isok() const
01361 {
01362     return cert && rsa && WvError::isok();
01363 }
01364 
01365 
01366 WvString WvX509Mgr::errstr() const
01367 {
01368     if (WvError::geterr() == 0)
01369     {
01370         // only use a custom string if there's not an error set
01371         if (!cert && !rsa)
01372             return "No certificate or RSA key assigned";
01373         else if (!cert)
01374             return "No certificate assigned";
01375         else if (!rsa)
01376             return "No RSA key assigned";
01377     }
01378     return WvError::errstr();
01379 }
01380 
01381 
01382 int WvX509Mgr::geterr() const
01383 {
01384     int ret = WvError::geterr();
01385     if (ret == 0 && (!cert || !rsa))
01386     {
01387         // unless there's a regular error set, we'll be returning a custom
01388         // string: see errstr()
01389         ret = -1;
01390     }
01391     return ret;
01392 }
01393 
01394 
01395 bool WvX509Mgr::signcert(X509 *unsignedcert)
01396 {
01397     if (unsignedcert == NULL)
01398     {
01399         debug("No certificate to sign??\n");
01400         return false;
01401     }
01402 
01403     if (cert == unsignedcert)
01404     {
01405         debug("Self Signing!\n");
01406         printf("Looks like:\n%s\n", encode(WvX509Mgr::CertPEM).cstr());
01407     }
01408     else if (!((cert->ex_flags & EXFLAG_KUSAGE) && 
01409           (cert->ex_kusage & KU_KEY_CERT_SIGN)))
01410     {
01411         debug("This Certificate is not allowed to sign Certificates!\n");
01412         return false;
01413     }
01414     
01415     debug("Ok, now sign the new cert with the current RSA key.\n");
01416     EVP_PKEY *certkey = EVP_PKEY_new();
01417     bool cakeyok = EVP_PKEY_set1_RSA(certkey, rsa->rsa);
01418     if (cakeyok)
01419     {
01420         
01421         X509_sign(unsignedcert, certkey, EVP_sha1());
01422     }
01423     else
01424     {
01425         debug("No keys??\n");
01426         EVP_PKEY_free(certkey);
01427         return false;
01428     }
01429     
01430     EVP_PKEY_free(certkey);
01431     return true;
01432 }
01433 
01434 WvString WvX509Mgr::sign(WvStringParm data)
01435 {
01436     WvDynBuf buf;
01437     buf.putstr(data);
01438     return sign(buf);
01439 }
01440 
01441 WvString WvX509Mgr::sign(WvBuf &data)
01442 {
01443     assert(rsa);
01444 
01445     EVP_MD_CTX sig_ctx;
01446     unsigned char sig_buf[4096];
01447     
01448     EVP_PKEY *pk = EVP_PKEY_new();
01449     if (!pk)
01450     {
01451         seterr("Unable to create PKEY object.\n");
01452         return WvString::null;
01453     }
01454     
01455     if (!EVP_PKEY_set1_RSA(pk, rsa->rsa))
01456     {
01457         seterr("Error setting RSA keys.\n");
01458         EVP_PKEY_free(pk);
01459         return WvString::null;
01460     }
01461     
01462     EVP_SignInit(&sig_ctx, EVP_sha1());
01463     EVP_SignUpdate(&sig_ctx, data.peek(0, data.used()), data.used());
01464     unsigned int sig_len = sizeof(sig_buf);
01465     int sig_err = EVP_SignFinal(&sig_ctx, sig_buf, 
01466                                 &sig_len, pk);
01467     if (sig_err != 1)
01468     {
01469         seterr("Error while signing!\n");
01470         EVP_PKEY_free(pk);
01471         return WvString::null;
01472     }
01473 
01474     EVP_PKEY_free(pk);
01475     EVP_MD_CTX_cleanup(&sig_ctx); // this isn't my fault ://
01476     WvDynBuf buf;
01477     buf.put(sig_buf, sig_len);
01478     debug("Signature size: %s\n", buf.used());
01479     return WvBase64Encoder().strflushbuf(buf, true);
01480 }
01481 
01482 bool WvX509Mgr::verify(WvStringParm original, WvStringParm signature)
01483 {
01484     WvDynBuf buf;
01485     buf.putstr(original);
01486     return verify(buf, signature);
01487 }
01488 
01489 bool WvX509Mgr::verify(WvBuf &original, WvStringParm signature)
01490 {
01491     
01492     unsigned char sig_buf[4096];
01493     size_t sig_size = sizeof(sig_buf);
01494     WvBase64Decoder().flushstrmem(signature, sig_buf, &sig_size, true);
01495     
01496     EVP_PKEY *pk = X509_get_pubkey(cert);
01497     if (!pk) 
01498     {
01499         seterr("Couldn't allocate PKEY for verify()\n");
01500         return false;
01501     }
01502     
01503     /* Verify the signature */
01504     EVP_MD_CTX sig_ctx;
01505     EVP_VerifyInit(&sig_ctx, EVP_sha1());
01506     EVP_VerifyUpdate(&sig_ctx, original.peek(0, original.used()), original.used());
01507     int sig_err = EVP_VerifyFinal(&sig_ctx, sig_buf, sig_size, pk);
01508     EVP_PKEY_free(pk);
01509     EVP_MD_CTX_cleanup(&sig_ctx); // Again, not my fault... 
01510     if (sig_err != 1) 
01511     {
01512         debug("Verify failed!\n");
01513         return false;
01514     }
01515     else
01516         return true;
01517 }
01518 
01519 
01520 ASN1_TIME *WvX509Mgr::get_notvalid_before()
01521 {
01522     assert(cert);
01523     return X509_get_notBefore(cert);
01524 }
01525 
01526 
01527 ASN1_TIME *WvX509Mgr::get_notvalid_after()
01528 {
01529     assert(cert);
01530     return X509_get_notAfter(cert);
01531 }
01532 
01533 
01534 bool WvX509Mgr::signcrl(WvCRLMgr *crl)
01535 {
01536     assert(crl);
01537     assert(rsa);
01538     
01539     if (!((cert->ex_flags & EXFLAG_KUSAGE) && 
01540           (cert->ex_kusage & KU_CRL_SIGN)))
01541     {
01542         debug("Certificate not allowed to sign CRLs!\n");
01543         return false;
01544     }
01545     
01546     EVP_PKEY *certkey = EVP_PKEY_new();
01547     bool cakeyok = EVP_PKEY_set1_RSA(certkey, rsa->rsa);
01548     if (crl->getcrl() && cakeyok)
01549     {
01550         // Use Version 2 CRLs - Of COURSE that means
01551         // to set it to 1 here... grumble..
01552         X509_CRL_set_version(crl->getcrl(), 1);
01553 
01554         X509_CRL_set_issuer_name(crl->getcrl(), X509_get_subject_name(cert));
01555 
01556         ASN1_TIME *tmptm = ASN1_TIME_new();
01557         // Set the LastUpdate time to now.
01558         X509_gmtime_adj(tmptm, 0);
01559         X509_CRL_set_lastUpdate(crl->getcrl(), tmptm);
01560         // CRL's are valid for 30 days
01561         X509_gmtime_adj(tmptm, (long)60*60*24*30);
01562         X509_CRL_set_nextUpdate(crl->getcrl(), tmptm);
01563         ASN1_TIME_free(tmptm);
01564         
01565         // OK - now sign it...
01566         X509_CRL_sign(crl->getcrl(), certkey, EVP_sha1());
01567     }
01568     else
01569     {
01570         debug("No keys??\n");
01571         EVP_PKEY_free(certkey);
01572         return false;
01573     }
01574     EVP_PKEY_free(certkey);
01575 
01576     crl->setca(this);
01577     
01578     return true;
01579 }
01580 
01581 

Generated on Sun Sep 24 20:10:52 2006 for WvStreams by  doxygen 1.4.7