From 79f33dd28b8e4c4436c2ae1bb9795bea2f071b17 Mon Sep 17 00:00:00 2001 From: Vlado Velichkovski Date: Sat, 16 Jun 2018 20:40:48 +0200 Subject: [PATCH 01/15] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 904298c..1706617 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,6 @@ }, "license": "MIT", "dependencies": { - "nan": "2.2.0" + "nan": "2.10.0" } } From 54ef6b6c047280930af278e953ba782ff45d5fcd Mon Sep 17 00:00:00 2001 From: Vlado Velichkovski Date: Sat, 16 Jun 2018 20:41:45 +0200 Subject: [PATCH 02/15] Update x509.cc --- src/x509.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/x509.cc b/src/x509.cc index a836301..2ce8f20 100644 --- a/src/x509.cc +++ b/src/x509.cc @@ -43,7 +43,7 @@ std::string parse_args(const Nan::FunctionCallbackInfo& info) { return std::string(); } - return *String::Utf8Value(info[0]->ToString()); + return *String::Utf8Value(info.GetIsolate(), info[0]->ToString()); } @@ -52,8 +52,8 @@ NAN_METHOD(verify) { Nan::HandleScope scope; OpenSSL_add_all_algorithms(); - std::string cert_path = *String::Utf8Value(info[0]->ToString()); - std::string ca_bundlestr = *String::Utf8Value(info[1]->ToString()); + std::string cert_path = *String::Utf8Value(info.GetIsolate(), info[0]->ToString()); + std::string ca_bundlestr = *String::Utf8Value(info.GetIsolate(), info[1]->ToString()); X509_STORE *store = NULL; X509_STORE_CTX *verify_ctx = NULL; From a8e5ba03aec74fcf235e4c691cf9bd1b62b62a77 Mon Sep 17 00:00:00 2001 From: Vlado Velichkovski Date: Sun, 17 Jun 2018 01:50:58 +0200 Subject: [PATCH 03/15] Update x509.cc --- src/x509.cc | 346 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 201 insertions(+), 145 deletions(-) diff --git a/src/x509.cc b/src/x509.cc index 2ce8f20..6ba1d64 100644 --- a/src/x509.cc +++ b/src/x509.cc @@ -6,39 +6,34 @@ using namespace v8; // Field names that OpenSSL is missing. static const char *MISSING[4][2] = { - { - "1.2.840.113533.7.65.0", - "entrustVersionInfo" - }, + {"1.2.840.113533.7.65.0", + "entrustVersionInfo"}, - { - "1.3.6.1.4.1.311.60.2.1.1", - "jurisdictionOfIncorpationLocalityName" - }, + {"1.3.6.1.4.1.311.60.2.1.1", + "jurisdictionOfIncorpationLocalityName"}, - { - "1.3.6.1.4.1.311.60.2.1.2", - "jurisdictionOfIncorporationStateOrProvinceName" - }, + {"1.3.6.1.4.1.311.60.2.1.2", + "jurisdictionOfIncorporationStateOrProvinceName"}, - { - "1.3.6.1.4.1.311.60.2.1.3", - "jurisdictionOfIncorporationCountryName" - } -}; + {"1.3.6.1.4.1.311.60.2.1.3", + "jurisdictionOfIncorporationCountryName"}}; -std::string parse_args(const Nan::FunctionCallbackInfo& info) { - if (info.Length() == 0) { +std::string parse_args(const Nan::FunctionCallbackInfo &info) +{ + if (info.Length() == 0) + { Nan::ThrowTypeError("Must provide a certificate string."); return std::string(); } - if (!info[0]->IsString()) { + if (!info[0]->IsString()) + { Nan::ThrowTypeError("Certificate must be a string."); return std::string(); } - if (info[0]->ToString()->Length() == 0) { + if (info[0]->ToString()->Length() == 0) + { Nan::ThrowTypeError("Certificate argument provided, but left blank."); return std::string(); } @@ -46,9 +41,8 @@ std::string parse_args(const Nan::FunctionCallbackInfo& info) { return *String::Utf8Value(info.GetIsolate(), info[0]->ToString()); } - - -NAN_METHOD(verify) { +NAN_METHOD(verify) +{ Nan::HandleScope scope; OpenSSL_add_all_algorithms(); @@ -61,97 +55,113 @@ NAN_METHOD(verify) { BIO *cert_bio = NULL; const char *error = NULL; - do { + do + { store = X509_STORE_new(); - if (store == NULL) { + if (store == NULL) + { error = "Failed to create X509 certificate store."; break; } verify_ctx = X509_STORE_CTX_new(); - if (verify_ctx == NULL) { + if (verify_ctx == NULL) + { error = "Failed to create X509 verification context."; break; } cert_bio = BIO_new(BIO_s_file()); int ret = BIO_read_filename(cert_bio, cert_path.c_str()); - if (ret != 1) { + if (ret != 1) + { error = "Error reading file"; break; } cert = PEM_read_bio_X509(cert_bio, NULL, 0, NULL); - if (cert == NULL) { + if (cert == NULL) + { error = "Failed to load cert"; break; } ret = X509_STORE_load_locations(store, ca_bundlestr.c_str(), NULL); - if (ret != 1) { + if (ret != 1) + { error = "Error loading CA chain file"; break; } X509_STORE_CTX_init(verify_ctx, store, cert, NULL); ret = X509_verify_cert(verify_ctx); - if (ret <= 0) { - error = X509_verify_cert_error_string(verify_ctx->error); + if (ret <= 0) + { + error = X509_verify_cert_error_string(X509_STORE_CTX_get_error(verify_ctx)); break; } - } while(0); - + } while (0); + X509_STORE_free(store); X509_free(cert); X509_STORE_CTX_free(verify_ctx); BIO_free_all(cert_bio); - if (error != NULL) { + if (error != NULL) + { Nan::ThrowError(error); - } else { + } + else + { info.GetReturnValue().Set(Nan::New(true)); } } - - -NAN_METHOD(get_altnames) { +NAN_METHOD(get_altnames) +{ Nan::HandleScope scope; std::string parsed_arg = parse_args(info); - if(parsed_arg.size() == 0) { + if (parsed_arg.size() == 0) + { info.GetReturnValue().SetUndefined(); } Local exports(try_parse(parsed_arg)->ToObject()); Local key = Nan::New("altNames").ToLocalChecked(); info.GetReturnValue().Set( - Nan::Get(exports, key).ToLocalChecked()); + Nan::Get(exports, key).ToLocalChecked()); ERR_clear_error(); } -NAN_METHOD(get_subject) { +NAN_METHOD(get_subject) +{ Nan::HandleScope scope; std::string parsed_arg = parse_args(info); - if(parsed_arg.size() == 0) { + if (parsed_arg.size() == 0) + { info.GetReturnValue().SetUndefined(); } Local exports(try_parse(parsed_arg)->ToObject()); Local key = Nan::New("subject").ToLocalChecked(); info.GetReturnValue().Set( - Nan::Get(exports, key).ToLocalChecked()); + Nan::Get(exports, key).ToLocalChecked()); ERR_clear_error(); } -NAN_METHOD(get_issuer) { +NAN_METHOD(get_issuer) +{ Nan::HandleScope scope; std::string parsed_arg = parse_args(info); - if(parsed_arg.size() == 0) { + if (parsed_arg.size() == 0) + { info.GetReturnValue().SetUndefined(); } Local exports(try_parse(parsed_arg)->ToObject()); Local key = Nan::New("issuer").ToLocalChecked(); info.GetReturnValue().Set( - Nan::Get(exports, key).ToLocalChecked()); + Nan::Get(exports, key).ToLocalChecked()); ERR_clear_error(); } -NAN_METHOD(parse_cert) { +NAN_METHOD(parse_cert) +{ Nan::HandleScope scope; std::string parsed_arg = parse_args(info); - if(parsed_arg.size() == 0) { + if (parsed_arg.size() == 0) + { info.GetReturnValue().SetUndefined(); } Local exports(try_parse(parsed_arg)->ToObject()); @@ -162,9 +172,10 @@ NAN_METHOD(parse_cert) { /* * This is where everything is handled for both -0.11.2 and 0.11.3+. */ -Local try_parse(const std::string& dataString) { +Local try_parse(const std::string &dataString) +{ Nan::EscapableHandleScope scope; - const char* data = dataString.c_str(); + const char *data = dataString.c_str(); Local exports = Nan::New(); X509 *cert; @@ -172,12 +183,14 @@ Local try_parse(const std::string& dataString) { BIO *bio = BIO_new(BIO_s_mem()); int result = BIO_puts(bio, data); - if (result == -2) { + if (result == -2) + { Nan::ThrowError("BIO doesn't support BIO_puts."); BIO_free(bio); return scope.Escape(exports); } - else if (result <= 0) { + else if (result <= 0) + { Nan::ThrowError("No data was written to BIO."); BIO_free(bio); return scope.Escape(exports); @@ -186,13 +199,15 @@ Local try_parse(const std::string& dataString) { // Try raw read cert = PEM_read_bio_X509(bio, NULL, 0, NULL); - if (cert == NULL) { + if (cert == NULL) + { BIO_free_all(bio); // Switch to file BIO bio = BIO_new(BIO_s_file()); // If raw read fails, try reading the input as a filename. - if (!BIO_read_filename(bio, data)) { + if (!BIO_read_filename(bio, data)) + { ERR_clear_error(); Nan::ThrowError("File doesn't exist."); BIO_free(bio); @@ -202,7 +217,8 @@ Local try_parse(const std::string& dataString) { // Try reading the bio again with the file in it. cert = PEM_read_bio_X509(bio, NULL, 0, NULL); - if (cert == NULL) { + if (cert == NULL) + { ERR_clear_error(); Nan::ThrowError("Unable to parse certificate."); BIO_free(bio); @@ -211,34 +227,35 @@ Local try_parse(const std::string& dataString) { } Nan::Set(exports, - Nan::New("version").ToLocalChecked(), - Nan::New((int) X509_get_version(cert))); + Nan::New("version").ToLocalChecked(), + Nan::New((int)X509_get_version(cert))); Nan::Set(exports, - Nan::New("subject").ToLocalChecked(), - parse_name(X509_get_subject_name(cert))); + Nan::New("subject").ToLocalChecked(), + parse_name(X509_get_subject_name(cert))); Nan::Set(exports, - Nan::New("issuer").ToLocalChecked(), - parse_name(X509_get_issuer_name(cert))); + Nan::New("issuer").ToLocalChecked(), + parse_name(X509_get_issuer_name(cert))); Nan::Set(exports, - Nan::New("serial").ToLocalChecked(), - parse_serial(X509_get_serialNumber(cert))); + Nan::New("serial").ToLocalChecked(), + parse_serial(X509_get_serialNumber(cert))); Nan::Set(exports, - Nan::New("notBefore").ToLocalChecked(), - parse_date(X509_get_notBefore(cert))); + Nan::New("notBefore").ToLocalChecked(), + parse_date(X509_get_notBefore(cert))); Nan::Set(exports, - Nan::New("notAfter").ToLocalChecked(), - parse_date(X509_get_notAfter(cert))); + Nan::New("notAfter").ToLocalChecked(), + parse_date(X509_get_notAfter(cert))); // Subject hash std::stringstream stream; stream << std::hex << X509_subject_name_hash(cert); Nan::Set(exports, - Nan::New("subjectHash").ToLocalChecked(), - Nan::New(stream.str()).ToLocalChecked()); + Nan::New("subjectHash").ToLocalChecked(), + Nan::New(stream.str()).ToLocalChecked()); // Signature Algorithm - int sig_alg_nid = OBJ_obj2nid(cert->sig_alg->algorithm); - if (sig_alg_nid == NID_undef) { + int sig_alg_nid = X509_get_signature_nid(cert); //OBJ_obj2nid(cert->sig_alg->algorithm); + if (sig_alg_nid == NID_undef) + { ERR_clear_error(); Nan::ThrowError("unable to find specified signature algorithm name."); X509_free(cert); @@ -246,34 +263,40 @@ Local try_parse(const std::string& dataString) { return scope.Escape(exports); } Nan::Set(exports, - Nan::New("signatureAlgorithm").ToLocalChecked(), - Nan::New(OBJ_nid2ln(sig_alg_nid)).ToLocalChecked()); + Nan::New("signatureAlgorithm").ToLocalChecked(), + Nan::New(OBJ_nid2ln(sig_alg_nid)).ToLocalChecked()); // fingerPrint unsigned int md_size, idx; unsigned char md[EVP_MAX_MD_SIZE]; - if (X509_digest(cert, EVP_sha1(), md, &md_size)) { + if (X509_digest(cert, EVP_sha1(), md, &md_size)) + { const char hex[] = "0123456789ABCDEF"; char fingerprint[EVP_MAX_MD_SIZE * 3]; - for (idx = 0; idx < md_size; idx++) { - fingerprint[3*idx] = hex[(md[idx] & 0xf0) >> 4]; - fingerprint[(3*idx)+1] = hex[(md[idx] & 0x0f)]; - fingerprint[(3*idx)+2] = ':'; + for (idx = 0; idx < md_size; idx++) + { + fingerprint[3 * idx] = hex[(md[idx] & 0xf0) >> 4]; + fingerprint[(3 * idx) + 1] = hex[(md[idx] & 0x0f)]; + fingerprint[(3 * idx) + 2] = ':'; } - if (md_size > 0) { - fingerprint[(3*(md_size-1))+2] = '\0'; - } else { + if (md_size > 0) + { + fingerprint[(3 * (md_size - 1)) + 2] = '\0'; + } + else + { fingerprint[0] = '\0'; } Nan::Set(exports, - Nan::New("fingerPrint").ToLocalChecked(), - Nan::New(fingerprint).ToLocalChecked()); + Nan::New("fingerPrint").ToLocalChecked(), + Nan::New(fingerprint).ToLocalChecked()); } // public key - int pkey_nid = OBJ_obj2nid(cert->cert_info->key->algor->algorithm); - if (pkey_nid == NID_undef) { + int pkey_nid = X509_get_signature_nid(cert); //OBJ_obj2nid(cert->cert_info->key->algor->algorithm); + if (pkey_nid == NID_undef) + { ERR_clear_error(); Nan::ThrowError("unable to find specified public key algorithm name."); X509_free(cert); @@ -283,28 +306,32 @@ Local try_parse(const std::string& dataString) { EVP_PKEY *pkey = X509_get_pubkey(cert); Local publicKey = Nan::New(); Nan::Set(publicKey, - Nan::New("algorithm").ToLocalChecked(), - Nan::New(OBJ_nid2ln(pkey_nid)).ToLocalChecked()); + Nan::New("algorithm").ToLocalChecked(), + Nan::New(OBJ_nid2ln(pkey_nid)).ToLocalChecked()); - if (pkey_nid == NID_rsaEncryption) { + if (pkey_nid == NID_rsaEncryption) + { char *rsa_e_dec, *rsa_n_hex; uint32_t rsa_key_length_int; RSA *rsa_key; - rsa_key = pkey->pkey.rsa; - rsa_e_dec = BN_bn2dec(rsa_key->e); - rsa_n_hex = BN_bn2hex(rsa_key->n); + rsa_key = EVP_PKEY_get1_RSA(pkey); + const BIGNUM *n; + const BIGNUM *e; + RSA_get0_key(rsa_key, &n, &e, NULL); + rsa_e_dec = BN_bn2dec(e); + rsa_n_hex = BN_bn2hex(n); rsa_key_length_int = RSA_size(rsa_key) * 8; Nan::Set(publicKey, - Nan::New("e").ToLocalChecked(), - Nan::New(rsa_e_dec).ToLocalChecked()); + Nan::New("e").ToLocalChecked(), + Nan::New(rsa_e_dec).ToLocalChecked()); OPENSSL_free(rsa_e_dec); Nan::Set(publicKey, - Nan::New("n").ToLocalChecked(), - Nan::New(rsa_n_hex).ToLocalChecked()); + Nan::New("n").ToLocalChecked(), + Nan::New(rsa_n_hex).ToLocalChecked()); OPENSSL_free(rsa_n_hex); Nan::Set(publicKey, - Nan::New("bitSize").ToLocalChecked(), - Nan::New(rsa_key_length_int)); + Nan::New("bitSize").ToLocalChecked(), + Nan::New(rsa_key_length_int)); } Nan::Set(exports, Nan::New("publicKey").ToLocalChecked(), publicKey); EVP_PKEY_free(pkey); @@ -314,17 +341,22 @@ Local try_parse(const std::string& dataString) { STACK_OF(GENERAL_NAME) *names = NULL; int i; - names = (STACK_OF(GENERAL_NAME)*) X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); + names = (STACK_OF(GENERAL_NAME) *)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); - if (names != NULL) { + if (names != NULL) + { int length = sk_GENERAL_NAME_num(names); - for (i = 0; i < length; i++) { + for (i = 0; i < length; i++) + { GENERAL_NAME *current = sk_GENERAL_NAME_value(names, i); - if (current->type == GEN_DNS) { - char *name = (char*) ASN1_STRING_data(current->d.dNSName); + if (current->type == GEN_DNS) + { - if (ASN1_STRING_length(current->d.dNSName) != (int) strlen(name)) { + char *name = (char *)ASN1_STRING_get0_data(current->d.dNSName); + + if (ASN1_STRING_length(current->d.dNSName) != (int)strlen(name)) + { ERR_clear_error(); Nan::ThrowError("Malformed alternative names field."); X509_free(cert); @@ -340,18 +372,23 @@ Local try_parse(const std::string& dataString) { // Extensions Local extensions(Nan::New()); - STACK_OF(X509_EXTENSION) *exts = cert->cert_info->extensions; + const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert); //->cert_info->extensions; + int num_of_exts; int index_of_exts; - if (exts) { + if (exts) + { num_of_exts = sk_X509_EXTENSION_num(exts); - } else { + } + else + { num_of_exts = 0; } // IFNEG_FAIL(num_of_exts, "error parsing number of X509v3 extensions."); - for (index_of_exts = 0; index_of_exts < num_of_exts; index_of_exts++) { + for (index_of_exts = 0; index_of_exts < num_of_exts; index_of_exts++) + { X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, index_of_exts); // IFNULL_FAIL(ext, "unable to extract extension from stack"); ASN1_OBJECT *obj = X509_EXTENSION_get_object(ext); @@ -359,8 +396,14 @@ Local try_parse(const std::string& dataString) { BIO *ext_bio = BIO_new(BIO_s_mem()); // IFNULL_FAIL(ext_bio, "unable to allocate memory for extension value BIO"); - if (!X509V3_EXT_print(ext_bio, ext, 0, 0)) { - M_ASN1_OCTET_STRING_print(ext_bio, ext->value); + if (!X509V3_EXT_print(ext_bio, ext, 0, 0)) + { + unsigned char **buf = NULL; + int len = i2d_ASN1_OCTET_STRING(X509_EXTENSION_get_data(ext), buf); + if (len >= 0) + { + BIO_write(ext_bio, *buf, len); + } } BUF_MEM *bptr; @@ -374,24 +417,26 @@ Local try_parse(const std::string& dataString) { BIO_free(ext_bio); unsigned nid = OBJ_obj2nid(obj); - if (nid == NID_undef) { + if (nid == NID_undef) + { char extname[100]; - OBJ_obj2txt(extname, 100, (const ASN1_OBJECT *) obj, 1); + OBJ_obj2txt(extname, 100, (const ASN1_OBJECT *)obj, 1); Nan::Set(extensions, - Nan::New(real_name(extname)).ToLocalChecked(), - Nan::New(trimmed_data).ToLocalChecked()); - - } else { + Nan::New(real_name(extname)).ToLocalChecked(), + Nan::New(trimmed_data).ToLocalChecked()); + } + else + { const char *c_ext_name = OBJ_nid2ln(nid); // IFNULL_FAIL(c_ext_name, "invalid X509v3 extension name"); Nan::Set(extensions, - Nan::New(real_name((char*)c_ext_name)).ToLocalChecked(), - Nan::New(trimmed_data).ToLocalChecked()); + Nan::New(real_name((char *)c_ext_name)).ToLocalChecked(), + Nan::New(trimmed_data).ToLocalChecked()); } delete[] data; } Nan::Set(exports, - Nan::New("extensions").ToLocalChecked(), extensions); + Nan::New("extensions").ToLocalChecked(), extensions); ERR_clear_error(); X509_free(cert); @@ -400,7 +445,8 @@ Local try_parse(const std::string& dataString) { return scope.Escape(exports); } -Local parse_serial(ASN1_INTEGER *serial) { +Local parse_serial(ASN1_INTEGER *serial) +{ Nan::EscapableHandleScope scope; Local serialNumber; BIGNUM *bn = ASN1_INTEGER_to_BN(serial, NULL); @@ -412,69 +458,79 @@ Local parse_serial(ASN1_INTEGER *serial) { return scope.Escape(serialNumber); } -Local parse_date(ASN1_TIME *date) { +Local parse_date(ASN1_TIME *date) +{ Nan::EscapableHandleScope scope; - BIO *bio; + // scope->BIO *bio; BUF_MEM *bm; char formatted[64]; Local args[1]; - formatted[0] = '\0'; - bio = BIO_new(BIO_s_mem()); + BIO *bio = BIO_new(BIO_s_mem()); ASN1_TIME_print(bio, date); BIO_get_mem_ptr(bio, &bm); BUF_strlcpy(formatted, bm->data, bm->length + 1); BIO_free(bio); args[0] = Nan::New(formatted).ToLocalChecked(); - Local global = Nan::GetCurrentContext()->Global(); Local DateObject = Nan::Get(global, - Nan::New("Date").ToLocalChecked()).ToLocalChecked()->ToObject(); - return scope.Escape(DateObject->CallAsConstructor(1, args)); + Nan::New("Date").ToLocalChecked()) + .ToLocalChecked() + ->ToObject(); + return scope.Escape(DateObject->CallAsConstructor(Nan::GetCurrentContext(), 1, args).ToLocalChecked()); } -Local parse_name(X509_NAME *subject) { +Local parse_name(X509_NAME *subject) +{ Nan::EscapableHandleScope scope; Local cert = Nan::New(); int i, length; ASN1_OBJECT *entry; - unsigned char *value; + const unsigned char *value; char buf[255]; length = X509_NAME_entry_count(subject); - for (i = 0; i < length; i++) { + for (i = 0; i < length; i++) + { entry = X509_NAME_ENTRY_get_object(X509_NAME_get_entry(subject, i)); OBJ_obj2txt(buf, 255, entry, 0); - value = ASN1_STRING_data(X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject, i))); + value = ASN1_STRING_get0_data(X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject, i))); Nan::Set(cert, - Nan::New(real_name(buf)).ToLocalChecked(), - Nan::New((const char*) value).ToLocalChecked()); + Nan::New(real_name(buf)).ToLocalChecked(), + Nan::New((const char *)value).ToLocalChecked()); } return scope.Escape(cert); } // Fix for missing fields in OpenSSL. -char* real_name(char *data) { - int i, length = (int) sizeof(MISSING) / sizeof(MISSING[0]); +char *real_name(char *data) +{ + int i, length = (int)sizeof(MISSING) / sizeof(MISSING[0]); - for (i = 0; i < length; i++) { + for (i = 0; i < length; i++) + { if (strcmp(data, MISSING[i][0]) == 0) - return (char*) MISSING[i][1]; + return (char *)MISSING[i][1]; } return data; } -char* trim(char *data, int len) { - if (data[0] == '\n' || data[0] == '\r') { - data = data+1; +char *trim(char *data, int len) +{ + if (data[0] == '\n' || data[0] == '\r') + { + data = data + 1; } - else if (len > 1 && (data[len-1] == '\n' || data[len-1] == '\r')) { - data[len-1] = (char) 0; + else if (len > 1 && (data[len - 1] == '\n' || data[len - 1] == '\r')) + { + data[len - 1] = (char)0; } - else if (len > 0 && (data[len] == '\n' || data[len] == '\r')) { - data[len] = (char) 0; + else if (len > 0 && (data[len] == '\n' || data[len] == '\r')) + { + data[len] = (char)0; } - else { + else + { return data; } From 8c4007c49fb2b72c1c48045e8ff9d19db47c5549 Mon Sep 17 00:00:00 2001 From: Vlado Velichkovski Date: Sun, 17 Jun 2018 23:50:18 +0200 Subject: [PATCH 04/15] Update x509.cc --- src/x509.cc | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/x509.cc b/src/x509.cc index 6ba1d64..fb92c27 100644 --- a/src/x509.cc +++ b/src/x509.cc @@ -164,6 +164,7 @@ NAN_METHOD(parse_cert) { info.GetReturnValue().SetUndefined(); } + Local exports(try_parse(parsed_arg)->ToObject()); info.GetReturnValue().Set(exports); ERR_clear_error(); @@ -244,7 +245,6 @@ Local try_parse(const std::string &dataString) Nan::Set(exports, Nan::New("notAfter").ToLocalChecked(), parse_date(X509_get_notAfter(cert))); - // Subject hash std::stringstream stream; stream << std::hex << X509_subject_name_hash(cert); @@ -292,7 +292,6 @@ Local try_parse(const std::string &dataString) Nan::New("fingerPrint").ToLocalChecked(), Nan::New(fingerprint).ToLocalChecked()); } - // public key int pkey_nid = X509_get_signature_nid(cert); //OBJ_obj2nid(cert->cert_info->key->algor->algorithm); if (pkey_nid == NID_undef) @@ -374,24 +373,18 @@ Local try_parse(const std::string &dataString) Local extensions(Nan::New()); const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert); //->cert_info->extensions; - int num_of_exts; + int num_of_exts = X509v3_get_ext_count(exts); int index_of_exts; - if (exts) - { - num_of_exts = sk_X509_EXTENSION_num(exts); - } - else - { - num_of_exts = 0; - } + + std::cout << num_of_exts; // IFNEG_FAIL(num_of_exts, "error parsing number of X509v3 extensions."); for (index_of_exts = 0; index_of_exts < num_of_exts; index_of_exts++) { - X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, index_of_exts); - // IFNULL_FAIL(ext, "unable to extract extension from stack"); + X509_EXTENSION *ext = X509v3_get_ext(exts, index_of_exts); ASN1_OBJECT *obj = X509_EXTENSION_get_object(ext); + // IFNULL_FAIL(obj, "unable to extract ASN1 object from extension"); BIO *ext_bio = BIO_new(BIO_s_mem()); @@ -400,6 +393,8 @@ Local try_parse(const std::string &dataString) { unsigned char **buf = NULL; int len = i2d_ASN1_OCTET_STRING(X509_EXTENSION_get_data(ext), buf); + std::cout << len << &(*buf); + if (len >= 0) { BIO_write(ext_bio, *buf, len); @@ -413,10 +408,10 @@ Local try_parse(const std::string &dataString) char *data = new char[bptr->length + 1]; BUF_strlcpy(data, bptr->data, bptr->length + 1); char *trimmed_data = trim(data, bptr->length); - BIO_free(ext_bio); unsigned nid = OBJ_obj2nid(obj); + if (nid == NID_undef) { char extname[100]; @@ -433,8 +428,10 @@ Local try_parse(const std::string &dataString) Nan::New(real_name((char *)c_ext_name)).ToLocalChecked(), Nan::New(trimmed_data).ToLocalChecked()); } + delete[] data; } + Nan::Set(exports, Nan::New("extensions").ToLocalChecked(), extensions); From 1844ec1dcd9d72258b0f8450b68535a014059d2d Mon Sep 17 00:00:00 2001 From: Vlado Velichkovski Date: Sun, 17 Jun 2018 23:51:36 +0200 Subject: [PATCH 05/15] Update x509.cc --- src/x509.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/x509.cc b/src/x509.cc index fb92c27..c7219f8 100644 --- a/src/x509.cc +++ b/src/x509.cc @@ -376,8 +376,6 @@ Local try_parse(const std::string &dataString) int num_of_exts = X509v3_get_ext_count(exts); int index_of_exts; - std::cout << num_of_exts; - // IFNEG_FAIL(num_of_exts, "error parsing number of X509v3 extensions."); for (index_of_exts = 0; index_of_exts < num_of_exts; index_of_exts++) @@ -393,7 +391,6 @@ Local try_parse(const std::string &dataString) { unsigned char **buf = NULL; int len = i2d_ASN1_OCTET_STRING(X509_EXTENSION_get_data(ext), buf); - std::cout << len << &(*buf); if (len >= 0) { From dc48bf0031aa5867dac4344804b3297b67555e53 Mon Sep 17 00:00:00 2001 From: Vlado Velichkovski Date: Mon, 18 Jun 2018 00:31:33 +0200 Subject: [PATCH 06/15] Update x509.cc --- src/x509.cc | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/x509.cc b/src/x509.cc index c7219f8..3354b77 100644 --- a/src/x509.cc +++ b/src/x509.cc @@ -253,7 +253,7 @@ Local try_parse(const std::string &dataString) Nan::New(stream.str()).ToLocalChecked()); // Signature Algorithm - int sig_alg_nid = X509_get_signature_nid(cert); //OBJ_obj2nid(cert->sig_alg->algorithm); + int sig_alg_nid = X509_get_signature_nid(cert); if (sig_alg_nid == NID_undef) { ERR_clear_error(); @@ -293,7 +293,7 @@ Local try_parse(const std::string &dataString) Nan::New(fingerprint).ToLocalChecked()); } // public key - int pkey_nid = X509_get_signature_nid(cert); //OBJ_obj2nid(cert->cert_info->key->algor->algorithm); + int pkey_nid = X509_get_signature_nid(cert); if (pkey_nid == NID_undef) { ERR_clear_error(); @@ -371,7 +371,7 @@ Local try_parse(const std::string &dataString) // Extensions Local extensions(Nan::New()); - const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert); //->cert_info->extensions; + const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert); int num_of_exts = X509v3_get_ext_count(exts); int index_of_exts; @@ -389,22 +389,28 @@ Local try_parse(const std::string &dataString) // IFNULL_FAIL(ext_bio, "unable to allocate memory for extension value BIO"); if (!X509V3_EXT_print(ext_bio, ext, 0, 0)) { - unsigned char **buf = NULL; - int len = i2d_ASN1_OCTET_STRING(X509_EXTENSION_get_data(ext), buf); - + unsigned char *buf = NULL; + int len = i2d_ASN1_OCTET_STRING(X509_EXTENSION_get_data(ext), &buf); if (len >= 0) { - BIO_write(ext_bio, *buf, len); + BIO_write(ext_bio, static_cast(buf), len); } } BUF_MEM *bptr; BIO_get_mem_ptr(ext_bio, &bptr); - BIO_set_close(ext_bio, BIO_CLOSE); char *data = new char[bptr->length + 1]; - BUF_strlcpy(data, bptr->data, bptr->length + 1); - char *trimmed_data = trim(data, bptr->length); + char *trimmed_data; + if (bptr->data == NULL) + { + trimmed_data = (char *)""; + } + else + { + BUF_strlcpy(data, bptr->data, bptr->length + 1); + trimmed_data = trim(data, bptr->length); + } BIO_free(ext_bio); unsigned nid = OBJ_obj2nid(obj); @@ -455,7 +461,6 @@ Local parse_serial(ASN1_INTEGER *serial) Local parse_date(ASN1_TIME *date) { Nan::EscapableHandleScope scope; - // scope->BIO *bio; BUF_MEM *bm; char formatted[64]; Local args[1]; From 70c52dedc8b4b54b6a12ede018a641c5c784be3c Mon Sep 17 00:00:00 2001 From: Vlado Velichkovski Date: Sun, 8 Jul 2018 20:33:50 +0200 Subject: [PATCH 07/15] Update .travis.yml --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index c45c402..37c49b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,9 @@ addons: language: node_js node_js: - "stable" + - "9.0" + - "8.0" + - "6.0" - "4.0" - "0.12" - "0.10" From c6e57d22ca96b1363d454b37a28add71ad55af37 Mon Sep 17 00:00:00 2001 From: stormwin Date: Sun, 8 Jul 2018 21:07:42 +0200 Subject: [PATCH 08/15] Fixed some of incompatibilities between nodejs versions --- package-lock.json | 13 +++++++++++++ src/x509.cc | 6 +++--- 2 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..c887769 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "x509", + "version": "0.3.3", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" + } + } +} diff --git a/src/x509.cc b/src/x509.cc index 3354b77..c953bad 100644 --- a/src/x509.cc +++ b/src/x509.cc @@ -38,7 +38,7 @@ std::string parse_args(const Nan::FunctionCallbackInfo &info) return std::string(); } - return *String::Utf8Value(info.GetIsolate(), info[0]->ToString()); + return *Nan::Utf8String(info[0]->ToString()); } NAN_METHOD(verify) @@ -46,8 +46,8 @@ NAN_METHOD(verify) Nan::HandleScope scope; OpenSSL_add_all_algorithms(); - std::string cert_path = *String::Utf8Value(info.GetIsolate(), info[0]->ToString()); - std::string ca_bundlestr = *String::Utf8Value(info.GetIsolate(), info[1]->ToString()); + std::string cert_path = *Nan::Utf8String(info[0]->ToString()); + std::string ca_bundlestr = *Nan::Utf8String(info[1]->ToString()); X509_STORE *store = NULL; X509_STORE_CTX *verify_ctx = NULL; From af15d6c31ea2656d382cf6adccf57d662821b526 Mon Sep 17 00:00:00 2001 From: stormwin Date: Sun, 8 Jul 2018 21:23:32 +0200 Subject: [PATCH 09/15] one more (nan) fix for older nodejs versions --- src/x509.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/x509.cc b/src/x509.cc index c953bad..d6d37c4 100644 --- a/src/x509.cc +++ b/src/x509.cc @@ -476,7 +476,7 @@ Local parse_date(ASN1_TIME *date) Nan::New("Date").ToLocalChecked()) .ToLocalChecked() ->ToObject(); - return scope.Escape(DateObject->CallAsConstructor(Nan::GetCurrentContext(), 1, args).ToLocalChecked()); + return scope.Escape(Nan::CallAsConstructor(DateObject, 1, args).ToLocalChecked()); } Local parse_name(X509_NAME *subject) From 07c6f0c827b584de5d1e938fee2d106af228310b Mon Sep 17 00:00:00 2001 From: stormwin Date: Sun, 8 Jul 2018 22:33:56 +0200 Subject: [PATCH 10/15] OPENSSL fixes for compatibility --- include/x509.h | 1 + src/x509.cc | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/include/x509.h b/include/x509.h index ce1198b..1ab0c85 100644 --- a/include/x509.h +++ b/include/x509.h @@ -16,6 +16,7 @@ #include #include #include +#include using namespace v8; diff --git a/src/x509.cc b/src/x509.cc index d6d37c4..274fb16 100644 --- a/src/x509.cc +++ b/src/x509.cc @@ -313,12 +313,17 @@ Local try_parse(const std::string &dataString) char *rsa_e_dec, *rsa_n_hex; uint32_t rsa_key_length_int; RSA *rsa_key; +#if OPENSSL_VERSION_NUMBER >= 0x10100000L rsa_key = EVP_PKEY_get1_RSA(pkey); const BIGNUM *n; const BIGNUM *e; RSA_get0_key(rsa_key, &n, &e, NULL); rsa_e_dec = BN_bn2dec(e); rsa_n_hex = BN_bn2hex(n); +#else + rsa_key = pkey->pkey.rsa; + rsa_e_dec = BN_bn2dec(rsa_key->e); +#endif rsa_key_length_int = RSA_size(rsa_key) * 8; Nan::Set(publicKey, Nan::New("e").ToLocalChecked(), @@ -351,8 +356,13 @@ Local try_parse(const std::string &dataString) if (current->type == GEN_DNS) { + char *name = NULL; - char *name = (char *)ASN1_STRING_get0_data(current->d.dNSName); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + name = (char *)ASN1_STRING_get0_data(current->d.dNSName); +#else + name = (char *)ASN1_STRING_data(current->d.dNSName); +#endif if (ASN1_STRING_length(current->d.dNSName) != (int)strlen(name)) { @@ -371,7 +381,11 @@ Local try_parse(const std::string &dataString) // Extensions Local extensions(Nan::New()); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert); +#else + STACK_OF(X509_EXTENSION) *exts = cert->cert_info->extensions; +#endif int num_of_exts = X509v3_get_ext_count(exts); int index_of_exts; @@ -492,7 +506,12 @@ Local parse_name(X509_NAME *subject) { entry = X509_NAME_ENTRY_get_object(X509_NAME_get_entry(subject, i)); OBJ_obj2txt(buf, 255, entry, 0); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L value = ASN1_STRING_get0_data(X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject, i))); +#else + value = ASN1_STRING_data(X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject, i))); +#endif + Nan::Set(cert, Nan::New(real_name(buf)).ToLocalChecked(), Nan::New((const char *)value).ToLocalChecked()); From 6407b83faa1e1345d0a03bc6500e87a7cafb39ff Mon Sep 17 00:00:00 2001 From: stormwin Date: Sun, 8 Jul 2018 22:43:36 +0200 Subject: [PATCH 11/15] Fix incompatibilities with nodejs v0.x --- src/x509.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/x509.cc b/src/x509.cc index 274fb16..7025d6b 100644 --- a/src/x509.cc +++ b/src/x509.cc @@ -253,7 +253,11 @@ Local try_parse(const std::string &dataString) Nan::New(stream.str()).ToLocalChecked()); // Signature Algorithm +#if OPENSSL_VERSION_NUMBER >= 0x10100000L int sig_alg_nid = X509_get_signature_nid(cert); +#else + int sig_alg_nid = OBJ_obj2nid(cert->sig_alg->algorithm); +#endif if (sig_alg_nid == NID_undef) { ERR_clear_error(); From f71920e689e6dccc98297f273dcd5b1fa0cb7d1f Mon Sep 17 00:00:00 2001 From: stormwin Date: Sun, 8 Jul 2018 22:52:36 +0200 Subject: [PATCH 12/15] Fix incompatibilities with nodejs v0.x --- src/x509.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/x509.cc b/src/x509.cc index 7025d6b..1b49355 100644 --- a/src/x509.cc +++ b/src/x509.cc @@ -297,7 +297,11 @@ Local try_parse(const std::string &dataString) Nan::New(fingerprint).ToLocalChecked()); } // public key +#if OPENSSL_VERSION_NUMBER >= 0x10100000L int pkey_nid = X509_get_signature_nid(cert); +#else + int pkey_nid = X509_get_signature_nid(cert->cert_info->key->algor->algorithm); +#endif if (pkey_nid == NID_undef) { ERR_clear_error(); From c76789c49f87181b08e14084175d5d96a23d26fc Mon Sep 17 00:00:00 2001 From: stormwin Date: Sun, 8 Jul 2018 22:56:48 +0200 Subject: [PATCH 13/15] Final fixes --- src/x509.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/x509.cc b/src/x509.cc index 1b49355..3aeb6e6 100644 --- a/src/x509.cc +++ b/src/x509.cc @@ -300,7 +300,7 @@ Local try_parse(const std::string &dataString) #if OPENSSL_VERSION_NUMBER >= 0x10100000L int pkey_nid = X509_get_signature_nid(cert); #else - int pkey_nid = X509_get_signature_nid(cert->cert_info->key->algor->algorithm); + int pkey_nid = OBJ_obj2nid(cert->cert_info->key->algor->algorithm); #endif if (pkey_nid == NID_undef) { From 9f3bdd11c5738f4445fcec7da809b58b323c9294 Mon Sep 17 00:00:00 2001 From: stormwin Date: Sun, 8 Jul 2018 23:29:19 +0200 Subject: [PATCH 14/15] Final fix --- src/x509.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/x509.cc b/src/x509.cc index 3aeb6e6..691051c 100644 --- a/src/x509.cc +++ b/src/x509.cc @@ -331,6 +331,7 @@ Local try_parse(const std::string &dataString) #else rsa_key = pkey->pkey.rsa; rsa_e_dec = BN_bn2dec(rsa_key->e); + rsa_n_hex = BN_bn2hex(rsa_key->n); #endif rsa_key_length_int = RSA_size(rsa_key) * 8; Nan::Set(publicKey, From 40140051e55b2ef5bef73a4412bcdf8e2b672c6a Mon Sep 17 00:00:00 2001 From: stormwin Date: Sun, 29 Jul 2018 13:56:50 +0200 Subject: [PATCH 15/15] change coding style to "{ BasedOnStyle: Google, IndentWidth: 4 }" --- include/x509.h | 16 +- src/addon.cc | 32 +- src/x509.cc | 875 ++++++++++++++++++++++--------------------------- 3 files changed, 420 insertions(+), 503 deletions(-) diff --git a/include/x509.h b/include/x509.h index 1ab0c85..adbbdf1 100644 --- a/include/x509.h +++ b/include/x509.h @@ -3,20 +3,20 @@ // Include header for addon version, node/v8 inclusions, etc. #include -#include #include +#include #include // OpenSSL headers #include #include +#include #include +#include #include #include -#include #include -#include -#include +#include using namespace v8; @@ -26,13 +26,13 @@ NAN_METHOD(get_issuer); NAN_METHOD(parse_cert); NAN_METHOD(verify); -Local try_parse(const std::string& dataString); -Local verify(const std::string& dataString); +Local try_parse(const std::string &dataString); +Local verify(const std::string &dataString); Local parse_date(ASN1_TIME *date); Local parse_serial(ASN1_INTEGER *serial); Local parse_name(X509_NAME *subject); -char* real_name(char *data); -char* trim(char *data, int len); +char *real_name(char *data); +char *trim(char *data, int len); #endif diff --git a/src/addon.cc b/src/addon.cc index f0aab0c..e4c8f2d 100644 --- a/src/addon.cc +++ b/src/addon.cc @@ -1,5 +1,5 @@ -#include #include +#include #include #include @@ -7,26 +7,20 @@ using namespace v8; void init(Local exports) { - Nan::Set(exports, - Nan::New("version").ToLocalChecked(), - Nan::New(VERSION).ToLocalChecked()); + Nan::Set(exports, Nan::New("version").ToLocalChecked(), + Nan::New(VERSION).ToLocalChecked()); - Nan::Set(exports, - Nan::New("verify").ToLocalChecked(), - Nan::New(verify)->GetFunction()); + Nan::Set(exports, Nan::New("verify").ToLocalChecked(), + Nan::New(verify)->GetFunction()); - Nan::Set(exports, - Nan::New("getAltNames").ToLocalChecked(), - Nan::New(get_altnames)->GetFunction()); - Nan::Set(exports, - Nan::New("getSubject").ToLocalChecked(), - Nan::New(get_subject)->GetFunction()); - Nan::Set(exports, - Nan::New("getIssuer").ToLocalChecked(), - Nan::New(get_issuer)->GetFunction()); - Nan::Set(exports, - Nan::New("parseCert").ToLocalChecked(), - Nan::New(parse_cert)->GetFunction()); + Nan::Set(exports, Nan::New("getAltNames").ToLocalChecked(), + Nan::New(get_altnames)->GetFunction()); + Nan::Set(exports, Nan::New("getSubject").ToLocalChecked(), + Nan::New(get_subject)->GetFunction()); + Nan::Set(exports, Nan::New("getIssuer").ToLocalChecked(), + Nan::New(get_issuer)->GetFunction()); + Nan::Set(exports, Nan::New("parseCert").ToLocalChecked(), + Nan::New(parse_cert)->GetFunction()); } NODE_MODULE(x509, init) diff --git a/src/x509.cc b/src/x509.cc index 691051c..9b121d4 100644 --- a/src/x509.cc +++ b/src/x509.cc @@ -1,565 +1,488 @@ +#include #include #include -#include using namespace v8; // Field names that OpenSSL is missing. static const char *MISSING[4][2] = { - {"1.2.840.113533.7.65.0", - "entrustVersionInfo"}, + {"1.2.840.113533.7.65.0", "entrustVersionInfo"}, - {"1.3.6.1.4.1.311.60.2.1.1", - "jurisdictionOfIncorpationLocalityName"}, + {"1.3.6.1.4.1.311.60.2.1.1", "jurisdictionOfIncorpationLocalityName"}, {"1.3.6.1.4.1.311.60.2.1.2", "jurisdictionOfIncorporationStateOrProvinceName"}, - {"1.3.6.1.4.1.311.60.2.1.3", - "jurisdictionOfIncorporationCountryName"}}; - -std::string parse_args(const Nan::FunctionCallbackInfo &info) -{ - if (info.Length() == 0) - { - Nan::ThrowTypeError("Must provide a certificate string."); - return std::string(); - } - - if (!info[0]->IsString()) - { - Nan::ThrowTypeError("Certificate must be a string."); - return std::string(); - } - - if (info[0]->ToString()->Length() == 0) - { - Nan::ThrowTypeError("Certificate argument provided, but left blank."); - return std::string(); - } - - return *Nan::Utf8String(info[0]->ToString()); -} + {"1.3.6.1.4.1.311.60.2.1.3", "jurisdictionOfIncorporationCountryName"}}; -NAN_METHOD(verify) -{ - Nan::HandleScope scope; - OpenSSL_add_all_algorithms(); - - std::string cert_path = *Nan::Utf8String(info[0]->ToString()); - std::string ca_bundlestr = *Nan::Utf8String(info[1]->ToString()); - - X509_STORE *store = NULL; - X509_STORE_CTX *verify_ctx = NULL; - X509 *cert = NULL; - BIO *cert_bio = NULL; - const char *error = NULL; - - do - { - store = X509_STORE_new(); - if (store == NULL) - { - error = "Failed to create X509 certificate store."; - break; - } - verify_ctx = X509_STORE_CTX_new(); - if (verify_ctx == NULL) - { - error = "Failed to create X509 verification context."; - break; - } - cert_bio = BIO_new(BIO_s_file()); - int ret = BIO_read_filename(cert_bio, cert_path.c_str()); - if (ret != 1) - { - error = "Error reading file"; - break; +std::string parse_args(const Nan::FunctionCallbackInfo &info) { + if (info.Length() == 0) { + Nan::ThrowTypeError("Must provide a certificate string."); + return std::string(); } - cert = PEM_read_bio_X509(cert_bio, NULL, 0, NULL); - if (cert == NULL) - { - error = "Failed to load cert"; - break; + + if (!info[0]->IsString()) { + Nan::ThrowTypeError("Certificate must be a string."); + return std::string(); } - ret = X509_STORE_load_locations(store, ca_bundlestr.c_str(), NULL); - if (ret != 1) - { - error = "Error loading CA chain file"; - break; + + if (info[0]->ToString()->Length() == 0) { + Nan::ThrowTypeError("Certificate argument provided, but left blank."); + return std::string(); } - X509_STORE_CTX_init(verify_ctx, store, cert, NULL); - ret = X509_verify_cert(verify_ctx); - if (ret <= 0) - { - error = X509_verify_cert_error_string(X509_STORE_CTX_get_error(verify_ctx)); - break; + + return *Nan::Utf8String(info[0]->ToString()); +} + +NAN_METHOD(verify) { + Nan::HandleScope scope; + OpenSSL_add_all_algorithms(); + + std::string cert_path = *Nan::Utf8String(info[0]->ToString()); + std::string ca_bundlestr = *Nan::Utf8String(info[1]->ToString()); + + X509_STORE *store = NULL; + X509_STORE_CTX *verify_ctx = NULL; + X509 *cert = NULL; + BIO *cert_bio = NULL; + const char *error = NULL; + + do { + store = X509_STORE_new(); + if (store == NULL) { + error = "Failed to create X509 certificate store."; + break; + } + verify_ctx = X509_STORE_CTX_new(); + if (verify_ctx == NULL) { + error = "Failed to create X509 verification context."; + break; + } + cert_bio = BIO_new(BIO_s_file()); + int ret = BIO_read_filename(cert_bio, cert_path.c_str()); + if (ret != 1) { + error = "Error reading file"; + break; + } + cert = PEM_read_bio_X509(cert_bio, NULL, 0, NULL); + if (cert == NULL) { + error = "Failed to load cert"; + break; + } + ret = X509_STORE_load_locations(store, ca_bundlestr.c_str(), NULL); + if (ret != 1) { + error = "Error loading CA chain file"; + break; + } + X509_STORE_CTX_init(verify_ctx, store, cert, NULL); + ret = X509_verify_cert(verify_ctx); + if (ret <= 0) { + error = X509_verify_cert_error_string( + X509_STORE_CTX_get_error(verify_ctx)); + break; + } + } while (0); + + X509_STORE_free(store); + X509_free(cert); + X509_STORE_CTX_free(verify_ctx); + BIO_free_all(cert_bio); + if (error != NULL) { + Nan::ThrowError(error); + } else { + info.GetReturnValue().Set(Nan::New(true)); } - } while (0); - - X509_STORE_free(store); - X509_free(cert); - X509_STORE_CTX_free(verify_ctx); - BIO_free_all(cert_bio); - if (error != NULL) - { - Nan::ThrowError(error); - } - else - { - info.GetReturnValue().Set(Nan::New(true)); - } } -NAN_METHOD(get_altnames) -{ - Nan::HandleScope scope; - std::string parsed_arg = parse_args(info); - if (parsed_arg.size() == 0) - { - info.GetReturnValue().SetUndefined(); - } - Local exports(try_parse(parsed_arg)->ToObject()); - Local key = Nan::New("altNames").ToLocalChecked(); - info.GetReturnValue().Set( - Nan::Get(exports, key).ToLocalChecked()); - ERR_clear_error(); +NAN_METHOD(get_altnames) { + Nan::HandleScope scope; + std::string parsed_arg = parse_args(info); + if (parsed_arg.size() == 0) { + info.GetReturnValue().SetUndefined(); + } + Local exports(try_parse(parsed_arg)->ToObject()); + Local key = Nan::New("altNames").ToLocalChecked(); + info.GetReturnValue().Set(Nan::Get(exports, key).ToLocalChecked()); + ERR_clear_error(); } -NAN_METHOD(get_subject) -{ - Nan::HandleScope scope; - std::string parsed_arg = parse_args(info); - if (parsed_arg.size() == 0) - { - info.GetReturnValue().SetUndefined(); - } - Local exports(try_parse(parsed_arg)->ToObject()); - Local key = Nan::New("subject").ToLocalChecked(); - info.GetReturnValue().Set( - Nan::Get(exports, key).ToLocalChecked()); - ERR_clear_error(); +NAN_METHOD(get_subject) { + Nan::HandleScope scope; + std::string parsed_arg = parse_args(info); + if (parsed_arg.size() == 0) { + info.GetReturnValue().SetUndefined(); + } + Local exports(try_parse(parsed_arg)->ToObject()); + Local key = Nan::New("subject").ToLocalChecked(); + info.GetReturnValue().Set(Nan::Get(exports, key).ToLocalChecked()); + ERR_clear_error(); } -NAN_METHOD(get_issuer) -{ - Nan::HandleScope scope; - std::string parsed_arg = parse_args(info); - if (parsed_arg.size() == 0) - { - info.GetReturnValue().SetUndefined(); - } - Local exports(try_parse(parsed_arg)->ToObject()); - Local key = Nan::New("issuer").ToLocalChecked(); - info.GetReturnValue().Set( - Nan::Get(exports, key).ToLocalChecked()); - ERR_clear_error(); +NAN_METHOD(get_issuer) { + Nan::HandleScope scope; + std::string parsed_arg = parse_args(info); + if (parsed_arg.size() == 0) { + info.GetReturnValue().SetUndefined(); + } + Local exports(try_parse(parsed_arg)->ToObject()); + Local key = Nan::New("issuer").ToLocalChecked(); + info.GetReturnValue().Set(Nan::Get(exports, key).ToLocalChecked()); + ERR_clear_error(); } -NAN_METHOD(parse_cert) -{ - Nan::HandleScope scope; - std::string parsed_arg = parse_args(info); - if (parsed_arg.size() == 0) - { - info.GetReturnValue().SetUndefined(); - } - - Local exports(try_parse(parsed_arg)->ToObject()); - info.GetReturnValue().Set(exports); - ERR_clear_error(); +NAN_METHOD(parse_cert) { + Nan::HandleScope scope; + std::string parsed_arg = parse_args(info); + if (parsed_arg.size() == 0) { + info.GetReturnValue().SetUndefined(); + } + + Local exports(try_parse(parsed_arg)->ToObject()); + info.GetReturnValue().Set(exports); + ERR_clear_error(); } /* * This is where everything is handled for both -0.11.2 and 0.11.3+. */ -Local try_parse(const std::string &dataString) -{ - Nan::EscapableHandleScope scope; - const char *data = dataString.c_str(); - - Local exports = Nan::New(); - X509 *cert; - - BIO *bio = BIO_new(BIO_s_mem()); - int result = BIO_puts(bio, data); - - if (result == -2) - { - Nan::ThrowError("BIO doesn't support BIO_puts."); - BIO_free(bio); - return scope.Escape(exports); - } - else if (result <= 0) - { - Nan::ThrowError("No data was written to BIO."); - BIO_free(bio); - return scope.Escape(exports); - } - - // Try raw read - cert = PEM_read_bio_X509(bio, NULL, 0, NULL); - - if (cert == NULL) - { - BIO_free_all(bio); - // Switch to file BIO - bio = BIO_new(BIO_s_file()); - - // If raw read fails, try reading the input as a filename. - if (!BIO_read_filename(bio, data)) - { - ERR_clear_error(); - Nan::ThrowError("File doesn't exist."); - BIO_free(bio); - return scope.Escape(exports); +Local try_parse(const std::string &dataString) { + Nan::EscapableHandleScope scope; + const char *data = dataString.c_str(); + + Local exports = Nan::New(); + X509 *cert; + + BIO *bio = BIO_new(BIO_s_mem()); + int result = BIO_puts(bio, data); + + if (result == -2) { + Nan::ThrowError("BIO doesn't support BIO_puts."); + BIO_free(bio); + return scope.Escape(exports); + } else if (result <= 0) { + Nan::ThrowError("No data was written to BIO."); + BIO_free(bio); + return scope.Escape(exports); } - // Try reading the bio again with the file in it. + // Try raw read cert = PEM_read_bio_X509(bio, NULL, 0, NULL); - if (cert == NULL) - { - ERR_clear_error(); - Nan::ThrowError("Unable to parse certificate."); - BIO_free(bio); - return scope.Escape(exports); + if (cert == NULL) { + BIO_free_all(bio); + // Switch to file BIO + bio = BIO_new(BIO_s_file()); + + // If raw read fails, try reading the input as a filename. + if (!BIO_read_filename(bio, data)) { + ERR_clear_error(); + Nan::ThrowError("File doesn't exist."); + BIO_free(bio); + return scope.Escape(exports); + } + + // Try reading the bio again with the file in it. + cert = PEM_read_bio_X509(bio, NULL, 0, NULL); + + if (cert == NULL) { + ERR_clear_error(); + Nan::ThrowError("Unable to parse certificate."); + BIO_free(bio); + return scope.Escape(exports); + } } - } - - Nan::Set(exports, - Nan::New("version").ToLocalChecked(), - Nan::New((int)X509_get_version(cert))); - Nan::Set(exports, - Nan::New("subject").ToLocalChecked(), - parse_name(X509_get_subject_name(cert))); - Nan::Set(exports, - Nan::New("issuer").ToLocalChecked(), - parse_name(X509_get_issuer_name(cert))); - Nan::Set(exports, - Nan::New("serial").ToLocalChecked(), - parse_serial(X509_get_serialNumber(cert))); - Nan::Set(exports, - Nan::New("notBefore").ToLocalChecked(), - parse_date(X509_get_notBefore(cert))); - Nan::Set(exports, - Nan::New("notAfter").ToLocalChecked(), - parse_date(X509_get_notAfter(cert))); - // Subject hash - std::stringstream stream; - stream << std::hex << X509_subject_name_hash(cert); - Nan::Set(exports, - Nan::New("subjectHash").ToLocalChecked(), - Nan::New(stream.str()).ToLocalChecked()); - - // Signature Algorithm + + Nan::Set(exports, Nan::New("version").ToLocalChecked(), + Nan::New((int)X509_get_version(cert))); + Nan::Set(exports, Nan::New("subject").ToLocalChecked(), + parse_name(X509_get_subject_name(cert))); + Nan::Set(exports, Nan::New("issuer").ToLocalChecked(), + parse_name(X509_get_issuer_name(cert))); + Nan::Set(exports, Nan::New("serial").ToLocalChecked(), + parse_serial(X509_get_serialNumber(cert))); + Nan::Set(exports, Nan::New("notBefore").ToLocalChecked(), + parse_date(X509_get_notBefore(cert))); + Nan::Set(exports, Nan::New("notAfter").ToLocalChecked(), + parse_date(X509_get_notAfter(cert))); + // Subject hash + std::stringstream stream; + stream << std::hex << X509_subject_name_hash(cert); + Nan::Set(exports, Nan::New("subjectHash").ToLocalChecked(), + Nan::New(stream.str()).ToLocalChecked()); + + // Signature Algorithm #if OPENSSL_VERSION_NUMBER >= 0x10100000L - int sig_alg_nid = X509_get_signature_nid(cert); + int sig_alg_nid = X509_get_signature_nid(cert); #else - int sig_alg_nid = OBJ_obj2nid(cert->sig_alg->algorithm); + int sig_alg_nid = OBJ_obj2nid(cert->sig_alg->algorithm); #endif - if (sig_alg_nid == NID_undef) - { - ERR_clear_error(); - Nan::ThrowError("unable to find specified signature algorithm name."); - X509_free(cert); - BIO_free(bio); - return scope.Escape(exports); - } - Nan::Set(exports, - Nan::New("signatureAlgorithm").ToLocalChecked(), - Nan::New(OBJ_nid2ln(sig_alg_nid)).ToLocalChecked()); - - // fingerPrint - unsigned int md_size, idx; - unsigned char md[EVP_MAX_MD_SIZE]; - if (X509_digest(cert, EVP_sha1(), md, &md_size)) - { - const char hex[] = "0123456789ABCDEF"; - char fingerprint[EVP_MAX_MD_SIZE * 3]; - for (idx = 0; idx < md_size; idx++) - { - fingerprint[3 * idx] = hex[(md[idx] & 0xf0) >> 4]; - fingerprint[(3 * idx) + 1] = hex[(md[idx] & 0x0f)]; - fingerprint[(3 * idx) + 2] = ':'; + if (sig_alg_nid == NID_undef) { + ERR_clear_error(); + Nan::ThrowError("unable to find specified signature algorithm name."); + X509_free(cert); + BIO_free(bio); + return scope.Escape(exports); } + Nan::Set(exports, Nan::New("signatureAlgorithm").ToLocalChecked(), + Nan::New(OBJ_nid2ln(sig_alg_nid)).ToLocalChecked()); + + // fingerPrint + unsigned int md_size, idx; + unsigned char md[EVP_MAX_MD_SIZE]; + if (X509_digest(cert, EVP_sha1(), md, &md_size)) { + const char hex[] = "0123456789ABCDEF"; + char fingerprint[EVP_MAX_MD_SIZE * 3]; + for (idx = 0; idx < md_size; idx++) { + fingerprint[3 * idx] = hex[(md[idx] & 0xf0) >> 4]; + fingerprint[(3 * idx) + 1] = hex[(md[idx] & 0x0f)]; + fingerprint[(3 * idx) + 2] = ':'; + } - if (md_size > 0) - { - fingerprint[(3 * (md_size - 1)) + 2] = '\0'; - } - else - { - fingerprint[0] = '\0'; + if (md_size > 0) { + fingerprint[(3 * (md_size - 1)) + 2] = '\0'; + } else { + fingerprint[0] = '\0'; + } + Nan::Set(exports, Nan::New("fingerPrint").ToLocalChecked(), + Nan::New(fingerprint).ToLocalChecked()); } - Nan::Set(exports, - Nan::New("fingerPrint").ToLocalChecked(), - Nan::New(fingerprint).ToLocalChecked()); - } - // public key + // public key #if OPENSSL_VERSION_NUMBER >= 0x10100000L - int pkey_nid = X509_get_signature_nid(cert); + int pkey_nid = X509_get_signature_nid(cert); #else - int pkey_nid = OBJ_obj2nid(cert->cert_info->key->algor->algorithm); + int pkey_nid = OBJ_obj2nid(cert->cert_info->key->algor->algorithm); #endif - if (pkey_nid == NID_undef) - { - ERR_clear_error(); - Nan::ThrowError("unable to find specified public key algorithm name."); - X509_free(cert); - BIO_free(bio); - return scope.Escape(exports); - } - EVP_PKEY *pkey = X509_get_pubkey(cert); - Local publicKey = Nan::New(); - Nan::Set(publicKey, - Nan::New("algorithm").ToLocalChecked(), - Nan::New(OBJ_nid2ln(pkey_nid)).ToLocalChecked()); - - if (pkey_nid == NID_rsaEncryption) - { - char *rsa_e_dec, *rsa_n_hex; - uint32_t rsa_key_length_int; - RSA *rsa_key; + if (pkey_nid == NID_undef) { + ERR_clear_error(); + Nan::ThrowError("unable to find specified public key algorithm name."); + X509_free(cert); + BIO_free(bio); + return scope.Escape(exports); + } + EVP_PKEY *pkey = X509_get_pubkey(cert); + Local publicKey = Nan::New(); + Nan::Set(publicKey, Nan::New("algorithm").ToLocalChecked(), + Nan::New(OBJ_nid2ln(pkey_nid)).ToLocalChecked()); + + if (pkey_nid == NID_rsaEncryption) { + char *rsa_e_dec, *rsa_n_hex; + uint32_t rsa_key_length_int; + RSA *rsa_key; #if OPENSSL_VERSION_NUMBER >= 0x10100000L - rsa_key = EVP_PKEY_get1_RSA(pkey); - const BIGNUM *n; - const BIGNUM *e; - RSA_get0_key(rsa_key, &n, &e, NULL); - rsa_e_dec = BN_bn2dec(e); - rsa_n_hex = BN_bn2hex(n); + rsa_key = EVP_PKEY_get1_RSA(pkey); + const BIGNUM *n; + const BIGNUM *e; + RSA_get0_key(rsa_key, &n, &e, NULL); + rsa_e_dec = BN_bn2dec(e); + rsa_n_hex = BN_bn2hex(n); #else - rsa_key = pkey->pkey.rsa; - rsa_e_dec = BN_bn2dec(rsa_key->e); - rsa_n_hex = BN_bn2hex(rsa_key->n); + rsa_key = pkey->pkey.rsa; + rsa_e_dec = BN_bn2dec(rsa_key->e); + rsa_n_hex = BN_bn2hex(rsa_key->n); #endif - rsa_key_length_int = RSA_size(rsa_key) * 8; - Nan::Set(publicKey, - Nan::New("e").ToLocalChecked(), - Nan::New(rsa_e_dec).ToLocalChecked()); - OPENSSL_free(rsa_e_dec); - Nan::Set(publicKey, - Nan::New("n").ToLocalChecked(), - Nan::New(rsa_n_hex).ToLocalChecked()); - OPENSSL_free(rsa_n_hex); - Nan::Set(publicKey, - Nan::New("bitSize").ToLocalChecked(), - Nan::New(rsa_key_length_int)); - } - Nan::Set(exports, Nan::New("publicKey").ToLocalChecked(), publicKey); - EVP_PKEY_free(pkey); - - // alt names - Local altNames(Nan::New()); - STACK_OF(GENERAL_NAME) *names = NULL; - int i; - - names = (STACK_OF(GENERAL_NAME) *)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); - - if (names != NULL) - { - int length = sk_GENERAL_NAME_num(names); - for (i = 0; i < length; i++) - { - GENERAL_NAME *current = sk_GENERAL_NAME_value(names, i); - - if (current->type == GEN_DNS) - { - char *name = NULL; + rsa_key_length_int = RSA_size(rsa_key) * 8; + Nan::Set(publicKey, Nan::New("e").ToLocalChecked(), + Nan::New(rsa_e_dec).ToLocalChecked()); + OPENSSL_free(rsa_e_dec); + Nan::Set(publicKey, Nan::New("n").ToLocalChecked(), + Nan::New(rsa_n_hex).ToLocalChecked()); + OPENSSL_free(rsa_n_hex); + Nan::Set(publicKey, Nan::New("bitSize").ToLocalChecked(), + Nan::New(rsa_key_length_int)); + } + Nan::Set(exports, Nan::New("publicKey").ToLocalChecked(), + publicKey); + EVP_PKEY_free(pkey); + + // alt names + Local altNames(Nan::New()); + STACK_OF(GENERAL_NAME) *names = NULL; + int i; + + names = (STACK_OF(GENERAL_NAME) *)X509_get_ext_d2i( + cert, NID_subject_alt_name, NULL, NULL); + + if (names != NULL) { + int length = sk_GENERAL_NAME_num(names); + for (i = 0; i < length; i++) { + GENERAL_NAME *current = sk_GENERAL_NAME_value(names, i); + + if (current->type == GEN_DNS) { + char *name = NULL; #if OPENSSL_VERSION_NUMBER >= 0x10100000L - name = (char *)ASN1_STRING_get0_data(current->d.dNSName); + name = (char *)ASN1_STRING_get0_data(current->d.dNSName); #else - name = (char *)ASN1_STRING_data(current->d.dNSName); + name = (char *)ASN1_STRING_data(current->d.dNSName); #endif - if (ASN1_STRING_length(current->d.dNSName) != (int)strlen(name)) - { - ERR_clear_error(); - Nan::ThrowError("Malformed alternative names field."); - X509_free(cert); - BIO_free(bio); - return scope.Escape(exports); + if (ASN1_STRING_length(current->d.dNSName) != + (int)strlen(name)) { + ERR_clear_error(); + Nan::ThrowError("Malformed alternative names field."); + X509_free(cert); + BIO_free(bio); + return scope.Escape(exports); + } + Nan::Set(altNames, i, Nan::New(name).ToLocalChecked()); + } } - Nan::Set(altNames, i, Nan::New(name).ToLocalChecked()); - } + sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); } - sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); - } - Nan::Set(exports, Nan::New("altNames").ToLocalChecked(), altNames); + Nan::Set(exports, Nan::New("altNames").ToLocalChecked(), altNames); - // Extensions - Local extensions(Nan::New()); + // Extensions + Local extensions(Nan::New()); #if OPENSSL_VERSION_NUMBER >= 0x10100000L - const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert); + const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert); #else - STACK_OF(X509_EXTENSION) *exts = cert->cert_info->extensions; + STACK_OF(X509_EXTENSION) *exts = cert->cert_info->extensions; #endif - int num_of_exts = X509v3_get_ext_count(exts); - int index_of_exts; + int num_of_exts = X509v3_get_ext_count(exts); + int index_of_exts; - // IFNEG_FAIL(num_of_exts, "error parsing number of X509v3 extensions."); + // IFNEG_FAIL(num_of_exts, "error parsing number of X509v3 extensions."); - for (index_of_exts = 0; index_of_exts < num_of_exts; index_of_exts++) - { - X509_EXTENSION *ext = X509v3_get_ext(exts, index_of_exts); - ASN1_OBJECT *obj = X509_EXTENSION_get_object(ext); + for (index_of_exts = 0; index_of_exts < num_of_exts; index_of_exts++) { + X509_EXTENSION *ext = X509v3_get_ext(exts, index_of_exts); + ASN1_OBJECT *obj = X509_EXTENSION_get_object(ext); - // IFNULL_FAIL(obj, "unable to extract ASN1 object from extension"); + // IFNULL_FAIL(obj, "unable to extract ASN1 object from extension"); - BIO *ext_bio = BIO_new(BIO_s_mem()); - // IFNULL_FAIL(ext_bio, "unable to allocate memory for extension value BIO"); - if (!X509V3_EXT_print(ext_bio, ext, 0, 0)) - { - unsigned char *buf = NULL; - int len = i2d_ASN1_OCTET_STRING(X509_EXTENSION_get_data(ext), &buf); - if (len >= 0) - { - BIO_write(ext_bio, static_cast(buf), len); - } - } + BIO *ext_bio = BIO_new(BIO_s_mem()); + // IFNULL_FAIL(ext_bio, "unable to allocate memory for extension value + // BIO"); + if (!X509V3_EXT_print(ext_bio, ext, 0, 0)) { + unsigned char *buf = NULL; + int len = i2d_ASN1_OCTET_STRING(X509_EXTENSION_get_data(ext), &buf); + if (len >= 0) { + BIO_write(ext_bio, static_cast(buf), len); + } + } - BUF_MEM *bptr; - BIO_get_mem_ptr(ext_bio, &bptr); + BUF_MEM *bptr; + BIO_get_mem_ptr(ext_bio, &bptr); - char *data = new char[bptr->length + 1]; - char *trimmed_data; - if (bptr->data == NULL) - { - trimmed_data = (char *)""; - } - else - { - BUF_strlcpy(data, bptr->data, bptr->length + 1); - trimmed_data = trim(data, bptr->length); - } - BIO_free(ext_bio); - - unsigned nid = OBJ_obj2nid(obj); + char *data = new char[bptr->length + 1]; + char *trimmed_data; + if (bptr->data == NULL) { + trimmed_data = (char *)""; + } else { + BUF_strlcpy(data, bptr->data, bptr->length + 1); + trimmed_data = trim(data, bptr->length); + } + BIO_free(ext_bio); + + unsigned nid = OBJ_obj2nid(obj); + + if (nid == NID_undef) { + char extname[100]; + OBJ_obj2txt(extname, 100, (const ASN1_OBJECT *)obj, 1); + Nan::Set(extensions, + Nan::New(real_name(extname)).ToLocalChecked(), + Nan::New(trimmed_data).ToLocalChecked()); + } else { + const char *c_ext_name = OBJ_nid2ln(nid); + // IFNULL_FAIL(c_ext_name, "invalid X509v3 extension name"); + Nan::Set(extensions, + Nan::New(real_name((char *)c_ext_name)) + .ToLocalChecked(), + Nan::New(trimmed_data).ToLocalChecked()); + } - if (nid == NID_undef) - { - char extname[100]; - OBJ_obj2txt(extname, 100, (const ASN1_OBJECT *)obj, 1); - Nan::Set(extensions, - Nan::New(real_name(extname)).ToLocalChecked(), - Nan::New(trimmed_data).ToLocalChecked()); - } - else - { - const char *c_ext_name = OBJ_nid2ln(nid); - // IFNULL_FAIL(c_ext_name, "invalid X509v3 extension name"); - Nan::Set(extensions, - Nan::New(real_name((char *)c_ext_name)).ToLocalChecked(), - Nan::New(trimmed_data).ToLocalChecked()); + delete[] data; } - delete[] data; - } - - Nan::Set(exports, - Nan::New("extensions").ToLocalChecked(), extensions); + Nan::Set(exports, Nan::New("extensions").ToLocalChecked(), + extensions); - ERR_clear_error(); - X509_free(cert); - BIO_free(bio); + ERR_clear_error(); + X509_free(cert); + BIO_free(bio); - return scope.Escape(exports); + return scope.Escape(exports); } -Local parse_serial(ASN1_INTEGER *serial) -{ - Nan::EscapableHandleScope scope; - Local serialNumber; - BIGNUM *bn = ASN1_INTEGER_to_BN(serial, NULL); - char *hex = BN_bn2hex(bn); - - serialNumber = Nan::New(hex).ToLocalChecked(); - BN_free(bn); - OPENSSL_free(hex); - return scope.Escape(serialNumber); +Local parse_serial(ASN1_INTEGER *serial) { + Nan::EscapableHandleScope scope; + Local serialNumber; + BIGNUM *bn = ASN1_INTEGER_to_BN(serial, NULL); + char *hex = BN_bn2hex(bn); + + serialNumber = Nan::New(hex).ToLocalChecked(); + BN_free(bn); + OPENSSL_free(hex); + return scope.Escape(serialNumber); } -Local parse_date(ASN1_TIME *date) -{ - Nan::EscapableHandleScope scope; - BUF_MEM *bm; - char formatted[64]; - Local args[1]; - formatted[0] = '\0'; - BIO *bio = BIO_new(BIO_s_mem()); - ASN1_TIME_print(bio, date); - BIO_get_mem_ptr(bio, &bm); - BUF_strlcpy(formatted, bm->data, bm->length + 1); - BIO_free(bio); - args[0] = Nan::New(formatted).ToLocalChecked(); - Local global = Nan::GetCurrentContext()->Global(); - Local DateObject = Nan::Get(global, - Nan::New("Date").ToLocalChecked()) - .ToLocalChecked() - ->ToObject(); - return scope.Escape(Nan::CallAsConstructor(DateObject, 1, args).ToLocalChecked()); +Local parse_date(ASN1_TIME *date) { + Nan::EscapableHandleScope scope; + BUF_MEM *bm; + char formatted[64]; + Local args[1]; + formatted[0] = '\0'; + BIO *bio = BIO_new(BIO_s_mem()); + ASN1_TIME_print(bio, date); + BIO_get_mem_ptr(bio, &bm); + BUF_strlcpy(formatted, bm->data, bm->length + 1); + BIO_free(bio); + args[0] = Nan::New(formatted).ToLocalChecked(); + Local global = Nan::GetCurrentContext()->Global(); + Local DateObject = + Nan::Get(global, Nan::New("Date").ToLocalChecked()) + .ToLocalChecked() + ->ToObject(); + return scope.Escape( + Nan::CallAsConstructor(DateObject, 1, args).ToLocalChecked()); } -Local parse_name(X509_NAME *subject) -{ - Nan::EscapableHandleScope scope; - Local cert = Nan::New(); - int i, length; - ASN1_OBJECT *entry; - const unsigned char *value; - char buf[255]; - length = X509_NAME_entry_count(subject); - for (i = 0; i < length; i++) - { - entry = X509_NAME_ENTRY_get_object(X509_NAME_get_entry(subject, i)); - OBJ_obj2txt(buf, 255, entry, 0); +Local parse_name(X509_NAME *subject) { + Nan::EscapableHandleScope scope; + Local cert = Nan::New(); + int i, length; + ASN1_OBJECT *entry; + const unsigned char *value; + char buf[255]; + length = X509_NAME_entry_count(subject); + for (i = 0; i < length; i++) { + entry = X509_NAME_ENTRY_get_object(X509_NAME_get_entry(subject, i)); + OBJ_obj2txt(buf, 255, entry, 0); #if OPENSSL_VERSION_NUMBER >= 0x10100000L - value = ASN1_STRING_get0_data(X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject, i))); + value = ASN1_STRING_get0_data( + X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject, i))); #else - value = ASN1_STRING_data(X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject, i))); + value = ASN1_STRING_data( + X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject, i))); #endif - Nan::Set(cert, - Nan::New(real_name(buf)).ToLocalChecked(), - Nan::New((const char *)value).ToLocalChecked()); - } - return scope.Escape(cert); + Nan::Set(cert, Nan::New(real_name(buf)).ToLocalChecked(), + Nan::New((const char *)value).ToLocalChecked()); + } + return scope.Escape(cert); } // Fix for missing fields in OpenSSL. -char *real_name(char *data) -{ - int i, length = (int)sizeof(MISSING) / sizeof(MISSING[0]); +char *real_name(char *data) { + int i, length = (int)sizeof(MISSING) / sizeof(MISSING[0]); - for (i = 0; i < length; i++) - { - if (strcmp(data, MISSING[i][0]) == 0) - return (char *)MISSING[i][1]; - } + for (i = 0; i < length; i++) { + if (strcmp(data, MISSING[i][0]) == 0) return (char *)MISSING[i][1]; + } - return data; + return data; } -char *trim(char *data, int len) -{ - if (data[0] == '\n' || data[0] == '\r') - { - data = data + 1; - } - else if (len > 1 && (data[len - 1] == '\n' || data[len - 1] == '\r')) - { - data[len - 1] = (char)0; - } - else if (len > 0 && (data[len] == '\n' || data[len] == '\r')) - { - data[len] = (char)0; - } - else - { - return data; - } +char *trim(char *data, int len) { + if (data[0] == '\n' || data[0] == '\r') { + data = data + 1; + } else if (len > 1 && (data[len - 1] == '\n' || data[len - 1] == '\r')) { + data[len - 1] = (char)0; + } else if (len > 0 && (data[len] == '\n' || data[len] == '\r')) { + data[len] = (char)0; + } else { + return data; + } - return trim(data, len - 1); + return trim(data, len - 1); }