summaryrefslogtreecommitdiff
path: root/sys/src/cmd/python/Modules/_ssl.c
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2021-06-14 00:00:37 +0000
committerOri Bernstein <ori@eigenstate.org>2021-06-14 00:00:37 +0000
commita73a964e51247ed169d322c725a3a18859f109a3 (patch)
tree3f752d117274d444bda44e85609aeac1acf313f3 /sys/src/cmd/python/Modules/_ssl.c
parente64efe273fcb921a61bf27d33b230c4e64fcd425 (diff)
python, hg: tow outside the environment.
they've served us well, and can ride off into the sunset.
Diffstat (limited to 'sys/src/cmd/python/Modules/_ssl.c')
-rw-r--r--sys/src/cmd/python/Modules/_ssl.c726
1 files changed, 0 insertions, 726 deletions
diff --git a/sys/src/cmd/python/Modules/_ssl.c b/sys/src/cmd/python/Modules/_ssl.c
deleted file mode 100644
index 3b91b2451..000000000
--- a/sys/src/cmd/python/Modules/_ssl.c
+++ /dev/null
@@ -1,726 +0,0 @@
-/* SSL socket module
-
- SSL support based on patches by Brian E Gallew and Laszlo Kovacs.
-
- This module is imported by socket.py. It should *not* be used
- directly.
-
-*/
-
-#include "Python.h"
-enum py_ssl_error {
- /* these mirror ssl.h */
- PY_SSL_ERROR_NONE,
- PY_SSL_ERROR_SSL,
- PY_SSL_ERROR_WANT_READ,
- PY_SSL_ERROR_WANT_WRITE,
- PY_SSL_ERROR_WANT_X509_LOOKUP,
- PY_SSL_ERROR_SYSCALL, /* look at error stack/return value/errno */
- PY_SSL_ERROR_ZERO_RETURN,
- PY_SSL_ERROR_WANT_CONNECT,
- /* start of non ssl.h errorcodes */
- PY_SSL_ERROR_EOF, /* special case of SSL_ERROR_SYSCALL */
- PY_SSL_ERROR_INVALID_ERROR_CODE
-};
-
-/* Include symbols from _socket module */
-#include "socketmodule.h"
-
-#if defined(HAVE_POLL_H)
-#include <poll.h>
-#elif defined(HAVE_SYS_POLL_H)
-#include <sys/poll.h>
-#endif
-
-/* Include OpenSSL header files */
-#include "openssl/rsa.h"
-#include "openssl/crypto.h"
-#include "openssl/x509.h"
-#include "openssl/pem.h"
-#include "openssl/ssl.h"
-#include "openssl/err.h"
-#include "openssl/rand.h"
-
-/* SSL error object */
-static PyObject *PySSLErrorObject;
-
-/* SSL socket object */
-
-#define X509_NAME_MAXLEN 256
-
-/* RAND_* APIs got added to OpenSSL in 0.9.5 */
-#if OPENSSL_VERSION_NUMBER >= 0x0090500fL
-# define HAVE_OPENSSL_RAND 1
-#else
-# undef HAVE_OPENSSL_RAND
-#endif
-
-typedef struct {
- PyObject_HEAD
- PySocketSockObject *Socket; /* Socket on which we're layered */
- SSL_CTX* ctx;
- SSL* ssl;
- X509* server_cert;
- char server[X509_NAME_MAXLEN];
- char issuer[X509_NAME_MAXLEN];
-
-} PySSLObject;
-
-static PyTypeObject PySSL_Type;
-static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args);
-static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args);
-static int check_socket_and_wait_for_timeout(PySocketSockObject *s,
- int writing);
-
-#define PySSLObject_Check(v) ((v)->ob_type == &PySSL_Type)
-
-typedef enum {
- SOCKET_IS_NONBLOCKING,
- SOCKET_IS_BLOCKING,
- SOCKET_HAS_TIMED_OUT,
- SOCKET_HAS_BEEN_CLOSED,
- SOCKET_TOO_LARGE_FOR_SELECT,
- SOCKET_OPERATION_OK
-} timeout_state;
-
-/* XXX It might be helpful to augment the error message generated
- below with the name of the SSL function that generated the error.
- I expect it's obvious most of the time.
-*/
-
-static PyObject *
-PySSL_SetError(PySSLObject *obj, int ret)
-{
- PyObject *v, *n, *s;
- char *errstr;
- int err;
- enum py_ssl_error p;
-
- assert(ret <= 0);
-
- err = SSL_get_error(obj->ssl, ret);
-
- switch (err) {
- case SSL_ERROR_ZERO_RETURN:
- errstr = "TLS/SSL connection has been closed";
- p = PY_SSL_ERROR_ZERO_RETURN;
- break;
- case SSL_ERROR_WANT_READ:
- errstr = "The operation did not complete (read)";
- p = PY_SSL_ERROR_WANT_READ;
- break;
- case SSL_ERROR_WANT_WRITE:
- p = PY_SSL_ERROR_WANT_WRITE;
- errstr = "The operation did not complete (write)";
- break;
- case SSL_ERROR_WANT_X509_LOOKUP:
- p = PY_SSL_ERROR_WANT_X509_LOOKUP;
- errstr = "The operation did not complete (X509 lookup)";
- break;
- case SSL_ERROR_WANT_CONNECT:
- p = PY_SSL_ERROR_WANT_CONNECT;
- errstr = "The operation did not complete (connect)";
- break;
- case SSL_ERROR_SYSCALL:
- {
- unsigned long e = ERR_get_error();
- if (e == 0) {
- if (ret == 0 || !obj->Socket) {
- p = PY_SSL_ERROR_EOF;
- errstr = "EOF occurred in violation of protocol";
- } else if (ret == -1) {
- /* the underlying BIO reported an I/O error */
- return obj->Socket->errorhandler();
- } else { /* possible? */
- p = PY_SSL_ERROR_SYSCALL;
- errstr = "Some I/O error occurred";
- }
- } else {
- p = PY_SSL_ERROR_SYSCALL;
- /* XXX Protected by global interpreter lock */
- errstr = ERR_error_string(e, NULL);
- }
- break;
- }
- case SSL_ERROR_SSL:
- {
- unsigned long e = ERR_get_error();
- p = PY_SSL_ERROR_SSL;
- if (e != 0)
- /* XXX Protected by global interpreter lock */
- errstr = ERR_error_string(e, NULL);
- else { /* possible? */
- errstr = "A failure in the SSL library occurred";
- }
- break;
- }
- default:
- p = PY_SSL_ERROR_INVALID_ERROR_CODE;
- errstr = "Invalid error code";
- }
- n = PyInt_FromLong((long) p);
- if (n == NULL)
- return NULL;
- v = PyTuple_New(2);
- if (v == NULL) {
- Py_DECREF(n);
- return NULL;
- }
-
- s = PyString_FromString(errstr);
- if (s == NULL) {
- Py_DECREF(v);
- Py_DECREF(n);
- }
- PyTuple_SET_ITEM(v, 0, n);
- PyTuple_SET_ITEM(v, 1, s);
- PyErr_SetObject(PySSLErrorObject, v);
- Py_DECREF(v);
- return NULL;
-}
-
-static PySSLObject *
-newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file)
-{
- PySSLObject *self;
- char *errstr = NULL;
- int ret;
- int err;
- int sockstate;
-
- self = PyObject_New(PySSLObject, &PySSL_Type); /* Create new object */
- if (self == NULL)
- return NULL;
- memset(self->server, '\0', sizeof(char) * X509_NAME_MAXLEN);
- memset(self->issuer, '\0', sizeof(char) * X509_NAME_MAXLEN);
- self->server_cert = NULL;
- self->ssl = NULL;
- self->ctx = NULL;
- self->Socket = NULL;
-
- if ((key_file && !cert_file) || (!key_file && cert_file)) {
- errstr = "Both the key & certificate files must be specified";
- goto fail;
- }
-
- Py_BEGIN_ALLOW_THREADS
- self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */
- Py_END_ALLOW_THREADS
- if (self->ctx == NULL) {
- errstr = "SSL_CTX_new error";
- goto fail;
- }
-
- if (key_file) {
- Py_BEGIN_ALLOW_THREADS
- ret = SSL_CTX_use_PrivateKey_file(self->ctx, key_file,
- SSL_FILETYPE_PEM);
- Py_END_ALLOW_THREADS
- if (ret < 1) {
- errstr = "SSL_CTX_use_PrivateKey_file error";
- goto fail;
- }
-
- Py_BEGIN_ALLOW_THREADS
- ret = SSL_CTX_use_certificate_chain_file(self->ctx,
- cert_file);
- Py_END_ALLOW_THREADS
- SSL_CTX_set_options(self->ctx, SSL_OP_ALL); /* ssl compatibility */
- if (ret < 1) {
- errstr = "SSL_CTX_use_certificate_chain_file error";
- goto fail;
- }
- }
-
- Py_BEGIN_ALLOW_THREADS
- SSL_CTX_set_verify(self->ctx,
- SSL_VERIFY_NONE, NULL); /* set verify lvl */
- self->ssl = SSL_new(self->ctx); /* New ssl struct */
- Py_END_ALLOW_THREADS
- SSL_set_fd(self->ssl, Sock->sock_fd); /* Set the socket for SSL */
-
- /* If the socket is in non-blocking mode or timeout mode, set the BIO
- * to non-blocking mode (blocking is the default)
- */
- if (Sock->sock_timeout >= 0.0) {
- /* Set both the read and write BIO's to non-blocking mode */
- BIO_set_nbio(SSL_get_rbio(self->ssl), 1);
- BIO_set_nbio(SSL_get_wbio(self->ssl), 1);
- }
-
- Py_BEGIN_ALLOW_THREADS
- SSL_set_connect_state(self->ssl);
- Py_END_ALLOW_THREADS
-
- /* Actually negotiate SSL connection */
- /* XXX If SSL_connect() returns 0, it's also a failure. */
- sockstate = 0;
- do {
- Py_BEGIN_ALLOW_THREADS
- ret = SSL_connect(self->ssl);
- err = SSL_get_error(self->ssl, ret);
- Py_END_ALLOW_THREADS
- if(PyErr_CheckSignals()) {
- goto fail;
- }
- if (err == SSL_ERROR_WANT_READ) {
- sockstate = check_socket_and_wait_for_timeout(Sock, 0);
- } else if (err == SSL_ERROR_WANT_WRITE) {
- sockstate = check_socket_and_wait_for_timeout(Sock, 1);
- } else {
- sockstate = SOCKET_OPERATION_OK;
- }
- if (sockstate == SOCKET_HAS_TIMED_OUT) {
- PyErr_SetString(PySSLErrorObject, "The connect operation timed out");
- goto fail;
- } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
- PyErr_SetString(PySSLErrorObject, "Underlying socket has been closed.");
- goto fail;
- } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
- PyErr_SetString(PySSLErrorObject, "Underlying socket too large for select().");
- goto fail;
- } else if (sockstate == SOCKET_IS_NONBLOCKING) {
- break;
- }
- } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
- if (ret <= 0) {
- PySSL_SetError(self, ret);
- goto fail;
- }
- self->ssl->debug = 1;
-
- Py_BEGIN_ALLOW_THREADS
- if ((self->server_cert = SSL_get_peer_certificate(self->ssl))) {
- X509_NAME_oneline(X509_get_subject_name(self->server_cert),
- self->server, X509_NAME_MAXLEN);
- X509_NAME_oneline(X509_get_issuer_name(self->server_cert),
- self->issuer, X509_NAME_MAXLEN);
- }
- Py_END_ALLOW_THREADS
- self->Socket = Sock;
- Py_INCREF(self->Socket);
- return self;
- fail:
- if (errstr)
- PyErr_SetString(PySSLErrorObject, errstr);
- Py_DECREF(self);
- return NULL;
-}
-
-static PyObject *
-PySocket_ssl(PyObject *self, PyObject *args)
-{
- PySSLObject *rv;
- PySocketSockObject *Sock;
- char *key_file = NULL;
- char *cert_file = NULL;
-
- if (!PyArg_ParseTuple(args, "O!|zz:ssl",
- PySocketModule.Sock_Type,
- (PyObject*)&Sock,
- &key_file, &cert_file))
- return NULL;
-
- rv = newPySSLObject(Sock, key_file, cert_file);
- if (rv == NULL)
- return NULL;
- return (PyObject *)rv;
-}
-
-PyDoc_STRVAR(ssl_doc,
-"ssl(socket, [keyfile, certfile]) -> sslobject");
-
-/* SSL object methods */
-
-static PyObject *
-PySSL_server(PySSLObject *self)
-{
- return PyString_FromString(self->server);
-}
-
-static PyObject *
-PySSL_issuer(PySSLObject *self)
-{
- return PyString_FromString(self->issuer);
-}
-
-
-static void PySSL_dealloc(PySSLObject *self)
-{
- if (self->server_cert) /* Possible not to have one? */
- X509_free (self->server_cert);
- if (self->ssl)
- SSL_free(self->ssl);
- if (self->ctx)
- SSL_CTX_free(self->ctx);
- Py_XDECREF(self->Socket);
- PyObject_Del(self);
-}
-
-/* If the socket has a timeout, do a select()/poll() on the socket.
- The argument writing indicates the direction.
- Returns one of the possibilities in the timeout_state enum (above).
- */
-
-static int
-check_socket_and_wait_for_timeout(PySocketSockObject *s, int writing)
-{
- fd_set fds;
- struct timeval tv;
- int rc;
-
- /* Nothing to do unless we're in timeout mode (not non-blocking) */
- if (s->sock_timeout < 0.0)
- return SOCKET_IS_BLOCKING;
- else if (s->sock_timeout == 0.0)
- return SOCKET_IS_NONBLOCKING;
-
- /* Guard against closed socket */
- if (s->sock_fd < 0)
- return SOCKET_HAS_BEEN_CLOSED;
-
- /* Prefer poll, if available, since you can poll() any fd
- * which can't be done with select(). */
-#ifdef HAVE_POLL
- {
- struct pollfd pollfd;
- int timeout;
-
- pollfd.fd = s->sock_fd;
- pollfd.events = writing ? POLLOUT : POLLIN;
-
- /* s->sock_timeout is in seconds, timeout in ms */
- timeout = (int)(s->sock_timeout * 1000 + 0.5);
- Py_BEGIN_ALLOW_THREADS
- rc = poll(&pollfd, 1, timeout);
- Py_END_ALLOW_THREADS
-
- goto normal_return;
- }
-#endif
-
- /* Guard against socket too large for select*/
-#ifndef Py_SOCKET_FD_CAN_BE_GE_FD_SETSIZE
- if (s->sock_fd >= FD_SETSIZE)
- return SOCKET_TOO_LARGE_FOR_SELECT;
-#endif
-
- /* Construct the arguments to select */
- tv.tv_sec = (int)s->sock_timeout;
- tv.tv_usec = (int)((s->sock_timeout - tv.tv_sec) * 1e6);
- FD_ZERO(&fds);
- FD_SET(s->sock_fd, &fds);
-
- /* See if the socket is ready */
- Py_BEGIN_ALLOW_THREADS
- if (writing)
- rc = select(s->sock_fd+1, NULL, &fds, NULL, &tv);
- else
- rc = select(s->sock_fd+1, &fds, NULL, NULL, &tv);
- Py_END_ALLOW_THREADS
-
-normal_return:
- /* Return SOCKET_TIMED_OUT on timeout, SOCKET_OPERATION_OK otherwise
- (when we are able to write or when there's something to read) */
- return rc == 0 ? SOCKET_HAS_TIMED_OUT : SOCKET_OPERATION_OK;
-}
-
-static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args)
-{
- char *data;
- int len;
- int count;
- int sockstate;
- int err;
-
- if (!PyArg_ParseTuple(args, "s#:write", &data, &count))
- return NULL;
-
- sockstate = check_socket_and_wait_for_timeout(self->Socket, 1);
- if (sockstate == SOCKET_HAS_TIMED_OUT) {
- PyErr_SetString(PySSLErrorObject, "The write operation timed out");
- return NULL;
- } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
- PyErr_SetString(PySSLErrorObject, "Underlying socket has been closed.");
- return NULL;
- } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
- PyErr_SetString(PySSLErrorObject, "Underlying socket too large for select().");
- return NULL;
- }
- do {
- err = 0;
- Py_BEGIN_ALLOW_THREADS
- len = SSL_write(self->ssl, data, count);
- err = SSL_get_error(self->ssl, len);
- Py_END_ALLOW_THREADS
- if(PyErr_CheckSignals()) {
- return NULL;
- }
- if (err == SSL_ERROR_WANT_READ) {
- sockstate = check_socket_and_wait_for_timeout(self->Socket, 0);
- } else if (err == SSL_ERROR_WANT_WRITE) {
- sockstate = check_socket_and_wait_for_timeout(self->Socket, 1);
- } else {
- sockstate = SOCKET_OPERATION_OK;
- }
- if (sockstate == SOCKET_HAS_TIMED_OUT) {
- PyErr_SetString(PySSLErrorObject, "The write operation timed out");
- return NULL;
- } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
- PyErr_SetString(PySSLErrorObject, "Underlying socket has been closed.");
- return NULL;
- } else if (sockstate == SOCKET_IS_NONBLOCKING) {
- break;
- }
- } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
- if (len > 0)
- return PyInt_FromLong(len);
- else
- return PySSL_SetError(self, len);
-}
-
-PyDoc_STRVAR(PySSL_SSLwrite_doc,
-"write(s) -> len\n\
-\n\
-Writes the string s into the SSL object. Returns the number\n\
-of bytes written.");
-
-static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
-{
- PyObject *buf;
- int count = 0;
- int len = 1024;
- int sockstate;
- int err;
-
- if (!PyArg_ParseTuple(args, "|i:read", &len))
- return NULL;
-
- if (!(buf = PyString_FromStringAndSize((char *) 0, len)))
- return NULL;
-
- /* first check if there are bytes ready to be read */
- Py_BEGIN_ALLOW_THREADS
- count = SSL_pending(self->ssl);
- Py_END_ALLOW_THREADS
-
- if (!count) {
- sockstate = check_socket_and_wait_for_timeout(self->Socket, 0);
- if (sockstate == SOCKET_HAS_TIMED_OUT) {
- PyErr_SetString(PySSLErrorObject, "The read operation timed out");
- Py_DECREF(buf);
- return NULL;
- } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
- PyErr_SetString(PySSLErrorObject, "Underlying socket too large for select().");
- return NULL;
- }
- }
- do {
- err = 0;
- Py_BEGIN_ALLOW_THREADS
- count = SSL_read(self->ssl, PyString_AsString(buf), len);
- err = SSL_get_error(self->ssl, count);
- Py_END_ALLOW_THREADS
- if(PyErr_CheckSignals()) {
- Py_DECREF(buf);
- return NULL;
- }
- if (err == SSL_ERROR_WANT_READ) {
- sockstate = check_socket_and_wait_for_timeout(self->Socket, 0);
- } else if (err == SSL_ERROR_WANT_WRITE) {
- sockstate = check_socket_and_wait_for_timeout(self->Socket, 1);
- } else {
- sockstate = SOCKET_OPERATION_OK;
- }
- if (sockstate == SOCKET_HAS_TIMED_OUT) {
- PyErr_SetString(PySSLErrorObject, "The read operation timed out");
- Py_DECREF(buf);
- return NULL;
- } else if (sockstate == SOCKET_IS_NONBLOCKING) {
- break;
- }
- } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
- if (count <= 0) {
- Py_DECREF(buf);
- return PySSL_SetError(self, count);
- }
- if (count != len)
- _PyString_Resize(&buf, count);
- return buf;
-}
-
-PyDoc_STRVAR(PySSL_SSLread_doc,
-"read([len]) -> string\n\
-\n\
-Read up to len bytes from the SSL socket.");
-
-static PyMethodDef PySSLMethods[] = {
- {"write", (PyCFunction)PySSL_SSLwrite, METH_VARARGS,
- PySSL_SSLwrite_doc},
- {"read", (PyCFunction)PySSL_SSLread, METH_VARARGS,
- PySSL_SSLread_doc},
- {"server", (PyCFunction)PySSL_server, METH_NOARGS},
- {"issuer", (PyCFunction)PySSL_issuer, METH_NOARGS},
- {NULL, NULL}
-};
-
-static PyObject *PySSL_getattr(PySSLObject *self, char *name)
-{
- return Py_FindMethod(PySSLMethods, (PyObject *)self, name);
-}
-
-static PyTypeObject PySSL_Type = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "socket.SSL", /*tp_name*/
- sizeof(PySSLObject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- /* methods */
- (destructor)PySSL_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- (getattrfunc)PySSL_getattr, /*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*/
-};
-
-#ifdef HAVE_OPENSSL_RAND
-
-/* helper routines for seeding the SSL PRNG */
-static PyObject *
-PySSL_RAND_add(PyObject *self, PyObject *args)
-{
- char *buf;
- int len;
- double entropy;
-
- if (!PyArg_ParseTuple(args, "s#d:RAND_add", &buf, &len, &entropy))
- return NULL;
- RAND_add(buf, len, entropy);
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-PyDoc_STRVAR(PySSL_RAND_add_doc,
-"RAND_add(string, entropy)\n\
-\n\
-Mix string into the OpenSSL PRNG state. entropy (a float) is a lower\n\
-bound on the entropy contained in string.");
-
-static PyObject *
-PySSL_RAND_status(PyObject *self)
-{
- return PyInt_FromLong(RAND_status());
-}
-
-PyDoc_STRVAR(PySSL_RAND_status_doc,
-"RAND_status() -> 0 or 1\n\
-\n\
-Returns 1 if the OpenSSL PRNG has been seeded with enough data and 0 if not.\n\
-It is necessary to seed the PRNG with RAND_add() on some platforms before\n\
-using the ssl() function.");
-
-static PyObject *
-PySSL_RAND_egd(PyObject *self, PyObject *arg)
-{
- int bytes;
-
- if (!PyString_Check(arg))
- return PyErr_Format(PyExc_TypeError,
- "RAND_egd() expected string, found %s",
- arg->ob_type->tp_name);
- bytes = RAND_egd(PyString_AS_STRING(arg));
- if (bytes == -1) {
- PyErr_SetString(PySSLErrorObject,
- "EGD connection failed or EGD did not return "
- "enough data to seed the PRNG");
- return NULL;
- }
- return PyInt_FromLong(bytes);
-}
-
-PyDoc_STRVAR(PySSL_RAND_egd_doc,
-"RAND_egd(path) -> bytes\n\
-\n\
-Queries the entropy gather daemon (EGD) on socket path. Returns number\n\
-of bytes read. Raises socket.sslerror if connection to EGD fails or\n\
-if it does provide enough data to seed PRNG.");
-
-#endif
-
-/* List of functions exported by this module. */
-
-static PyMethodDef PySSL_methods[] = {
- {"ssl", PySocket_ssl,
- METH_VARARGS, ssl_doc},
-#ifdef HAVE_OPENSSL_RAND
- {"RAND_add", PySSL_RAND_add, METH_VARARGS,
- PySSL_RAND_add_doc},
- {"RAND_egd", PySSL_RAND_egd, METH_O,
- PySSL_RAND_egd_doc},
- {"RAND_status", (PyCFunction)PySSL_RAND_status, METH_NOARGS,
- PySSL_RAND_status_doc},
-#endif
- {NULL, NULL} /* Sentinel */
-};
-
-
-PyDoc_STRVAR(module_doc,
-"Implementation module for SSL socket operations. See the socket module\n\
-for documentation.");
-
-PyMODINIT_FUNC
-init_ssl(void)
-{
- PyObject *m, *d;
-
- PySSL_Type.ob_type = &PyType_Type;
-
- m = Py_InitModule3("_ssl", PySSL_methods, module_doc);
- if (m == NULL)
- return;
- d = PyModule_GetDict(m);
-
- /* Load _socket module and its C API */
- if (PySocketModule_ImportModuleAndAPI())
- return;
-
- /* Init OpenSSL */
- SSL_load_error_strings();
- SSLeay_add_ssl_algorithms();
-
- /* Add symbols to module dict */
- PySSLErrorObject = PyErr_NewException("socket.sslerror",
- PySocketModule.error,
- NULL);
- if (PySSLErrorObject == NULL)
- return;
- PyDict_SetItemString(d, "sslerror", PySSLErrorObject);
- if (PyDict_SetItemString(d, "SSLType",
- (PyObject *)&PySSL_Type) != 0)
- return;
- PyModule_AddIntConstant(m, "SSL_ERROR_ZERO_RETURN",
- PY_SSL_ERROR_ZERO_RETURN);
- PyModule_AddIntConstant(m, "SSL_ERROR_WANT_READ",
- PY_SSL_ERROR_WANT_READ);
- PyModule_AddIntConstant(m, "SSL_ERROR_WANT_WRITE",
- PY_SSL_ERROR_WANT_WRITE);
- PyModule_AddIntConstant(m, "SSL_ERROR_WANT_X509_LOOKUP",
- PY_SSL_ERROR_WANT_X509_LOOKUP);
- PyModule_AddIntConstant(m, "SSL_ERROR_SYSCALL",
- PY_SSL_ERROR_SYSCALL);
- PyModule_AddIntConstant(m, "SSL_ERROR_SSL",
- PY_SSL_ERROR_SSL);
- PyModule_AddIntConstant(m, "SSL_ERROR_WANT_CONNECT",
- PY_SSL_ERROR_WANT_CONNECT);
- /* non ssl.h errorcodes */
- PyModule_AddIntConstant(m, "SSL_ERROR_EOF",
- PY_SSL_ERROR_EOF);
- PyModule_AddIntConstant(m, "SSL_ERROR_INVALID_ERROR_CODE",
- PY_SSL_ERROR_INVALID_ERROR_CODE);
-
-}