diff options
author | ssuda <sambasivarao@gmail.com> | 2012-05-14 01:08:23 +0530 |
---|---|---|
committer | Ben Noordhuis <info@bnoordhuis.nl> | 2012-05-14 17:12:59 +0200 |
commit | fb7348ae060bf9dd4b0521ac2533fc1d66c44d8b (patch) | |
tree | 0fb6d3419831be14ba09275d3f940779add629eb /src/node_crypto.cc | |
parent | bd907174e8082afd6dd8553940aac09cae3dcfb7 (diff) | |
download | node-fb7348ae060bf9dd4b0521ac2533fc1d66c44d8b.tar.gz |
crypto: add PKCS12/PFX support
Fixes #2845.
Diffstat (limited to 'src/node_crypto.cc')
-rw-r--r-- | src/node_crypto.cc | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/node_crypto.cc b/src/node_crypto.cc index bf95d7970..b2858f508 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -43,6 +43,7 @@ # include <pthread.h> #endif + #if OPENSSL_VERSION_NUMBER >= 0x10000000L # define OPENSSL_CONST const #else @@ -169,6 +170,7 @@ void SecureContext::Initialize(Handle<Object> target) { NODE_SET_PROTOTYPE_METHOD(t, "setSessionIdContext", SecureContext::SetSessionIdContext); NODE_SET_PROTOTYPE_METHOD(t, "close", SecureContext::Close); + NODE_SET_PROTOTYPE_METHOD(t, "loadPKCS12", SecureContext::LoadPKCS12); target->Set(String::NewSymbol("SecureContext"), t->GetFunction()); } @@ -595,6 +597,83 @@ Handle<Value> SecureContext::Close(const Arguments& args) { return False(); } +//Takes .pfx or .p12 and password in string or buffer format +Handle<Value> SecureContext::LoadPKCS12(const Arguments& args) { + HandleScope scope; + + BIO* in = NULL; + PKCS12* p12 = NULL; + EVP_PKEY* pkey = NULL; + X509* cert = NULL; + STACK_OF(X509)* extraCerts = NULL; + char* pass = NULL; + bool ret = false; + + SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.Holder()); + + if (args.Length() < 1) { + return ThrowException(Exception::TypeError( + String::New("Bad parameter"))); + } + + in = LoadBIO(args[0]); + if (in == NULL) { + return ThrowException(Exception::Error( + String::New("Unable to load BIO"))); + } + + if (args.Length() >= 2) { + ASSERT_IS_STRING_OR_BUFFER(args[1]); + + int passlen = DecodeBytes(args[1], BINARY); + if (passlen < 0) { + BIO_free(in); + return ThrowException(Exception::TypeError( + String::New("Bad password"))); + } + pass = new char[passlen + 1]; + int pass_written = DecodeWrite(pass, passlen, args[1], BINARY); + + assert(pass_written == passlen); + pass[passlen] = '\0'; + } + + if (d2i_PKCS12_bio(in, &p12) && + PKCS12_parse(p12, pass, &pkey, &cert, &extraCerts) && + SSL_CTX_use_certificate(sc->ctx_, cert) && + SSL_CTX_use_PrivateKey(sc->ctx_, pkey)) + { + // set extra certs + while (X509* x509 = sk_X509_pop(extraCerts)) { + if (!sc->ca_store_) { + sc->ca_store_ = X509_STORE_new(); + SSL_CTX_set_cert_store(sc->ctx_, sc->ca_store_); + } + + X509_STORE_add_cert(sc->ca_store_, x509); + SSL_CTX_add_client_CA(sc->ctx_, x509); + } + + EVP_PKEY_free(pkey); + X509_free(cert); + sk_X509_free(extraCerts); + + ret = true; + } + + PKCS12_free(p12); + BIO_free(in); + delete[] pass; + + if (!ret) { + unsigned long err = ERR_get_error(); + const char *str = ERR_reason_error_string(err); + return ThrowException(Exception::Error(String::New(str))); + } + + return True(); +} + #ifdef SSL_PRINT_DEBUG # define DEBUG_PRINT(...) fprintf (stderr, __VA_ARGS__) |