summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorjoelostrowski <jo@craftwork.dk>2016-04-15 16:49:36 +0200
committerRich Trott <rtrott@gmail.com>2017-11-11 13:35:23 -0800
commit6ee985f311de14621c440377f76d0391b6b23320 (patch)
tree59f867c0c20454201dba81344aab16bff5c72a48 /test
parentf7436ba1358f6af30d7d9baffdbef8754573f0e5 (diff)
downloadandroid-node-v8-6ee985f311de14621c440377f76d0391b6b23320.tar.gz
android-node-v8-6ee985f311de14621c440377f76d0391b6b23320.tar.bz2
android-node-v8-6ee985f311de14621c440377f76d0391b6b23320.zip
tls: implement clientCertEngine option
Add an option 'clientCertEngine' to `tls.createSecureContext()` which gets wired up to OpenSSL function `SSL_CTX_set_client_cert_engine`. The option is passed through from `https.request()` as well. This allows using a custom OpenSSL engine to provide the client certificate.
Diffstat (limited to 'test')
-rw-r--r--test/addons/openssl-client-cert-engine/binding.gyp24
-rw-r--r--test/addons/openssl-client-cert-engine/test.js62
-rw-r--r--test/addons/openssl-client-cert-engine/testengine.cc100
-rw-r--r--test/parallel/test-https-agent-getname.js4
4 files changed, 188 insertions, 2 deletions
diff --git a/test/addons/openssl-client-cert-engine/binding.gyp b/test/addons/openssl-client-cert-engine/binding.gyp
new file mode 100644
index 0000000000..b069e43429
--- /dev/null
+++ b/test/addons/openssl-client-cert-engine/binding.gyp
@@ -0,0 +1,24 @@
+{
+ 'targets': [
+ {
+ 'target_name': 'testengine',
+ 'type': 'none',
+ 'conditions': [
+ ['OS=="mac" and '
+ 'node_use_openssl=="true" and '
+ 'node_shared=="false" and '
+ 'node_shared_openssl=="false"', {
+ 'type': 'shared_library',
+ 'sources': [ 'testengine.cc' ],
+ 'product_extension': 'engine',
+ 'include_dirs': ['../../../deps/openssl/openssl/include'],
+ 'link_settings': {
+ 'libraries': [
+ '../../../../out/<(PRODUCT_DIR)/<(OPENSSL_PRODUCT)'
+ ]
+ },
+ }]
+ ]
+ }
+ ]
+}
diff --git a/test/addons/openssl-client-cert-engine/test.js b/test/addons/openssl-client-cert-engine/test.js
new file mode 100644
index 0000000000..d07b9c6a1c
--- /dev/null
+++ b/test/addons/openssl-client-cert-engine/test.js
@@ -0,0 +1,62 @@
+'use strict';
+const common = require('../../common');
+const fixture = require('../../common/fixtures');
+
+if (!common.hasCrypto)
+ common.skip('missing crypto');
+
+const fs = require('fs');
+const path = require('path');
+
+const engine = path.join(__dirname,
+ `/build/${common.buildType}/testengine.engine`);
+
+if (!fs.existsSync(engine))
+ common.skip('no client cert engine');
+
+const assert = require('assert');
+const https = require('https');
+
+const agentKey = fs.readFileSync(fixture.path('/keys/agent1-key.pem'));
+const agentCert = fs.readFileSync(fixture.path('/keys/agent1-cert.pem'));
+const agentCa = fs.readFileSync(fixture.path('/keys/ca1-cert.pem'));
+
+const port = common.PORT;
+
+const serverOptions = {
+ key: agentKey,
+ cert: agentCert,
+ ca: agentCa,
+ requestCert: true,
+ rejectUnauthorized: true
+};
+
+const server = https.createServer(serverOptions, (req, res) => {
+ res.writeHead(200);
+ res.end('hello world');
+}).listen(port, common.localhostIPv4, () => {
+ const clientOptions = {
+ method: 'GET',
+ host: common.localhostIPv4,
+ port: port,
+ path: '/test',
+ clientCertEngine: engine, // engine will provide key+cert
+ rejectUnauthorized: false, // prevent failing on self-signed certificates
+ headers: {}
+ };
+
+ const req = https.request(clientOptions, common.mustCall(function(response) {
+ let body = '';
+ response.setEncoding('utf8');
+ response.on('data', function(chunk) {
+ body += chunk;
+ });
+
+ response.on('end', common.mustCall(function() {
+ assert.strictEqual(body, 'hello world');
+ server.close();
+ }));
+ }));
+
+ req.end();
+});
diff --git a/test/addons/openssl-client-cert-engine/testengine.cc b/test/addons/openssl-client-cert-engine/testengine.cc
new file mode 100644
index 0000000000..078695a056
--- /dev/null
+++ b/test/addons/openssl-client-cert-engine/testengine.cc
@@ -0,0 +1,100 @@
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <openssl/engine.h>
+#include <openssl/pem.h>
+
+#include <fstream>
+#include <iterator>
+#include <string>
+
+#ifndef ENGINE_CMD_BASE
+# error did not get engine.h
+#endif
+
+#define TEST_ENGINE_ID "testengine"
+#define TEST_ENGINE_NAME "dummy test engine"
+
+#define AGENT_KEY "test/fixtures/keys/agent1-key.pem"
+#define AGENT_CERT "test/fixtures/keys/agent1-cert.pem"
+
+namespace {
+
+int EngineInit(ENGINE* engine) {
+ return 1;
+}
+
+int EngineFinish(ENGINE* engine) {
+ return 1;
+}
+
+int EngineDestroy(ENGINE* engine) {
+ return 1;
+}
+
+std::string LoadFile(const char* filename) {
+ std::ifstream file(filename);
+ return std::string(std::istreambuf_iterator<char>(file),
+ std::istreambuf_iterator<char>());
+}
+
+
+int EngineLoadSSLClientCert(ENGINE* engine,
+ SSL* ssl,
+ STACK_OF(X509_NAME)* ca_dn,
+ X509** ppcert,
+ EVP_PKEY** ppkey,
+ STACK_OF(X509)** pother,
+ UI_METHOD* ui_method,
+ void* callback_data) {
+ if (ppcert != nullptr) {
+ std::string cert = LoadFile(AGENT_CERT);
+ if (cert.empty()) {
+ return 0;
+ }
+
+ BIO* bio = BIO_new_mem_buf(cert.data(), cert.size());
+ *ppcert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
+ BIO_vfree(bio);
+ if (*ppcert == nullptr) {
+ printf("Could not read certificate\n");
+ return 0;
+ }
+ }
+
+ if (ppkey != nullptr) {
+ std::string key = LoadFile(AGENT_KEY);
+ if (key.empty()) {
+ return 0;
+ }
+
+ BIO* bio = BIO_new_mem_buf(key.data(), key.size());
+ *ppkey = PEM_read_bio_PrivateKey(bio, nullptr, nullptr, nullptr);
+ BIO_vfree(bio);
+ if (*ppkey == nullptr) {
+ printf("Could not read private key\n");
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int bind_fn(ENGINE* engine, const char* id) {
+ ENGINE_set_id(engine, TEST_ENGINE_ID);
+ ENGINE_set_name(engine, TEST_ENGINE_NAME);
+ ENGINE_set_init_function(engine, EngineInit);
+ ENGINE_set_finish_function(engine, EngineFinish);
+ ENGINE_set_destroy_function(engine, EngineDestroy);
+ ENGINE_set_load_ssl_client_cert_function(engine, EngineLoadSSLClientCert);
+
+ return 1;
+}
+
+extern "C" {
+ IMPLEMENT_DYNAMIC_CHECK_FN();
+ IMPLEMENT_DYNAMIC_BIND_FN(bind_fn);
+}
+
+} // anonymous namespace
diff --git a/test/parallel/test-https-agent-getname.js b/test/parallel/test-https-agent-getname.js
index 0986f8472d..0cdc9568d8 100644
--- a/test/parallel/test-https-agent-getname.js
+++ b/test/parallel/test-https-agent-getname.js
@@ -12,7 +12,7 @@ const agent = new https.Agent();
// empty options
assert.strictEqual(
agent.getName({}),
- 'localhost::::::::::'
+ 'localhost:::::::::::'
);
// pass all options arguments
@@ -31,5 +31,5 @@ const options = {
assert.strictEqual(
agent.getName(options),
- '0.0.0.0:443:192.168.1.1:ca:cert:ciphers:key:pfx:false:localhost:'
+ '0.0.0.0:443:192.168.1.1:ca:cert::ciphers:key:pfx:false:localhost:'
);