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

Generated on Thu May 25 21:51:04 2006 for WvStreams by  doxygen 1.4.6