From 5bb18030d20b69ec617c4ffc51c5373681168dde Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Wed, 19 Aug 2015 14:57:19 -0700 Subject: [PATCH 1/2] Modified server SSL certs to allow multiple pairs and force_client_auth flag --- ext/server_credentials.cc | 63 ++++++++++++++++++++++++++++++++------- interop/interop_server.js | 4 +-- test/server_test.js | 4 ++- 3 files changed, 58 insertions(+), 13 deletions(-) diff --git a/ext/server_credentials.cc b/ext/server_credentials.cc index 1b8e7b43..6e17197e 100644 --- a/ext/server_credentials.cc +++ b/ext/server_credentials.cc @@ -41,6 +41,7 @@ namespace grpc { namespace node { +using v8::Array; using v8::Exception; using v8::External; using v8::Function; @@ -52,6 +53,7 @@ using v8::Local; using v8::Object; using v8::ObjectTemplate; using v8::Persistent; +using v8::String; using v8::Value; NanCallback *ServerCredentials::constructor; @@ -122,25 +124,66 @@ NAN_METHOD(ServerCredentials::CreateSsl) { // TODO: have the node API support multiple key/cert pairs. NanScope(); char *root_certs = NULL; - grpc_ssl_pem_key_cert_pair key_cert_pair; if (::node::Buffer::HasInstance(args[0])) { root_certs = ::node::Buffer::Data(args[0]); } else if (!(args[0]->IsNull() || args[0]->IsUndefined())) { return NanThrowTypeError( "createSSl's first argument must be a Buffer if provided"); } - if (!::node::Buffer::HasInstance(args[1])) { - return NanThrowTypeError("createSsl's second argument must be a Buffer"); + if (!args[1]->IsArray()) { + return NanThrowTypeError( + "createSsl's second argument must be a list of objects"); } - key_cert_pair.private_key = ::node::Buffer::Data(args[1]); - if (!::node::Buffer::HasInstance(args[2])) { - return NanThrowTypeError("createSsl's third argument must be a Buffer"); + int force_client_auth = 0; + if (args[2]->IsBoolean()) { + force_client_auth = (int)args[2]->BooleanValue(); + } else if (!(args[2]->IsUndefined() || args[2]->IsNull())) { + return NanThrowTypeError( + "createSsl's third argument must be a boolean if provided"); + } + Handle pair_list = Local::Cast(args[1]); + uint32_t key_cert_pair_count = pair_list->Length(); + grpc_ssl_pem_key_cert_pair *key_cert_pairs = new grpc_ssl_pem_key_cert_pair[ + key_cert_pair_count]; + + Handle key_key = NanNew("private_key"); + Handle cert_key = NanNew("cert_chain"); + + for(uint32_t i = 0; i < key_cert_pair_count; i++) { + if (!pair_list->Get(i)->IsObject()) { + delete key_cert_pairs; + return NanThrowTypeError("Key/cert pairs must be objects"); + } + Handle pair_obj = pair_list->Get(i)->ToObject(); + if (!pair_obj->HasOwnProperty(key_key)) { + delete key_cert_pairs; + return NanThrowTypeError( + "Key/cert pairs must have a private_key and a cert_chain"); + } + if (!pair_obj->HasOwnProperty(cert_key)) { + delete key_cert_pairs; + return NanThrowTypeError( + "Key/cert pairs must have a private_key and a cert_chain"); + } + if (!::node::Buffer::HasInstance(pair_obj->Get(key_key))) { + delete key_cert_pairs; + return NanThrowTypeError("private_key must be a Buffer"); + } + if (!::node::Buffer::HasInstance(pair_obj->Get(cert_key))) { + delete key_cert_pairs; + return NanThrowTypeError("cert_chain must be a Buffer"); + } + key_cert_pairs[i].private_key = ::node::Buffer::Data( + pair_obj->Get(key_key)); + key_cert_pairs[i].cert_chain = ::node::Buffer::Data( + pair_obj->Get(cert_key)); } - key_cert_pair.cert_chain = ::node::Buffer::Data(args[2]); - // TODO Add a force_client_auth parameter and pass it as the last parameter - // here. grpc_server_credentials *creds = - grpc_ssl_server_credentials_create(root_certs, &key_cert_pair, 1, 0); + grpc_ssl_server_credentials_create(root_certs, + key_cert_pairs, + key_cert_pair_count, + force_client_auth); + delete key_cert_pairs; if (creds == NULL) { NanReturnNull(); } diff --git a/interop/interop_server.js b/interop/interop_server.js index 1242a0f9..09d594d1 100644 --- a/interop/interop_server.js +++ b/interop/interop_server.js @@ -169,8 +169,8 @@ function getServer(port, tls) { var key_data = fs.readFileSync(key_path); var pem_data = fs.readFileSync(pem_path); server_creds = grpc.ServerCredentials.createSsl(null, - key_data, - pem_data); + {private_key: key_data, + cert_chain: pem_data}); } else { server_creds = grpc.ServerCredentials.createInsecure(); } diff --git a/test/server_test.js b/test/server_test.js index 20c9a07f..3d2f5504 100644 --- a/test/server_test.js +++ b/test/server_test.js @@ -70,7 +70,9 @@ describe('server', function() { var pem_path = path.join(__dirname, '../test/data/server1.pem'); var key_data = fs.readFileSync(key_path); var pem_data = fs.readFileSync(pem_path); - var creds = grpc.ServerCredentials.createSsl(null, key_data, pem_data); + var creds = grpc.ServerCredentials.createSsl(null, + {private_key: key_data, + cert_chain: pem_data}); assert.doesNotThrow(function() { port = server.addHttp2Port('0.0.0.0:0', creds); }); From 9a57cad9ff1810a1389777854999cffe49bda3c2 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Wed, 19 Aug 2015 15:02:15 -0700 Subject: [PATCH 2/2] Fixed tests --- interop/interop_server.js | 4 ++-- test/server_test.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interop/interop_server.js b/interop/interop_server.js index 09d594d1..99155e99 100644 --- a/interop/interop_server.js +++ b/interop/interop_server.js @@ -169,8 +169,8 @@ function getServer(port, tls) { var key_data = fs.readFileSync(key_path); var pem_data = fs.readFileSync(pem_path); server_creds = grpc.ServerCredentials.createSsl(null, - {private_key: key_data, - cert_chain: pem_data}); + [{private_key: key_data, + cert_chain: pem_data}]); } else { server_creds = grpc.ServerCredentials.createInsecure(); } diff --git a/test/server_test.js b/test/server_test.js index 3d2f5504..78bac8da 100644 --- a/test/server_test.js +++ b/test/server_test.js @@ -71,8 +71,8 @@ describe('server', function() { var key_data = fs.readFileSync(key_path); var pem_data = fs.readFileSync(pem_path); var creds = grpc.ServerCredentials.createSsl(null, - {private_key: key_data, - cert_chain: pem_data}); + [{private_key: key_data, + cert_chain: pem_data}]); assert.doesNotThrow(function() { port = server.addHttp2Port('0.0.0.0:0', creds); });