blob: e6c55e263cbc4996d3aca41b266aa288291d2fbd [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 }
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700148 int force_client_auth = 0;
murgatroid992b097832015-09-17 13:56:25 -0700149 if (info[2]->IsBoolean()) {
150 force_client_auth = (int)Nan::To<bool>(info[2]).FromJust();
151 } else if (!(info[2]->IsUndefined() || info[2]->IsNull())) {
152 return Nan::ThrowTypeError(
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700153 "createSsl's third argument must be a boolean if provided");
murgatroid99e5061512015-01-12 18:14:35 -0800154 }
murgatroid992b097832015-09-17 13:56:25 -0700155 Local<Array> pair_list = Local<Array>::Cast(info[1]);
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700156 uint32_t key_cert_pair_count = pair_list->Length();
157 grpc_ssl_pem_key_cert_pair *key_cert_pairs = new grpc_ssl_pem_key_cert_pair[
158 key_cert_pair_count];
159
murgatroid992b097832015-09-17 13:56:25 -0700160 Local<String> key_key = Nan::New("private_key").ToLocalChecked();
161 Local<String> cert_key = Nan::New("cert_chain").ToLocalChecked();
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700162
163 for(uint32_t i = 0; i < key_cert_pair_count; i++) {
murgatroid992b097832015-09-17 13:56:25 -0700164 Local<Value> pair_val = Nan::Get(pair_list, i).ToLocalChecked();
165 if (!pair_val->IsObject()) {
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700166 delete key_cert_pairs;
murgatroid992b097832015-09-17 13:56:25 -0700167 return Nan::ThrowTypeError("Key/cert pairs must be objects");
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700168 }
murgatroid992b097832015-09-17 13:56:25 -0700169 Local<Object> pair_obj = Nan::To<Object>(pair_val).ToLocalChecked();
170 MaybeLocal<Value> maybe_key = Nan::Get(pair_obj, key_key);
171 if (maybe_key.IsEmpty()) {
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700172 delete key_cert_pairs;
murgatroid992b097832015-09-17 13:56:25 -0700173 return Nan::ThrowTypeError(
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700174 "Key/cert pairs must have a private_key and a cert_chain");
175 }
murgatroid992b097832015-09-17 13:56:25 -0700176 MaybeLocal<Value> maybe_cert = Nan::Get(pair_obj, cert_key);
177 if (maybe_cert.IsEmpty()) {
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700178 delete key_cert_pairs;
murgatroid992b097832015-09-17 13:56:25 -0700179 return Nan::ThrowTypeError(
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700180 "Key/cert pairs must have a private_key and a cert_chain");
181 }
murgatroid992b097832015-09-17 13:56:25 -0700182 if (!::node::Buffer::HasInstance(maybe_key.ToLocalChecked())) {
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700183 delete key_cert_pairs;
murgatroid992b097832015-09-17 13:56:25 -0700184 return Nan::ThrowTypeError("private_key must be a Buffer");
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700185 }
murgatroid992b097832015-09-17 13:56:25 -0700186 if (!::node::Buffer::HasInstance(maybe_cert.ToLocalChecked())) {
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700187 delete key_cert_pairs;
murgatroid992b097832015-09-17 13:56:25 -0700188 return Nan::ThrowTypeError("cert_chain must be a Buffer");
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700189 }
190 key_cert_pairs[i].private_key = ::node::Buffer::Data(
murgatroid992b097832015-09-17 13:56:25 -0700191 maybe_key.ToLocalChecked());
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700192 key_cert_pairs[i].cert_chain = ::node::Buffer::Data(
murgatroid992b097832015-09-17 13:56:25 -0700193 maybe_cert.ToLocalChecked());
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700194 }
Julien Boeufc5b570f2015-08-25 17:47:55 -0700195 grpc_server_credentials *creds = grpc_ssl_server_credentials_create(
196 root_certs, key_cert_pairs, key_cert_pair_count, force_client_auth, NULL);
murgatroid99c2fdfcf2015-08-19 14:57:19 -0700197 delete key_cert_pairs;
murgatroid991a7dcac2015-07-27 16:13:28 -0700198 if (creds == NULL) {
murgatroid992b097832015-09-17 13:56:25 -0700199 info.GetReturnValue().SetNull();
200 } else {
201 info.GetReturnValue().Set(WrapStruct(creds));
murgatroid991a7dcac2015-07-27 16:13:28 -0700202 }
murgatroid991a7dcac2015-07-27 16:13:28 -0700203}
204
205NAN_METHOD(ServerCredentials::CreateInsecure) {
murgatroid992b097832015-09-17 13:56:25 -0700206 info.GetReturnValue().Set(WrapStruct(NULL));
murgatroid99e5061512015-01-12 18:14:35 -0800207}
208
murgatroid99e5061512015-01-12 18:14:35 -0800209} // namespace node
Craig Tiller190d3602015-02-18 09:23:38 -0800210} // namespace grpc