2 #include "wvsslhacks.h"
4 #include "wvautoconf.h"
6 #include <openssl/pem.h>
7 #include <openssl/x509v3.h>
8 #include <openssl/err.h>
9 #include <openssl/ssl.h>
10 #include <openssl/sha.h>
11 #include <openssl/pkcs12.h>
17 AutoClose(FILE *fp): fp(fp) { }
24 operator FILE *()
const
37 debug(
"X509 Manager",
WvLog::Debug5)
45 debug(
"X509 Manager",
WvLog::Debug5)
54 debug(
"X509 Manager",
WvLog::Debug5)
56 debug(
"Creating new certificate+key pair for %s.\n", _dname);
62 debug(
"Ok - Parameters set... now signing certificate.\n");
66 debug(
"Sorry, can't create an anonymous certificate.");
72 debug(
"X509 Manager",
WvLog::Debug5)
74 debug(
"Creating new certificate+key pair for %s.\n", _dname);
81 debug(
"Ok - Parameters set... now signing certificate.\n");
85 debug(
"Sorry, can't create an anonymous certificate.");
93 debug(
"Replacing already existant certificate...\n");
100 debug(
"RSA Key is fine.\n");
104 if ((cert = X509_new()) == NULL)
130 debug(
"Setting Extensions with CA Parameters.\n");
131 debug(
"Setting Key Usage.\n");
132 set_key_usage(
"critical, keyCertSign, cRLSign");
133 debug(
"Setting Basic Constraints.\n");
134 set_extension(NID_basic_constraints,
"critical, CA:TRUE");
135 debug(
"Setting Netscape Certificate Type.\n");
136 set_extension(NID_netscape_cert_type,
137 "SSL CA, S/MIME CA, Object Signing CA");
142 set_ext_key_usage(
"OCSP Signing");
149 debug(
"Setting Key Usage with normal server parameters\n");
151 set_key_usage(
"critical, digitalSignature, keyEncipherment, "
153 set_extension(NID_basic_constraints,
"CA:FALSE");
154 set_ext_key_usage(
"TLS Web Server Authentication,"
155 "TLS Web Client Authentication");
161 debug(
"Certificate for %s created\n", dname);
167 debug(
"Deleting.\n");
190 return "No RSA key set.";
191 else if (!rsa->isok())
192 return "RSA key not valid.";
194 return "RSA key and certificate do not match.";
196 return WvString::empty;
202 if (SSL_CTX_use_certificate(ctx,
get_cert()) <= 0)
206 debug(
"Certificate activated.\n");
208 if (SSL_CTX_use_RSAPrivateKey(ctx, rsa->rsa) <= 0)
212 debug(
"RSA private key activated.\n");
221 debug(
"No X509 certificate: test fails.\n");
227 EVP_PKEY *pk = EVP_PKEY_new();
230 if (!EVP_PKEY_set1_RSA(pk, rsa->rsa))
232 debug(
"Error setting RSA keys: test fails.\n");
238 int verify_return = X509_verify(cert, pk);
240 if (verify_return != 1)
249 if (certpub == rsapub)
254 debug(
"Certificate test failed: %s\n", wvssl_errstr());
269 debug(
"Signing a certificate request with: %s\n",
get_subject());
272 debug(WvLog::Warning,
"Asked to sign certificate request, but not ok! "
281 BIO *membuf = BIO_new(BIO_s_mem());
282 BIO_write(membuf, pkcs10req, pkcs10req.len());
284 X509_REQ *
certreq = PEM_read_bio_X509_REQ(membuf, NULL, NULL, NULL);
285 BIO_free_all(membuf);
289 WvX509 newcert(X509_new());
291 newcert.set_subject(X509_REQ_get_subject_name(certreq));
297 newcert.set_serial(serial);
303 EVP_PKEY *pk = X509_REQ_get_pubkey(certreq);
304 X509_set_pubkey(newcert.
get_cert(), pk);
309 newcert.set_aki(*
this);
312 newcert.set_issuer(*
this);
314 X509_EXTENSION *ex = NULL;
317 newcert.set_key_usage(
"critical, digitalSignature, keyEncipherment");
323 ex = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints,
326 X509_add_ext(newcert.
get_cert(), ex, -1);
327 X509_EXTENSION_free(ex);
329 newcert.set_ext_key_usage(
"critical, TLS Web Client Authentication");
333 X509_REQ_free(certreq);
338 debug(
"Can't decode Certificate Request\n");
339 return WvString::null;
348 debug(WvLog::Warning,
"Asked to sign certificate, but not ok! "
353 if (cert == unsignedcert.cert)
355 debug(
"Self Signing!\n");
357 #ifdef HAVE_OPENSSL_POLICY_MAPPING
358 else if (!X509_check_ca(cert))
360 debug(
"This certificate is not a CA, and is thus not allowed to sign "
365 else if (!((cert->ex_flags & EXFLAG_KUSAGE) &&
366 (cert->ex_kusage & KU_KEY_CERT_SIGN)))
368 debug(
"This Certificate is not allowed to sign certificates!\n");
372 debug(
"Ok, now sign the new cert with the current RSA key.\n");
373 EVP_PKEY *certkey = EVP_PKEY_new();
374 bool cakeyok = EVP_PKEY_set1_RSA(certkey, rsa->rsa);
377 X509_sign(unsignedcert.
get_cert(), certkey, EVP_sha1());
381 debug(
"No keys??\n");
382 EVP_PKEY_free(certkey);
386 EVP_PKEY_free(certkey);
395 debug(WvLog::Warning,
"Asked to sign CRL, but certificate or CRL (or "
396 "both) not ok! Aborting.\n");
399 #ifdef HAVE_OPENSSL_POLICY_MAPPING
400 else if (!X509_check_ca(cert))
402 debug(
"This certificate is not a CA, and is thus not allowed to sign "
406 else if (!((cert->ex_flags & EXFLAG_KUSAGE) &&
407 (cert->ex_kusage & KU_CRL_SIGN)))
409 debug(
"Certificate not allowed to sign CRLs! (%s %s)\n",
410 (cert->ex_flags & EXFLAG_KUSAGE),
411 (cert->ex_kusage & KU_CRL_SIGN));
416 EVP_PKEY *certkey = EVP_PKEY_new();
417 bool cakeyok = EVP_PKEY_set1_RSA(certkey, rsa->rsa);
420 ASN1_TIME *tmptm = ASN1_TIME_new();
422 X509_gmtime_adj(tmptm, 0);
423 X509_CRL_set_lastUpdate(crl.
getcrl(), tmptm);
425 X509_gmtime_adj(tmptm, (
long)60*60*24*30);
426 X509_CRL_set_nextUpdate(crl.
getcrl(), tmptm);
427 ASN1_TIME_free(tmptm);
430 X509_CRL_sign(crl.
getcrl(), certkey, EVP_sha1());
434 debug(WvLog::Warning,
"Asked to sign CRL, but no RSA key associated "
435 "with certificate. Aborting.\n");
436 EVP_PKEY_free(certkey);
439 EVP_PKEY_free(certkey);
458 unsigned char sig_buf[4096];
460 EVP_PKEY *pk = EVP_PKEY_new();
463 if (!EVP_PKEY_set1_RSA(pk, rsa->rsa))
465 debug(
"Error setting RSA keys.\n");
467 return WvString::null;
470 EVP_SignInit(&sig_ctx, EVP_sha1());
471 EVP_SignUpdate(&sig_ctx, data.
peek(0, data.
used()), data.
used());
472 unsigned int sig_len =
sizeof(sig_buf);
473 int sig_err = EVP_SignFinal(&sig_ctx, sig_buf,
477 debug(
"Error while signing.\n");
479 return WvString::null;
483 EVP_MD_CTX_cleanup(&sig_ctx);
485 buf.put(sig_buf, sig_len);
486 debug(
"Signature size: %s\n", buf.
used());
493 debug(
"Dumping RSA Key and X509 Cert to PKCS12 structure.\n");
495 AutoClose fp = fopen(_fname,
"wb");
499 debug(WvLog::Warning,
"Unable to open file. Error: %s\n",
508 EVP_PKEY *pk = EVP_PKEY_new();
511 if (!EVP_PKEY_set1_RSA(pk, rsa->rsa))
513 debug(
"Error setting RSA keys.\n");
521 = PKCS12_create(pkcs12pass.
edit(), (
char*)
"foo", pk,
526 debug(
"Writing the PKCS12 object out...\n");
527 i2d_PKCS12_fp(fp, pkg);
533 debug(WvLog::Warning,
"Unable to create PKCS12 object.");
541 debug(WvLog::Warning,
542 "The RSA key or the certificate is not present.");
548 debug(WvLog::Warning,
"No password specified for PKCS12 dump.");
558 debug(
"Reading Certificate and Private Key from PKCS12 file: %s\n",
564 AutoClose fp = fopen(_fname,
"r");
568 debug(
"Unable to open file '%s'!\n", _fname);
574 PKCS12 *pkg = d2i_PKCS12_fp(fp, NULL);
581 PKCS12_parse(pkg, _pkcs12pass, &pk, &x, NULL);
585 debug(
"Could not decode pkcs12 file.\n");
595 rsa =
new WvRSAKey(EVP_PKEY_get1_RSA(pk),
true);
601 debug(
"Could not fill in RSA and certificate with matching "
602 "values! Expect problems.\n");
608 debug(
"Read in of PKCS12 file '%s' failed", _fname);
614 debug(
"No password specified for PKCS12 file\n");
650 rsa->
decode(mode, encoded);
654 rsa->
decode(mode, encoded);
668 rsa->
decode(mode, encoded);
672 rsa->
decode(mode, encoded);
bool isok() const
Do we have any errors...
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
WvString sign(WvBuf &data) const
Sign the contents of data and return the signature as a BASE64 string.
WvString encode(const DumpMode mode) const
Return the information requested by mode.
void read_p12(WvStringParm _fname, WvStringParm _pkcs12pass)
And this reads from the file specified in filename using the password "_pkcs12pass", and fills the RSA and cert members with the decoded information.
X509_CRL * getcrl()
Accessor for CRL.
virtual ~WvX509Mgr()
Destructor.
WvString strflushbuf(WvBuf &inbuf, bool finish=false)
Flushes data through the encoder from a buffer to a string.
WvString get_subject() const
get and set the Subject field of the certificate
void set_pubkey(WvRSAKey &rsa_pubkey)
Set the public key of the certificate to the public key rsa_pubkey.
virtual void decode(const WvX509::DumpMode mode, WvStringParm encoded)
Load the information from the format requested by mode into the class - this overwrites the certifica...
virtual void decode(const DumpMode mode, WvStringParm str)
Load the information from the format requested by mode into the class - this overwrites the certifica...
virtual bool isok() const
Says if this certificate+key pair is good for use.
X509 Class to handle certificates and their related functions.
virtual WvString encode(const WvX509::DumpMode mode) const
Encodes the information requested by mode into a buffer.
char * edit()
make the string editable, and return a non-const (char*)
bool write_p12(WvStringParm _fname, WvStringParm _pkcs12pass) const
This writes the certificate and RSA keys in PKCS12 format to the file specified by filename...
WvX509Mgr()
Constructor to create a blank certificate + keypair (useful if, for example, you were going to load t...
virtual bool isok() const
Is the certificate object valid?
Specialization of WvBufBase for unsigned char type buffers intended for use with raw memory buffers...
virtual WvString errstr() const
Returns an error string if isok() is not true.
bool signcert(WvX509 &unsignedcert) const
Sign the certificate with the rsa key associated with this class.
size_t used() const
Returns the number of elements in the buffer currently available for reading.
void set_version()
Set the Certificate to use X509v3, since that's all modern PKI uses anyways :)
bool test() const
Test to make sure that a certificate and a keypair go together.
WvString signreq(WvStringParm pkcs10req) const
Take the PKCS#10 request in the string pkcs10req, sign it with the private key in rsa...
DumpMode
Type for the encode() and decode() methods.
X509 * get_cert()
Allow us to access the certificate member - this will be going away eventually, but for now...
const T * peek(int offset, size_t count)
Returns a const pointer into the buffer at the specified offset to the specified number of elements w...
bool operator!() const
The not operator returns true if !isok()
virtual void decode(const DumpMode mode, WvStringParm encoded)
Load the information from the format requested by mode into the class - this overwrites the certifica...
bool bind_ssl(SSL_CTX *ctx)
Avoid a lot of ugliness by having it so that we are binding to the SSL context, and not the other way...
virtual WvString encode(const DumpMode mode) const
Return the information requested by mode.
void create_selfissued(WvStringParm dname, bool is_ca=false)
Given the Distinguished Name dname and an already generated keypair in rsa, return a Self Signed Cert...
An RSA public key or public/private key pair that can be used for encryption.
WvString is an implementation of a simple and efficient printable-string class.
void set_lifetime(long seconds)
Set the lifetime to be used for this certificate...
void putstr(WvStringParm str)
Copies a WvString into the buffer, excluding the null-terminator.
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's...
CRL Class to handle certificate revocation lists and their related functions.
static WvString certreq(WvStringParm subject, const WvRSAKey &rsa)
Create a certificate request (PKCS#10) using this function.
virtual WvString errstr() const
Says what the error is, if isok() is not true.
bool signcrl(WvCRL &unsignedcrl) const
Sign the CRL with the rsa key associated with this class.
DumpMode
Type for the encode() and decode() methods.