diff options
-rw-r--r-- | src/python/setup.py | 1 | ||||
-rw-r--r-- | src/python/src/_adapter/_c.c | 4 | ||||
-rw-r--r-- | src/python/src/_adapter/_c_test.py | 26 | ||||
-rw-r--r-- | src/python/src/_adapter/_server_credentials.c | 157 | ||||
-rw-r--r-- | src/python/src/_adapter/_server_credentials.h | 48 |
5 files changed, 236 insertions, 0 deletions
diff --git a/src/python/setup.py b/src/python/setup.py index 58dc3b17df..5e566bad4f 100644 --- a/src/python/setup.py +++ b/src/python/setup.py @@ -38,6 +38,7 @@ _EXTENSION_SOURCES = ( 'src/_adapter/_completion_queue.c', 'src/_adapter/_error.c', 'src/_adapter/_server.c', + 'src/_adapter/_server_credentials.c', ) _EXTENSION_INCLUDE_DIRECTORIES = ( diff --git a/src/python/src/_adapter/_c.c b/src/python/src/_adapter/_c.c index d1f7fbb0d5..6fb7fa29fa 100644 --- a/src/python/src/_adapter/_c.c +++ b/src/python/src/_adapter/_c.c @@ -38,6 +38,7 @@ #include "_adapter/_channel.h" #include "_adapter/_call.h" #include "_adapter/_server.h" +#include "_adapter/_server_credentials.h" static PyObject *init(PyObject *self, PyObject *args) { grpc_init(); @@ -74,4 +75,7 @@ PyMODINIT_FUNC init_c(void) { if (pygrpc_add_server(module) == -1) { return; } + if (pygrpc_add_server_credentials(module) == -1) { + return; + } } diff --git a/src/python/src/_adapter/_c_test.py b/src/python/src/_adapter/_c_test.py index bc0a622cc4..19c91ffe01 100644 --- a/src/python/src/_adapter/_c_test.py +++ b/src/python/src/_adapter/_c_test.py @@ -136,6 +136,32 @@ class _CTest(unittest.TestCase): _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.' + first_certificate_chain = b'Trust me! Do I not look trustworty?' + second_private_key = b'This is another bad private key, yo.' + second_certificate_chain = b'Look into my eyes; you can totes trust me.' + + _c.init() + + server_credentials = _c.ServerCredentials( + None, ((first_private_key, first_certificate_chain),)) + del server_credentials + server_credentials = _c.ServerCredentials( + root_certificates, ((first_private_key, first_certificate_chain),)) + del server_credentials + server_credentials = _c.ServerCredentials( + root_certificates, + ((first_private_key, first_certificate_chain), + (second_private_key, second_certificate_chain),)) + del server_credentials + with self.assertRaises(TypeError): + _c.ServerCredentials( + root_certificates, first_private_key, second_certificate_chain) + + _c.shut_down() + if __name__ == '__main__': unittest.main() diff --git a/src/python/src/_adapter/_server_credentials.c b/src/python/src/_adapter/_server_credentials.c new file mode 100644 index 0000000000..390266ae89 --- /dev/null +++ b/src/python/src/_adapter/_server_credentials.c @@ -0,0 +1,157 @@ +/* + * + * 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 "_adapter/_server_credentials.h" + +#include <Python.h> +#include <grpc/grpc_security.h> +#include <grpc/support/alloc.h> + +static int pygrpc_server_credentials_init(ServerCredentials *self, + PyObject *args, PyObject *kwds) { + char *root_certificates; + PyObject *pair_sequence; + Py_ssize_t pair_count; + grpc_ssl_pem_key_cert_pair *pairs; + int error; + PyObject *iterator; + int i; + PyObject *pair; + + if (!(PyArg_ParseTuple(args, "zO", &root_certificates, &pair_sequence))) { + self->c_server_credentials = NULL; + return -1; + } + + pair_count = PySequence_Length(pair_sequence); + if (pair_count == -1) { + self->c_server_credentials = NULL; + return -1; + } + + iterator = PyObject_GetIter(pair_sequence); + if (iterator == NULL) { + self->c_server_credentials = NULL; + return -1; + } + pairs = gpr_malloc(pair_count * sizeof(grpc_ssl_pem_key_cert_pair)); + error = 0; + for (i = 0; i < pair_count; i++) { + pair = PyIter_Next(iterator); + if (pair == NULL) { + error = 1; + break; + } + if (!(PyArg_ParseTuple(pair, "ss", &pairs[i].private_key, + &pairs[i].cert_chain))) { + error = 1; + Py_DECREF(pair); + break; + } + Py_DECREF(pair); + } + Py_DECREF(iterator); + + if (error) { + self->c_server_credentials = NULL; + gpr_free(pairs); + return -1; + } else { + self->c_server_credentials = grpc_ssl_server_credentials_create( + root_certificates, pairs, pair_count); + gpr_free(pairs); + return 0; + } +} + +static void pygrpc_server_credentials_dealloc(ServerCredentials *self) { + if (self->c_server_credentials != NULL) { + grpc_server_credentials_release(self->c_server_credentials); + } + self->ob_type->tp_free((PyObject *)self); +} + +PyTypeObject pygrpc_ServerCredentialsType = { + PyObject_HEAD_INIT(NULL)0, /*ob_size*/ + "_grpc.ServerCredencials", /*tp_name*/ + sizeof(ServerCredentials), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)pygrpc_server_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_server_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_server_credentials_init, /* tp_init */ +}; + +int pygrpc_add_server_credentials(PyObject *module) { + pygrpc_ServerCredentialsType.tp_new = PyType_GenericNew; + if (PyType_Ready(&pygrpc_ServerCredentialsType) < 0) { + PyErr_SetString(PyExc_RuntimeError, + "Error defining pygrpc_ServerCredentialsType!"); + return -1; + } + if (PyModule_AddObject(module, "ServerCredentials", + (PyObject *)&pygrpc_ServerCredentialsType) == -1) { + PyErr_SetString(PyExc_ImportError, + "Couldn't add ServerCredentials type to module!"); + return -1; + } + return 0; +} diff --git a/src/python/src/_adapter/_server_credentials.h b/src/python/src/_adapter/_server_credentials.h new file mode 100644 index 0000000000..2e56efdcd9 --- /dev/null +++ b/src/python/src/_adapter/_server_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__SERVER_CREDENTIALS_H_ +#define _ADAPTER__SERVER_CREDENTIALS_H_ + +#include <Python.h> +#include <grpc/grpc_security.h> + +typedef struct { + PyObject_HEAD grpc_server_credentials *c_server_credentials; +} ServerCredentials; + +PyTypeObject pygrpc_ServerCredentialsType; + +int pygrpc_add_server_credentials(PyObject *module); + +#endif /* _ADAPTER__SERVER_CREDENTIALS_H_ */ |