Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,21 @@ x509.verify(

```

#### x509.verifyFromStr(`certStr`, `caStr`, function(err, result){ /*...*/})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use CABundleStr to replace caStr to keep consistent with verify().

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CABundleStr should be caBundleStr. It is not a constant, therefore it should not start with a capital.


It is the same with verify.

```js
const x509 = require('x509');

x509.verify(
path.readFileSync(__dirname + '/certs/user.com.crt'),
path.readFileSync(__dirname + 'enduser-example.com.chain'),
function(err, result){ /*...*/}
);

```

## Examples
Checking the date to make sure the certificate is active:
```js
Expand Down
2 changes: 2 additions & 0 deletions include/x509.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ NAN_METHOD(get_subject);
NAN_METHOD(get_issuer);
NAN_METHOD(parse_cert);
NAN_METHOD(verify);
NAN_METHOD(verifyFromStr);

Local<Value> try_parse(const std::string& dataString);
Local<Value> verify(const std::string& dataString);
Local<Value> verifyFromStr(const std::string& dataString);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to verify_from_str().

Local<Value> parse_date(ASN1_TIME *date);
Local<Value> parse_serial(ASN1_INTEGER *serial);
Local<Object> parse_name(X509_NAME *subject);
Expand Down
13 changes: 13 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ exports.getAltNames = x509.getAltNames;
exports.getSubject = x509.getSubject;
exports.getIssuer = x509.getIssuer;

exports.verifyFromStr = function(certStr, CABundleStr, cb) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid if certStr and CABundleStr is a Buffer or String.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CABundleStr should be caBundleStr. It is not a constant, therefore it should not start with a capital.

var caughtErr = null;
try {
x509.verifyFromStr(certStr, CABundleStr);
}
catch (verificationError) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move catch to previous line, please :)

caughtErr = verificationError;
}
finally {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

cb(caughtErr);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid the callback is a function, too.

}
};

exports.verify = function(certPath, CABundlePath, cb) {
if (!certPath) {
throw new TypeError('Certificate path is required');
Expand Down
4 changes: 4 additions & 0 deletions src/addon.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ void init(Local<Object> exports) {
Nan::Set(exports,
Nan::New<String>("version").ToLocalChecked(),
Nan::New<String>(VERSION).ToLocalChecked());

Nan::Set(exports,
Nan::New<String>("verifyFromStr").ToLocalChecked(),
Nan::New<FunctionTemplate>(verifyFromStr)->GetFunction());

Nan::Set(exports,
Nan::New<String>("verify").ToLocalChecked(),
Expand Down
67 changes: 66 additions & 1 deletion src/x509.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,72 @@ std::string parse_args(const Nan::FunctionCallbackInfo<v8::Value>& info) {
return *String::Utf8Value(info[0]->ToString());
}


NAN_METHOD(verifyFromStr) {
Nan::HandleScope scope;
OpenSSL_add_all_algorithms();
std::string cert_str = *String::Utf8Value(info[0]->ToString());
std::string ca_str = *String::Utf8Value(info[1]->ToString());

X509_STORE *store = NULL;
X509_STORE_CTX *verify_ctx = NULL;
X509 *ca_cert = NULL;
BIO *ca_bio = 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_mem());
size_t ret = BIO_puts(cert_bio, cert_str.c_str());
if (ret != cert_str.length()) {
error = "Error reading cert content";
break;
}
cert = PEM_read_bio_X509(cert_bio, NULL, 0, NULL);
if (cert == NULL) {
error = "Failed to load cert";
break;
}
ca_bio = BIO_new(BIO_s_mem());
ret = BIO_puts(ca_bio, ca_str.c_str());
if (ret != ca_str.length()) {
error = "Error reading ca content";
break;
}
ca_cert = PEM_read_bio_X509(ca_bio, NULL, 0, NULL);
if (ca_cert == NULL) {
error = "Failed to load ca";
break;
}
X509_STORE_CTX_init(verify_ctx, store, ca_cert, NULL);
X509_STORE_add_cert(store, cert);
ret = X509_verify_cert(verify_ctx);
if (ret < 1) {
error = X509_verify_cert_error_string(verify_ctx->error);
break;
}
} while(0);
X509_STORE_free(store);
X509_STORE_CTX_free(verify_ctx);
X509_free(ca_cert);
BIO_free_all(ca_bio);
X509_free(cert);
BIO_free_all(cert_bio);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check store, verify_ctx and others is a NULL, free a NULL might cause segfault.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these functions have checked NULL, the free function also does nothing when ptr is NULL , so we don't need to check again

if (error != NULL) {
Nan::ThrowError(error);
} else {
info.GetReturnValue().Set(Nan::New(true));
}
}

NAN_METHOD(verify) {
Nan::HandleScope scope;
Expand Down
32 changes: 32 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,36 @@ x509.verify(
function(err, result) {
assert.throws(assert.ifError.bind(null, err), /Failed to load cert/)
}
);

x509.verifyFromStr(
fs.readFileSync(path.join(__dirname, 'certs/enduser-example.com.crt')),
fs.readFileSync(path.join(__dirname, 'CA_chains/enduser-example.com.chain')),
function(err, result) {
assert.strictEqual(err, null)
}
);

x509.verifyFromStr(
fs.readFileSync(path.join(__dirname, 'certs/acaline.com.crt')),
fs.readFileSync(path.join(__dirname, 'CA_chains/enduser-example.com.chain')),
function(err, result) {
assert.throws(assert.ifError.bind(null, err), /self signed certificate/)
}
);

x509.verifyFromStr(
fs.readFileSync(path.join(__dirname, 'test.js')),
fs.readFileSync(path.join(__dirname, 'CA_chains/enduser-example.com.chain')),
function(err, result) {
assert.throws(assert.ifError.bind(null, err), /Failed to load cert/)
}
);

x509.verifyFromStr(
fs.readFileSync(path.join(__dirname, 'certs/acaline.com.crt')),
fs.readFileSync(path.join(__dirname, 'test.js')),
function(err, result) {
assert.throws(assert.ifError.bind(null, err), /Failed to load ca/)
}
);