diff --git a/src/python/src/grpc/_adapter/_c.c b/src/python/src/grpc/_adapter/_c.c index 55b9d0512c9..f096a55b618 100644 --- a/src/python/src/grpc/_adapter/_c.c +++ b/src/python/src/grpc/_adapter/_c.c @@ -38,6 +38,7 @@ #include "grpc/_adapter/_channel.h" #include "grpc/_adapter/_call.h" #include "grpc/_adapter/_server.h" +#include "grpc/_adapter/_client_credentials.h" #include "grpc/_adapter/_server_credentials.h" static PyObject *init(PyObject *self) { @@ -76,6 +77,9 @@ PyMODINIT_FUNC init_c(void) { if (pygrpc_add_server(module) == -1) { return; } + if (pygrpc_add_client_credentials(module) == -1) { + return; + } if (pygrpc_add_server_credentials(module) == -1) { return; } diff --git a/src/python/src/grpc/_adapter/_c_test.py b/src/python/src/grpc/_adapter/_c_test.py index d421692ec9c..44aff44ffa0 100644 --- a/src/python/src/grpc/_adapter/_c_test.py +++ b/src/python/src/grpc/_adapter/_c_test.py @@ -136,6 +136,29 @@ class _CTest(unittest.TestCase): _c.shut_down() + def test_client_credentials(self): + root_certificates = b'Trust starts here. Really.' + private_key = b'This is a really bad private key, yo.' + certificate_chain = b'Trust me! Do I not look trustworty?' + + _c.init() + + client_credentials = _c.ClientCredentials( + None, None, None) + self.assertIsNotNone(client_credentials) + client_credentials = _c.ClientCredentials( + root_certificates, None, None) + self.assertIsNotNone(client_credentials) + client_credentials = _c.ClientCredentials( + None, private_key, certificate_chain) + self.assertIsNotNone(client_credentials) + client_credentials = _c.ClientCredentials( + root_certificates, private_key, certificate_chain) + self.assertIsNotNone(client_credentials) + del client_credentials + + _c.shut_down() + def test_server_credentials(self): root_certificates = b'Trust starts here. Really.' first_private_key = b'This is a really bad private key, yo.' diff --git a/src/python/src/grpc/_adapter/_client_credentials.c b/src/python/src/grpc/_adapter/_client_credentials.c new file mode 100644 index 00000000000..b970c866ef7 --- /dev/null +++ b/src/python/src/grpc/_adapter/_client_credentials.c @@ -0,0 +1,120 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "grpc/_adapter/_client_credentials.h" + +#include +#include +#include + +static int pygrpc_client_credentials_init(ClientCredentials *self, + PyObject *args, PyObject *kwds) { + char *root_certificates; + grpc_ssl_pem_key_cert_pair key_certificate_pair; + static char *kwlist[] = {"root_certificates", "private_key", + "certificate_chain", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "zzz:ClientCredentials", kwlist, + &root_certificates, + &key_certificate_pair.private_key, + &key_certificate_pair.cert_chain)) { + return -1; + } + + if (key_certificate_pair.private_key != NULL && key_certificate_pair.cert_chain != NULL) { + self->c_client_credentials = + grpc_ssl_credentials_create(root_certificates, &key_certificate_pair); + } else { + self->c_client_credentials = + grpc_ssl_credentials_create(root_certificates, NULL); + } +} + +static void pygrpc_client_credentials_dealloc(ClientCredentials *self) { + if (self->c_client_credentials != NULL) { + grpc_credentials_release(self->c_client_credentials); + } + self->ob_type->tp_free((PyObject *)self); +} + +PyTypeObject pygrpc_ClientCredentialsType = { + PyVarObject_HEAD_INIT(NULL, 0) + "_grpc.ClientCredencials", /*tp_name*/ + sizeof(ClientCredentials), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)pygrpc_client_credentials_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "Wrapping of grpc_credentials.", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)pygrpc_client_credentials_init, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + +int pygrpc_add_client_credentials(PyObject *module) { + if (PyType_Ready(&pygrpc_ClientCredentialsType) < 0) { + return -1; + } + if (PyModule_AddObject(module, "ClientCredentials", + (PyObject *)&pygrpc_ClientCredentialsType) == -1) { + return -1; + } + return 0; +} diff --git a/src/python/src/grpc/_adapter/_client_credentials.h b/src/python/src/grpc/_adapter/_client_credentials.h new file mode 100644 index 00000000000..664dc80d751 --- /dev/null +++ b/src/python/src/grpc/_adapter/_client_credentials.h @@ -0,0 +1,48 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _ADAPTER__CLIENT_CREDENTIALS_H_ +#define _ADAPTER__CLIENT_CREDENTIALS_H_ + +#include +#include + +typedef struct { + PyObject_HEAD grpc_credentials *c_client_credentials; +} ClientCredentials; + +PyTypeObject pygrpc_ClientCredentialsType; + +int pygrpc_add_client_credentials(PyObject *module); + +#endif /* _ADAPTER__CLIENT_CREDENTIALS_H_ */ diff --git a/src/python/src/grpc/_adapter/_low.py b/src/python/src/grpc/_adapter/_low.py index 2ef2eb879c1..a24baaeb3e7 100644 --- a/src/python/src/grpc/_adapter/_low.py +++ b/src/python/src/grpc/_adapter/_low.py @@ -52,5 +52,6 @@ Call = _c.Call Channel = _c.Channel CompletionQueue = _c.CompletionQueue Server = _c.Server +ClientCredentials = _c.ClientCredentials ServerCredentials = _c.ServerCredentials # pylint: enable=invalid-name diff --git a/src/python/src/setup.py b/src/python/src/setup.py index e3f13fa5c8f..23f128636e4 100644 --- a/src/python/src/setup.py +++ b/src/python/src/setup.py @@ -38,6 +38,7 @@ _EXTENSION_SOURCES = ( 'grpc/_adapter/_completion_queue.c', 'grpc/_adapter/_error.c', 'grpc/_adapter/_server.c', + 'grpc/_adapter/_client_credentials.c', 'grpc/_adapter/_server_credentials.c', )