WvStreams
|
00001 #include "wvbase64.h" 00002 #include "wvsslhacks.h" 00003 #include "wvx509mgr.h" 00004 #include "wvautoconf.h" 00005 00006 #include <openssl/pem.h> 00007 #include <openssl/x509v3.h> 00008 #include <openssl/err.h> 00009 #include <openssl/ssl.h> 00010 #include <openssl/sha.h> 00011 #include <openssl/pkcs12.h> 00012 00013 00014 namespace { 00015 class AutoClose { 00016 public: 00017 AutoClose(FILE *fp): fp(fp) { } 00018 ~AutoClose() 00019 { 00020 if (fp) 00021 fclose(fp); 00022 } 00023 00024 operator FILE *() const 00025 { 00026 return fp; 00027 } 00028 00029 private: 00030 FILE *fp; 00031 }; 00032 } // anomymous namespace... 00033 00034 00035 WvX509Mgr::WvX509Mgr() 00036 : WvX509(), 00037 debug("X509 Manager", WvLog::Debug5) 00038 { 00039 rsa = NULL; 00040 } 00041 00042 00043 WvX509Mgr::WvX509Mgr(const WvX509Mgr &x) 00044 : WvX509(x), 00045 debug("X509 Manager", WvLog::Debug5) 00046 { 00047 rsa = NULL; 00048 set_rsa(x.rsa); 00049 } 00050 00051 00052 WvX509Mgr::WvX509Mgr(WvStringParm _dname, WvRSAKey *_rsa, bool ca) 00053 : WvX509(), 00054 debug("X509 Manager", WvLog::Debug5) 00055 { 00056 debug("Creating new certificate+key pair for %s.\n", _dname); 00057 rsa = _rsa; 00058 00059 if (!!_dname) 00060 { 00061 create_selfissued(_dname, ca); 00062 debug("Ok - Parameters set... now signing certificate.\n"); 00063 signcert(*this); 00064 } 00065 else 00066 debug("Sorry, can't create an anonymous certificate."); 00067 } 00068 00069 00070 WvX509Mgr::WvX509Mgr(WvStringParm _dname, int bits, bool ca) 00071 : WvX509(), 00072 debug("X509 Manager", WvLog::Debug5) 00073 { 00074 debug("Creating new certificate+key pair for %s.\n", _dname); 00075 rsa = NULL; 00076 00077 if (!!_dname) 00078 { 00079 rsa = new WvRSAKey(bits); 00080 create_selfissued(_dname, ca); 00081 debug("Ok - Parameters set... now signing certificate.\n"); 00082 signcert(*this); 00083 } 00084 else 00085 debug("Sorry, can't create an anonymous certificate."); 00086 } 00087 00088 00089 void WvX509Mgr::create_selfissued(WvStringParm dname, bool is_ca) 00090 { 00091 if (cert) 00092 { 00093 debug("Replacing already existant certificate...\n"); 00094 X509_free(cert); 00095 cert = NULL; 00096 } 00097 00098 // double check RSA key 00099 if (rsa->isok()) 00100 debug("RSA Key is fine.\n"); 00101 else 00102 return; 00103 00104 if ((cert = X509_new()) == NULL) 00105 return; 00106 00107 // Completely broken in my mind - this sets the version 00108 // string to '3' (I guess version starts at 0) 00109 set_version(); 00110 00111 // RFC2459 says that this number must be unique for each certificate 00112 // issued by a CA. It may be that some web browsers get confused if 00113 // more than one cert with the same name has the same serial number, so 00114 // let's be careful. 00115 srand(time(NULL)); 00116 int serial = rand(); 00117 set_serial(serial); 00118 00119 // 10 years... 00120 set_lifetime(60*60*24*3650); 00121 00122 set_pubkey(*rsa); 00123 00124 set_issuer(dname); 00125 set_subject(dname); 00126 set_ski(); 00127 00128 if (is_ca) 00129 { 00130 debug("Setting Extensions with CA Parameters.\n"); 00131 debug("Setting Key Usage.\n"); 00132 set_key_usage("critical, keyCertSign, cRLSign"); 00133 debug("Setting Basic Constraints.\n"); 00134 set_extension(NID_basic_constraints, "critical, CA:TRUE"); 00135 debug("Setting Netscape Certificate Type.\n"); 00136 set_extension(NID_netscape_cert_type, 00137 "SSL CA, S/MIME CA, Object Signing CA"); 00138 #if 0 00139 // uncomment this to allow certificate to be used as 00140 // an OCSP signer (seems too obscure to enable by default 00141 // right now). 00142 set_ext_key_usage("OCSP Signing"); 00143 #endif 00144 // debug("Setting Constraints.\n"); 00145 // set_constraints("requireExplicitPolicy"); 00146 } 00147 else 00148 { 00149 debug("Setting Key Usage with normal server parameters\n"); 00150 set_nsserver(dname); 00151 set_key_usage("critical, digitalSignature, keyEncipherment, " 00152 "keyAgreement"); 00153 set_extension(NID_basic_constraints, "CA:FALSE"); 00154 set_ext_key_usage("TLS Web Server Authentication," 00155 "TLS Web Client Authentication"); 00156 } 00157 00158 // we do not actually sign the certificate here: that must be done by the 00159 // user (WvX509Mgr most likely) 00160 00161 debug("Certificate for %s created\n", dname); 00162 } 00163 00164 00165 WvX509Mgr::~WvX509Mgr() 00166 { 00167 debug("Deleting.\n"); 00168 WVDELETE(rsa); 00169 } 00170 00171 00172 bool WvX509Mgr::isok() const 00173 { 00174 return WvX509::isok() && rsa && rsa->isok() && test(); 00175 } 00176 00177 00178 bool WvX509Mgr::operator! () const 00179 { 00180 return !isok(); 00181 } 00182 00183 00184 WvString WvX509Mgr::errstr() const 00185 { 00186 if (!WvX509::isok()) 00187 return WvX509::errstr(); 00188 00189 if (!rsa) 00190 return "No RSA key set."; 00191 else if (!rsa->isok()) 00192 return "RSA key not valid."; 00193 else if (!test()) 00194 return "RSA key and certificate do not match."; 00195 00196 return WvString::empty; 00197 } 00198 00199 00200 bool WvX509Mgr::bind_ssl(SSL_CTX *ctx) 00201 { 00202 if (SSL_CTX_use_certificate(ctx, get_cert()) <= 0) 00203 { 00204 return false; 00205 } 00206 debug("Certificate activated.\n"); 00207 00208 if (SSL_CTX_use_RSAPrivateKey(ctx, rsa->rsa) <= 0) 00209 { 00210 return false; 00211 } 00212 debug("RSA private key activated.\n"); 00213 return true; 00214 } 00215 00216 00217 bool WvX509Mgr::test() const 00218 { 00219 if (!cert) 00220 { 00221 debug("No X509 certificate: test fails.\n"); 00222 return false; 00223 } 00224 00225 if (rsa) 00226 { 00227 EVP_PKEY *pk = EVP_PKEY_new(); 00228 assert(pk); 00229 00230 if (!EVP_PKEY_set1_RSA(pk, rsa->rsa)) 00231 { 00232 debug("Error setting RSA keys: test fails.\n"); 00233 EVP_PKEY_free(pk); 00234 return false; 00235 } 00236 00237 bool bad = false; 00238 int verify_return = X509_verify(cert, pk); 00239 00240 if (verify_return != 1) // only '1' means okay 00241 { 00242 // However let's double check: 00243 WvString rsapub = rsa->encode(WvRSAKey::RsaPubPEM); 00244 WvRSAKey *temprsa = get_rsa_pub(); 00245 WvString certpub = temprsa->encode(WvRSAKey::RsaPubPEM); 00246 delete temprsa; 00247 // debug("rsapub:\n%s\n", rsapub); 00248 // debug("certpub:\n%s\n", certpub); 00249 if (certpub == rsapub) 00250 ; // do nothing, since OpenSSL is lying 00251 else 00252 { 00253 // I guess that it really did fail. 00254 debug("Certificate test failed: %s\n", wvssl_errstr()); 00255 bad = true; 00256 } 00257 } 00258 00259 EVP_PKEY_free(pk); 00260 return !bad; 00261 } 00262 00263 return false; 00264 } 00265 00266 00267 WvString WvX509Mgr::signreq(WvStringParm pkcs10req) const 00268 { 00269 debug("Signing a certificate request with: %s\n", get_subject()); 00270 if (!isok()) 00271 { 00272 debug(WvLog::Warning, "Asked to sign certificate request, but not ok! " 00273 "Aborting.\n"); 00274 return false; 00275 } 00276 00277 // Break this next part out into a de-pemify section, since that is what 00278 // this part up until the FIXME: is about. 00279 WvString pkcs10(pkcs10req); 00280 00281 BIO *membuf = BIO_new(BIO_s_mem()); 00282 BIO_write(membuf, pkcs10req, pkcs10req.len()); 00283 00284 X509_REQ *certreq = PEM_read_bio_X509_REQ(membuf, NULL, NULL, NULL); 00285 BIO_free_all(membuf); 00286 00287 if (certreq) 00288 { 00289 WvX509 newcert(X509_new()); 00290 00291 newcert.set_subject(X509_REQ_get_subject_name(certreq)); 00292 newcert.set_version(); 00293 00294 // Set the Serial Number for the certificate 00295 srand(time(NULL)); 00296 int serial = rand(); 00297 newcert.set_serial(serial); 00298 00299 newcert.set_lifetime(60*60*24*3650); 00300 00301 // The public key of the new cert should be the same as that from 00302 // the request. 00303 EVP_PKEY *pk = X509_REQ_get_pubkey(certreq); 00304 X509_set_pubkey(newcert.get_cert(), pk); 00305 EVP_PKEY_free(pk); 00306 00307 // every good cert needs an ski+aki 00308 newcert.set_ski(); 00309 newcert.set_aki(*this); 00310 00311 // The Issuer name is the subject name of the current cert 00312 newcert.set_issuer(*this); 00313 00314 X509_EXTENSION *ex = NULL; 00315 // Set the RFC2459-mandated keyUsage field to critical, and restrict 00316 // the usage of this cert to digital signature and key encipherment. 00317 newcert.set_key_usage("critical, digitalSignature, keyEncipherment"); 00318 00319 // This could cause Netscape to barf because if we set 00320 // basicConstraints to critical, we break RFC2459 compliance. Why 00321 // they chose to enforce that bit, and not the rest is beyond me... 00322 // but oh well... 00323 ex = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, 00324 (char*)"CA:FALSE"); 00325 00326 X509_add_ext(newcert.get_cert(), ex, -1); 00327 X509_EXTENSION_free(ex); 00328 00329 newcert.set_ext_key_usage("critical, TLS Web Client Authentication"); 00330 00331 signcert(newcert); 00332 00333 X509_REQ_free(certreq); 00334 return WvString(newcert.encode(WvX509::CertPEM)); 00335 } 00336 else 00337 { 00338 debug("Can't decode Certificate Request\n"); 00339 return WvString::null; 00340 } 00341 } 00342 00343 00344 bool WvX509Mgr::signcert(WvX509 &unsignedcert) const 00345 { 00346 if (!isok()) 00347 { 00348 debug(WvLog::Warning, "Asked to sign certificate, but not ok! " 00349 "Aborting.\n"); 00350 return false; 00351 } 00352 00353 if (cert == unsignedcert.cert) 00354 { 00355 debug("Self Signing!\n"); 00356 } 00357 #ifdef HAVE_OPENSSL_POLICY_MAPPING 00358 else if (!X509_check_ca(cert)) 00359 { 00360 debug("This certificate is not a CA, and is thus not allowed to sign " 00361 "certificates!\n"); 00362 return false; 00363 } 00364 #endif 00365 else if (!((cert->ex_flags & EXFLAG_KUSAGE) && 00366 (cert->ex_kusage & KU_KEY_CERT_SIGN))) 00367 { 00368 debug("This Certificate is not allowed to sign certificates!\n"); 00369 return false; 00370 } 00371 00372 debug("Ok, now sign the new cert with the current RSA key.\n"); 00373 EVP_PKEY *certkey = EVP_PKEY_new(); 00374 bool cakeyok = EVP_PKEY_set1_RSA(certkey, rsa->rsa); 00375 if (cakeyok) 00376 { 00377 X509_sign(unsignedcert.get_cert(), certkey, EVP_sha1()); 00378 } 00379 else 00380 { 00381 debug("No keys??\n"); 00382 EVP_PKEY_free(certkey); 00383 return false; 00384 } 00385 00386 EVP_PKEY_free(certkey); 00387 return true; 00388 } 00389 00390 00391 bool WvX509Mgr::signcrl(WvCRL &crl) const 00392 { 00393 if (!isok() || !crl.isok()) 00394 { 00395 debug(WvLog::Warning, "Asked to sign CRL, but certificate or CRL (or " 00396 "both) not ok! Aborting.\n"); 00397 return false; 00398 } 00399 #ifdef HAVE_OPENSSL_POLICY_MAPPING 00400 else if (!X509_check_ca(cert)) 00401 { 00402 debug("This certificate is not a CA, and is thus not allowed to sign " 00403 "CRLs!\n"); 00404 return false; 00405 } 00406 else if (!((cert->ex_flags & EXFLAG_KUSAGE) && 00407 (cert->ex_kusage & KU_CRL_SIGN))) 00408 { 00409 debug("Certificate not allowed to sign CRLs! (%s %s)\n", 00410 (cert->ex_flags & EXFLAG_KUSAGE), 00411 (cert->ex_kusage & KU_CRL_SIGN)); 00412 return false; 00413 } 00414 #endif 00415 00416 EVP_PKEY *certkey = EVP_PKEY_new(); 00417 bool cakeyok = EVP_PKEY_set1_RSA(certkey, rsa->rsa); 00418 if (cakeyok) 00419 { 00420 ASN1_TIME *tmptm = ASN1_TIME_new(); 00421 // Set the LastUpdate time to now. 00422 X509_gmtime_adj(tmptm, 0); 00423 X509_CRL_set_lastUpdate(crl.getcrl(), tmptm); 00424 // CRL's are valid for 30 days 00425 X509_gmtime_adj(tmptm, (long)60*60*24*30); 00426 X509_CRL_set_nextUpdate(crl.getcrl(), tmptm); 00427 ASN1_TIME_free(tmptm); 00428 00429 // OK - now sign it... 00430 X509_CRL_sign(crl.getcrl(), certkey, EVP_sha1()); 00431 } 00432 else 00433 { 00434 debug(WvLog::Warning, "Asked to sign CRL, but no RSA key associated " 00435 "with certificate. Aborting.\n"); 00436 EVP_PKEY_free(certkey); 00437 return false; 00438 } 00439 EVP_PKEY_free(certkey); 00440 00441 return true; 00442 } 00443 00444 00445 WvString WvX509Mgr::sign(WvStringParm data) const 00446 { 00447 WvDynBuf buf; 00448 buf.putstr(data); 00449 return sign(buf); 00450 } 00451 00452 00453 WvString WvX509Mgr::sign(WvBuf &data) const 00454 { 00455 assert(rsa); 00456 00457 EVP_MD_CTX sig_ctx; 00458 unsigned char sig_buf[4096]; 00459 00460 EVP_PKEY *pk = EVP_PKEY_new(); 00461 assert(pk); // OOM 00462 00463 if (!EVP_PKEY_set1_RSA(pk, rsa->rsa)) 00464 { 00465 debug("Error setting RSA keys.\n"); 00466 EVP_PKEY_free(pk); 00467 return WvString::null; 00468 } 00469 00470 EVP_SignInit(&sig_ctx, EVP_sha1()); 00471 EVP_SignUpdate(&sig_ctx, data.peek(0, data.used()), data.used()); 00472 unsigned int sig_len = sizeof(sig_buf); 00473 int sig_err = EVP_SignFinal(&sig_ctx, sig_buf, 00474 &sig_len, pk); 00475 if (sig_err != 1) 00476 { 00477 debug("Error while signing.\n"); 00478 EVP_PKEY_free(pk); 00479 return WvString::null; 00480 } 00481 00482 EVP_PKEY_free(pk); 00483 EVP_MD_CTX_cleanup(&sig_ctx); // this isn't my fault :// 00484 WvDynBuf buf; 00485 buf.put(sig_buf, sig_len); 00486 debug("Signature size: %s\n", buf.used()); 00487 return WvBase64Encoder().strflushbuf(buf, true); 00488 } 00489 00490 00491 bool WvX509Mgr::write_p12(WvStringParm _fname, WvStringParm _pkcs12pass) const 00492 { 00493 debug("Dumping RSA Key and X509 Cert to PKCS12 structure.\n"); 00494 00495 AutoClose fp = fopen(_fname, "wb"); 00496 00497 if (!fp) 00498 { 00499 debug(WvLog::Warning, "Unable to open file. Error: %s\n", 00500 strerror(errno)); 00501 return false; 00502 } 00503 00504 if (!!_pkcs12pass) 00505 { 00506 if (rsa && cert) 00507 { 00508 EVP_PKEY *pk = EVP_PKEY_new(); 00509 assert(pk); // OOM 00510 00511 if (!EVP_PKEY_set1_RSA(pk, rsa->rsa)) 00512 { 00513 debug("Error setting RSA keys.\n"); 00514 EVP_PKEY_free(pk); 00515 return false; 00516 } 00517 else 00518 { 00519 WvString pkcs12pass(_pkcs12pass); 00520 PKCS12 *pkg 00521 = PKCS12_create(pkcs12pass.edit(), (char*)"foo", pk, 00522 cert, NULL, 0, 0, 0, 00523 0, 0); 00524 if (pkg) 00525 { 00526 debug("Writing the PKCS12 object out...\n"); 00527 i2d_PKCS12_fp(fp, pkg); 00528 PKCS12_free(pkg); 00529 EVP_PKEY_free(pk); 00530 } 00531 else 00532 { 00533 debug(WvLog::Warning, "Unable to create PKCS12 object."); 00534 EVP_PKEY_free(pk); 00535 return false; 00536 } 00537 } 00538 } 00539 else 00540 { 00541 debug(WvLog::Warning, 00542 "The RSA key or the certificate is not present."); 00543 return false; 00544 } 00545 } 00546 else 00547 { 00548 debug(WvLog::Warning, "No password specified for PKCS12 dump."); 00549 return false; 00550 } 00551 00552 return true; 00553 } 00554 00555 00556 void WvX509Mgr::read_p12(WvStringParm _fname, WvStringParm _pkcs12pass) 00557 { 00558 debug("Reading Certificate and Private Key from PKCS12 file: %s\n", 00559 _fname); 00560 00561 if (rsa) 00562 WVDELETE(rsa); 00563 00564 AutoClose fp = fopen(_fname, "r"); 00565 00566 if (!fp) 00567 { 00568 debug("Unable to open file '%s'!\n", _fname); 00569 return; 00570 } 00571 00572 if (!!_pkcs12pass) 00573 { 00574 PKCS12 *pkg = d2i_PKCS12_fp(fp, NULL); 00575 if (pkg) 00576 { 00577 EVP_PKEY *pk = NULL; 00578 00579 // Parse out the bits out the PKCS12 package. 00580 X509 *x; 00581 PKCS12_parse(pkg, _pkcs12pass, &pk, &x, NULL); 00582 PKCS12_free(pkg); 00583 if (!pk || !x) 00584 { 00585 debug("Could not decode pkcs12 file.\n"); 00586 EVP_PKEY_free(pk); 00587 return; 00588 } 00589 00590 cert = x; 00591 00592 // Now, cert should be OK, let's try and set up the RSA stuff 00593 // since we've essentially got a PKEY, and not a WvRSAKey 00594 // We need to create a new WvRSAKey from the PKEY... 00595 rsa = new WvRSAKey(EVP_PKEY_get1_RSA(pk), true); 00596 EVP_PKEY_free(pk); 00597 00598 // Now that we have both, check to make sure that they match 00599 if (!test()) 00600 { 00601 debug("Could not fill in RSA and certificate with matching " 00602 "values! Expect problems.\n"); 00603 return; 00604 } 00605 } 00606 else 00607 { 00608 debug("Read in of PKCS12 file '%s' failed", _fname); 00609 return; 00610 } 00611 } 00612 else 00613 { 00614 debug("No password specified for PKCS12 file\n"); 00615 return; 00616 } 00617 } 00618 00619 00620 WvString WvX509Mgr::encode(const WvRSAKey::DumpMode mode) const 00621 { 00622 if (rsa) 00623 return rsa->encode(mode); 00624 return ""; 00625 } 00626 00627 00628 WvString WvX509Mgr::encode(const WvX509::DumpMode mode) const 00629 { 00630 return WvX509::encode(mode); 00631 } 00632 00633 00634 void WvX509Mgr::encode(const WvRSAKey::DumpMode mode, WvBuf &buf) const 00635 { 00636 if (rsa) 00637 rsa->encode(mode, buf); 00638 } 00639 00640 00641 void WvX509Mgr::encode(const WvX509::DumpMode mode, WvBuf &buf) const 00642 { 00643 WvX509::encode(mode, buf); 00644 } 00645 00646 00647 void WvX509Mgr::decode(const WvRSAKey::DumpMode mode, WvStringParm encoded) 00648 { 00649 if (rsa) 00650 rsa->decode(mode, encoded); 00651 else 00652 { 00653 rsa = new WvRSAKey(); 00654 rsa->decode(mode, encoded); 00655 } 00656 } 00657 00658 00659 void WvX509Mgr::decode(const WvX509::DumpMode mode, WvStringParm encoded) 00660 { 00661 WvX509::decode(mode, encoded); 00662 } 00663 00664 00665 void WvX509Mgr::decode(const WvRSAKey::DumpMode mode, WvBuf &encoded) 00666 { 00667 if (rsa) 00668 rsa->decode(mode, encoded); 00669 else 00670 { 00671 rsa = new WvRSAKey(); 00672 rsa->decode(mode, encoded); 00673 } 00674 } 00675 00676 00677 void WvX509Mgr::decode(const WvX509::DumpMode mode, WvBuf &encoded) 00678 { 00679 WvX509::decode(mode, encoded); 00680 }