blob: 0ff58bb20924101d3378530a23470752f9eab1e0 [file] [log] [blame]
murgatroid99749666e2015-01-12 18:25:58 -08001/*
2 *
Craig Tiller06059952015-02-18 08:34:56 -08003 * Copyright 2015, Google Inc.
murgatroid99749666e2015-01-12 18:25:58 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
murgatroid99e5061512015-01-12 18:14:35 -080034#include <node.h>
35
36#include "grpc/grpc.h"
37#include "grpc/grpc_security.h"
38#include "grpc/support/log.h"
39#include "server_credentials.h"
40
41namespace grpc {
42namespace node {
43
murgatroid992b097832015-09-17 13:56:25 -070044using Nan::Callback;
45using Nan::EscapableHandleScope;
46using Nan::HandleScope;
47using Nan::Maybe;
48using Nan::MaybeLocal;
49using Nan::ObjectWrap;
50using Nan::Persistent;
51using Nan::Utf8String;
52
murgatroid99c2fdfcf2015-08-19 14:57:19 -070053using v8::Array;
murgatroid99e5061512015-01-12 18:14:35 -080054using v8::Exception;
55using v8::External;
56using v8::Function;
57using v8::FunctionTemplate;
murgatroid99e5061512015-01-12 18:14:35 -080058using v8::Integer;
59using v8::Local;
60using v8::Object;
61using v8::ObjectTemplate;
murgatroid99c2fdfcf2015-08-19 14:57:19 -070062using v8::String;
murgatroid99e5061512015-01-12 18:14:35 -080063using v8::Value;
64
murgatroid992b097832015-09-17 13:56:25 -070065Nan::Callback *ServerCredentials::constructor;
murgatroid99e5061512015-01-12 18:14:35 -080066Persistent<FunctionTemplate> ServerCredentials::fun_tpl;
67
68ServerCredentials::ServerCredentials(grpc_server_credentials *credentials)
Craig Tillere8e304e2015-01-13 14:41:29 -080069 : wrapped_credentials(credentials) {}
murgatroid99e5061512015-01-12 18:14:35 -080070
71ServerCredentials::~ServerCredentials() {
murgatroid99e5061512015-01-12 18:14:35 -080072 grpc_server_credentials_release(wrapped_credentials);
73}
74
murgatroid992b097832015-09-17 13:56:25 -070075void ServerCredentials::Init(Local<Object> exports) {
76 Nan::HandleScope scope;
77 Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
78 tpl->SetClassName(Nan::New("ServerCredentials").ToLocalChecked());
murgatroid99e5061512015-01-12 18:14:35 -080079 tpl->InstanceTemplate()->SetInternalFieldCount(1);
murgatroid992b097832015-09-17 13:56:25 -070080 Local<Function> ctr = tpl->GetFunction();
81 Nan::Set(ctr, Nan::New("createSsl").ToLocalChecked(),
82 Nan::GetFunction(
83 Nan::New<FunctionTemplate>(CreateSsl)).ToLocalChecked());
84 Nan::Set(ctr, Nan::New("createInsecure").ToLocalChecked(),
85 Nan::GetFunction(
86 Nan::New<FunctionTemplate>(CreateInsecure)).ToLocalChecked());
87 fun_tpl.Reset(tpl);
88 constructor = new Nan::Callback(ctr);
89 Nan::Set(exports, Nan::New("ServerCredentials").ToLocalChecked(), ctr);
murgatroid99e5061512015-01-12 18:14:35 -080090}
91
murgatroid992b097832015-09-17 13:56:25 -070092bool ServerCredentials::HasInstance(Local<Value> val) {
93 Nan::HandleScope scope;
94 return Nan::New(fun_tpl)->HasInstance(val);
murgatroid99e5061512015-01-12 18:14:35 -080095}
96
murgatroid992b097832015-09-17 13:56:25 -070097Local<Value> ServerCredentials::WrapStruct(
murgatroid99e5061512015-01-12 18:14:35 -080098 grpc_server_credentials *credentials) {
murgatroid992b097832015-09-17 13:56:25 -070099 Nan::EscapableHandleScope scope;
murgatroid99e5061512015-01-12 18:14:35 -0800100 const int argc = 1;
murgatroid992b097832015-09-17 13:56:25 -0700101 Local<Value> argv[argc] = {
102 Nan::New<External>(reinterpret_cast<void *>(credentials))};
103 MaybeLocal<Object> maybe_instance = Nan::NewInstance(
104 constructor->GetFunction(), argc, argv);
105 if (maybe_instance.IsEmpty()) {
106 return scope.Escape(Nan::Null());
107 } else {
108 return scope.Escape(maybe_instance.ToLocalChecked());
109 }
murgatroid99e5061512015-01-12 18:14:35 -0800110}
111
112grpc_server_credentials *ServerCredentials::GetWrappedServerCredentials() {
113 return wrapped_credentials;
114}
115
116NAN_METHOD(ServerCredentials::New) {
murgatroid992b097832015-09-17 13:56:25 -0700117 if (info.IsConstructCall()) {
118 if (!info[0]->IsExternal()) {
119 return Nan::ThrowTypeError(
murgatroid9975a2bba2015-10-12 16:12:04 -0700120 "ServerCredentials can only be created with the provided functions");
murgatroid99e5061512015-01-12 18:14:35 -0800121 }
murgatroid992b097832015-09-17 13:56:25 -0700122 Local<External> ext = info[0].As<External>();
murgatroid99e5061512015-01-12 18:14:35 -0800123 grpc_server_credentials *creds_value =
murgatroid99f28066b2015-03-04 14:42:31 -0800124 reinterpret_cast<grpc_server_credentials *>(ext->Value());
murgatroid99e5061512015-01-12 18:14:35 -0800125 ServerCredentials *credentials = new ServerCredentials(creds_value);
murgatroid992b097832015-09-17 13:56:25 -0700126 credentials->Wrap(info.This());
127 info.GetReturnValue().Set(info.This());
murgatroid99e5061512015-01-12 18:14:35 -0800128 } else {
murgatroid9975a2bba2015-10-12 16:12:04 -0700129 // This should never be called directly
130 return Nan::ThrowTypeError(
131 "ServerCredentials can only be created with the provided functions");
murgatroid99e5061512015-01-12 18:14:35 -0800132 }
133}
134
135NAN_METHOD(ServerCredentials::CreateSsl) {
murgatroid992b097832015-09-17 13:56:25 -0700136 Nan::HandleScope scope;
murgatroid99e5061512015-01-12 18:14:35 -0800137 char *root_certs = NULL;
murgatroid992b097832015-09-17 13:56:25 -0700138 if (::node::Buffer::HasInstance(info[0])) {
139 root_certs = ::node::Buffer::Data(info[0]);
140 } else if (!(info[0]->IsNull() || info[0]->IsUndefined())) {
141 return Nan::ThrowTypeError(
murgatroid99e5061512015-01-12 18:14:35 -0800142 "createSSl's first argument must be a Buffer if provided");
143 }
murgatroid992b097832015-09-17 13:56:25 -0700144 if (!info[1]->IsArray()) {
145 return Nan::ThrowTypeError(
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700146 "createSsl's second argument must be a list of objects");
murgatroid99e5061512015-01-12 18:14:35 -0800147 }
Deepak Lukosedba4c5f2016-03-25 12:54:25 -0700148
murgatroid998658b172016-04-27 14:54:40 -0700149 // Default to not requesting the client certificate
150 grpc_ssl_client_certificate_request_type client_certificate_request =
151 GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE;
murgatroid992b097832015-09-17 13:56:25 -0700152 if (info[2]->IsBoolean()) {
Deepak Lukosedba4c5f2016-03-25 12:54:25 -0700153 client_certificate_request =
154 Nan::To<bool>(info[2]).FromJust()
155 ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
156 : GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE;
murgatroid992b097832015-09-17 13:56:25 -0700157 } else if (!(info[2]->IsUndefined() || info[2]->IsNull())) {
158 return Nan::ThrowTypeError(
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700159 "createSsl's third argument must be a boolean if provided");
murgatroid99e5061512015-01-12 18:14:35 -0800160 }
murgatroid992b097832015-09-17 13:56:25 -0700161 Local<Array> pair_list = Local<Array>::Cast(info[1]);
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700162 uint32_t key_cert_pair_count = pair_list->Length();
163 grpc_ssl_pem_key_cert_pair *key_cert_pairs = new grpc_ssl_pem_key_cert_pair[
164 key_cert_pair_count];
165
murgatroid992b097832015-09-17 13:56:25 -0700166 Local<String> key_key = Nan::New("private_key").ToLocalChecked();
167 Local<String> cert_key = Nan::New("cert_chain").ToLocalChecked();
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700168
169 for(uint32_t i = 0; i < key_cert_pair_count; i++) {
murgatroid992b097832015-09-17 13:56:25 -0700170 Local<Value> pair_val = Nan::Get(pair_list, i).ToLocalChecked();
171 if (!pair_val->IsObject()) {
murgatroid998fecf282016-09-20 09:55:33 -0700172 delete[] key_cert_pairs;
murgatroid992b097832015-09-17 13:56:25 -0700173 return Nan::ThrowTypeError("Key/cert pairs must be objects");
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700174 }
murgatroid992b097832015-09-17 13:56:25 -0700175 Local<Object> pair_obj = Nan::To<Object>(pair_val).ToLocalChecked();
murgatroid99a9172d22015-12-09 16:12:37 -0800176 Local<Value> maybe_key = Nan::Get(pair_obj, key_key).ToLocalChecked();
177 Local<Value> maybe_cert = Nan::Get(pair_obj, cert_key).ToLocalChecked();
178 if (!::node::Buffer::HasInstance(maybe_key)) {
murgatroid998fecf282016-09-20 09:55:33 -0700179 delete[] key_cert_pairs;
murgatroid992b097832015-09-17 13:56:25 -0700180 return Nan::ThrowTypeError("private_key must be a Buffer");
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700181 }
murgatroid99a9172d22015-12-09 16:12:37 -0800182 if (!::node::Buffer::HasInstance(maybe_cert)) {
murgatroid998fecf282016-09-20 09:55:33 -0700183 delete[] key_cert_pairs;
murgatroid992b097832015-09-17 13:56:25 -0700184 return Nan::ThrowTypeError("cert_chain must be a Buffer");
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700185 }
murgatroid99a9172d22015-12-09 16:12:37 -0800186 key_cert_pairs[i].private_key = ::node::Buffer::Data(maybe_key);
187 key_cert_pairs[i].cert_chain = ::node::Buffer::Data(maybe_cert);
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700188 }
Deepak Lukosedba4c5f2016-03-25 12:54:25 -0700189 grpc_server_credentials *creds = grpc_ssl_server_credentials_create_ex(
190 root_certs, key_cert_pairs, key_cert_pair_count,
191 client_certificate_request, NULL);
murgatroid998fecf282016-09-20 09:55:33 -0700192 delete[] key_cert_pairs;
murgatroid991a7dcac2015-07-27 16:13:28 -0700193 if (creds == NULL) {
murgatroid992b097832015-09-17 13:56:25 -0700194 info.GetReturnValue().SetNull();
195 } else {
196 info.GetReturnValue().Set(WrapStruct(creds));
murgatroid991a7dcac2015-07-27 16:13:28 -0700197 }
murgatroid991a7dcac2015-07-27 16:13:28 -0700198}
199
200NAN_METHOD(ServerCredentials::CreateInsecure) {
murgatroid992b097832015-09-17 13:56:25 -0700201 info.GetReturnValue().Set(WrapStruct(NULL));
murgatroid99e5061512015-01-12 18:14:35 -0800202}
203
murgatroid99e5061512015-01-12 18:14:35 -0800204} // namespace node
Craig Tiller190d3602015-02-18 09:23:38 -0800205} // namespace grpc