diff options
author | Michael Lumish <mlumish@google.com> | 2015-08-31 10:27:07 -0700 |
---|---|---|
committer | Michael Lumish <mlumish@google.com> | 2015-08-31 10:27:07 -0700 |
commit | 519e27d84583398192d9db11627419b052672659 (patch) | |
tree | 8d9da8c7b4952746725084251dde1c5977903c86 /src/ruby/ext | |
parent | 504e379afcf049a0700b43a1db6dbd3a631dbd97 (diff) | |
parent | 643ebb6fb83f9734032e7d0291ad7df69be5ace1 (diff) |
Merge pull request #3158 from tbetbetbe/grpc-ruby-server-support-multiple-certs
Grpc ruby server add support for multiple certs
Diffstat (limited to 'src/ruby/ext')
-rw-r--r-- | src/ruby/ext/grpc/rb_server.c | 23 | ||||
-rw-r--r-- | src/ruby/ext/grpc/rb_server_credentials.c | 125 |
2 files changed, 104 insertions, 44 deletions
diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c index bd19b2fe4e..4469658869 100644 --- a/src/ruby/ext/grpc/rb_server.c +++ b/src/ruby/ext/grpc/rb_server.c @@ -49,6 +49,9 @@ static VALUE grpc_rb_cServer = Qnil; /* id_at is the constructor method of the ruby standard Time class. */ static ID id_at; +/* id_insecure_server is used to indicate that a server is insecure */ +static VALUE id_insecure_server; + /* grpc_rb_server wraps a grpc_server. It provides a peer ruby object, 'mark' to minimize copying when a server is created from ruby. */ typedef struct grpc_rb_server { @@ -314,7 +317,7 @@ static VALUE grpc_rb_server_destroy(int argc, VALUE *argv, VALUE self) { call-seq: // insecure port insecure_server = Server.new(cq, {'arg1': 'value1'}) - insecure_server.add_http2_port('mydomain:50051') + insecure_server.add_http2_port('mydomain:50051', :this_port_is_insecure) // secure port server_creds = ... @@ -322,21 +325,22 @@ static VALUE grpc_rb_server_destroy(int argc, VALUE *argv, VALUE self) { secure_server.add_http_port('mydomain:50051', server_creds) Adds a http2 port to server */ -static VALUE grpc_rb_server_add_http2_port(int argc, VALUE *argv, VALUE self) { - VALUE port = Qnil; - VALUE rb_creds = Qnil; +static VALUE grpc_rb_server_add_http2_port(VALUE self, VALUE port, + VALUE rb_creds) { grpc_rb_server *s = NULL; grpc_server_credentials *creds = NULL; int recvd_port = 0; - /* "11" == 1 mandatory args, 1 (rb_creds) is optional */ - rb_scan_args(argc, argv, "11", &port, &rb_creds); - TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s); if (s->wrapped == NULL) { rb_raise(rb_eRuntimeError, "destroyed!"); return Qnil; - } else if (rb_creds == Qnil) { + } else if (TYPE(rb_creds) == T_SYMBOL) { + if (id_insecure_server != SYM2ID(rb_creds)) { + rb_raise(rb_eTypeError, + "bad creds symbol, want :this_port_is_insecure"); + return Qnil; + } recvd_port = grpc_server_add_insecure_http2_port(s->wrapped, StringValueCStr(port)); if (recvd_port == 0) { @@ -378,8 +382,9 @@ void Init_grpc_server() { rb_define_alias(grpc_rb_cServer, "close", "destroy"); rb_define_method(grpc_rb_cServer, "add_http2_port", grpc_rb_server_add_http2_port, - -1); + 2); id_at = rb_intern("at"); + id_insecure_server = rb_intern("this_port_is_insecure"); } /* Gets the wrapped server from the ruby wrapper */ diff --git a/src/ruby/ext/grpc/rb_server_credentials.c b/src/ruby/ext/grpc/rb_server_credentials.c index 6af4c86c45..ea4d0d864e 100644 --- a/src/ruby/ext/grpc/rb_server_credentials.c +++ b/src/ruby/ext/grpc/rb_server_credentials.c @@ -135,63 +135,117 @@ static VALUE grpc_rb_server_credentials_init_copy(VALUE copy, VALUE orig) { return copy; } -/* The attribute used on the mark object to hold the pem_root_certs. */ +/* The attribute used on the mark object to preserve the pem_root_certs. */ static ID id_pem_root_certs; -/* The attribute used on the mark object to hold the pem_private_key. */ -static ID id_pem_private_key; +/* The attribute used on the mark object to preserve the pem_key_certs */ +static ID id_pem_key_certs; -/* The attribute used on the mark object to hold the pem_private_key. */ -static ID id_pem_cert_chain; +/* The key used to access the pem cert in a key_cert pair hash */ +static VALUE sym_cert_chain; + +/* The key used to access the pem private key in a key_cert pair hash */ +static VALUE sym_private_key; /* call-seq: - creds = ServerCredentials.new(pem_root_certs, pem_private_key, - pem_cert_chain) - creds = ServerCredentials.new(nil, pem_private_key, - pem_cert_chain) - - pem_root_certs: (required) PEM encoding of the server root certificate - pem_private_key: (optional) PEM encoding of the server's private key - pem_cert_chain: (optional) PEM encoding of the server's cert chain + creds = ServerCredentials.new(nil, + [{private_key: <pem_private_key1>, + {cert_chain: <pem_cert_chain1>}], + force_client_auth) + creds = ServerCredentials.new(pem_root_certs, + [{private_key: <pem_private_key1>, + {cert_chain: <pem_cert_chain1>}], + force_client_auth) + + pem_root_certs: (optional) PEM encoding of the server root certificate + pem_private_key: (required) PEM encoding of the server's private keys + force_client_auth: indicatees Initializes ServerCredential instances. */ static VALUE grpc_rb_server_credentials_init(VALUE self, VALUE pem_root_certs, - VALUE pem_private_key, - VALUE pem_cert_chain) { - /* TODO support multiple key cert pairs in the ruby API. */ + VALUE pem_key_certs, + VALUE force_client_auth) { grpc_rb_server_credentials *wrapper = NULL; grpc_server_credentials *creds = NULL; - grpc_ssl_pem_key_cert_pair key_cert_pair = {NULL, NULL}; - TypedData_Get_Struct(self, grpc_rb_server_credentials, - &grpc_rb_server_credentials_data_type, wrapper); - if (pem_cert_chain == Qnil) { - rb_raise(rb_eRuntimeError, - "could not create a server credential: nil pem_cert_chain"); + grpc_ssl_pem_key_cert_pair *key_cert_pairs = NULL; + VALUE cert = Qnil; + VALUE key = Qnil; + VALUE key_cert = Qnil; + int auth_client = 0; + int num_key_certs = 0; + int i; + + if (NIL_P(force_client_auth) || + !(force_client_auth == Qfalse || force_client_auth == Qtrue)) { + rb_raise(rb_eTypeError, + "bad force_client_auth: got:<%s> want: <True|False|nil>", + rb_obj_classname(force_client_auth)); return Qnil; - } else if (pem_private_key == Qnil) { - rb_raise(rb_eRuntimeError, - "could not create a server credential: nil pem_private_key"); + } + if (NIL_P(pem_key_certs) || TYPE(pem_key_certs) != T_ARRAY) { + rb_raise(rb_eTypeError, "bad pem_key_certs: got:<%s> want: <Array>", + rb_obj_classname(pem_key_certs)); + return Qnil; + } + num_key_certs = RARRAY_LEN(pem_key_certs); + if (num_key_certs == 0) { + rb_raise(rb_eTypeError, "bad pem_key_certs: it had no elements"); return Qnil; } - key_cert_pair.private_key = RSTRING_PTR(pem_private_key); - key_cert_pair.cert_chain = RSTRING_PTR(pem_cert_chain); - /* TODO Add a force_client_auth parameter and pass it here. */ + for (i = 0; i < num_key_certs; i++) { + key_cert = rb_ary_entry(pem_key_certs, i); + if (key_cert == Qnil) { + rb_raise(rb_eTypeError, + "could not create a server credential: nil key_cert"); + return Qnil; + } else if (TYPE(key_cert) != T_HASH) { + rb_raise(rb_eTypeError, + "could not create a server credential: want <Hash>, got <%s>", + rb_obj_classname(key_cert)); + return Qnil; + } else if (rb_hash_aref(key_cert, sym_private_key) == Qnil) { + rb_raise(rb_eTypeError, + "could not create a server credential: want nil private key"); + return Qnil; + } else if (rb_hash_aref(key_cert, sym_cert_chain) == Qnil) { + rb_raise(rb_eTypeError, + "could not create a server credential: want nil cert chain"); + return Qnil; + } + } + + auth_client = TYPE(force_client_auth) == T_TRUE; + key_cert_pairs = ALLOC_N(grpc_ssl_pem_key_cert_pair, num_key_certs); + for (i = 0; i < num_key_certs; i++) { + key_cert = rb_ary_entry(pem_key_certs, i); + key = rb_hash_aref(key_cert, sym_private_key); + cert = rb_hash_aref(key_cert, sym_cert_chain); + key_cert_pairs[i].private_key = RSTRING_PTR(key); + key_cert_pairs[i].cert_chain = RSTRING_PTR(cert); + } + + TypedData_Get_Struct(self, grpc_rb_server_credentials, + &grpc_rb_server_credentials_data_type, wrapper); + if (pem_root_certs == Qnil) { - creds = - grpc_ssl_server_credentials_create(NULL, &key_cert_pair, 1, 0, NULL); + creds = grpc_ssl_server_credentials_create(NULL, key_cert_pairs, + num_key_certs, + auth_client, NULL); } else { creds = grpc_ssl_server_credentials_create(RSTRING_PTR(pem_root_certs), - &key_cert_pair, 1, 0, NULL); + key_cert_pairs, num_key_certs, + auth_client, NULL); } + xfree(key_cert_pairs); if (creds == NULL) { rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why"); + return Qnil; } wrapper->wrapped = creds; /* Add the input objects as hidden fields to preserve them. */ - rb_ivar_set(self, id_pem_cert_chain, pem_cert_chain); - rb_ivar_set(self, id_pem_private_key, pem_private_key); + rb_ivar_set(self, id_pem_key_certs, pem_key_certs); rb_ivar_set(self, id_pem_root_certs, pem_root_certs); return self; @@ -211,9 +265,10 @@ void Init_grpc_server_credentials() { rb_define_method(grpc_rb_cServerCredentials, "initialize_copy", grpc_rb_server_credentials_init_copy, 1); - id_pem_cert_chain = rb_intern("__pem_cert_chain"); - id_pem_private_key = rb_intern("__pem_private_key"); + id_pem_key_certs = rb_intern("__pem_key_certs"); id_pem_root_certs = rb_intern("__pem_root_certs"); + sym_private_key = ID2SYM(rb_intern("private_key")); + sym_cert_chain = ID2SYM(rb_intern("cert_chain")); } /* Gets the wrapped grpc_server_credentials from the ruby wrapper */ |