|
|
f63228 |
diff -up Python-2.7.5/Modules/_ssl.c.wrap Python-2.7.5/Modules/_ssl.c
|
|
|
f63228 |
--- Python-2.7.5/Modules/_ssl.c.wrap 2015-06-25 09:09:59.646325880 +0200
|
|
|
f63228 |
+++ Python-2.7.5/Modules/_ssl.c 2015-06-25 10:33:20.349273370 +0200
|
|
|
f63228 |
@@ -224,6 +224,19 @@ typedef struct {
|
|
|
f63228 |
enum py_ssl_server_or_client socket_type;
|
|
|
f63228 |
} PySSLSocket;
|
|
|
f63228 |
|
|
|
f63228 |
+typedef struct {
|
|
|
f63228 |
+ PyObject_HEAD
|
|
|
f63228 |
+ PySocketSockObject *Socket; /* Socket on which we're layered */
|
|
|
f63228 |
+ PySSLContext* ctx;
|
|
|
f63228 |
+ SSL* ssl;
|
|
|
f63228 |
+ X509* peer_cert;
|
|
|
f63228 |
+ char server[X509_NAME_MAXLEN];
|
|
|
f63228 |
+ char issuer[X509_NAME_MAXLEN];
|
|
|
f63228 |
+ int shutdown_seen_zero;
|
|
|
f63228 |
+
|
|
|
f63228 |
+} PySSLObject;
|
|
|
f63228 |
+
|
|
|
f63228 |
+static PyTypeObject PySSL_Type;
|
|
|
f63228 |
static PyTypeObject PySSLContext_Type;
|
|
|
f63228 |
static PyTypeObject PySSLSocket_Type;
|
|
|
f63228 |
|
|
|
f63228 |
@@ -455,6 +468,138 @@ _setSSLError (char *errstr, int errcode,
|
|
|
f63228 |
* SSL objects
|
|
|
f63228 |
*/
|
|
|
f63228 |
|
|
|
f63228 |
+static PyObject *
|
|
|
f63228 |
+context_new_args(PyTypeObject *type, int proto_version);
|
|
|
f63228 |
+
|
|
|
f63228 |
+static PyObject *
|
|
|
f63228 |
+load_cert_chain_args(PySSLContext *self, char *certfile_bytes, char *keyfile_bytes, PyObject *password);
|
|
|
f63228 |
+
|
|
|
f63228 |
+static PyObject *
|
|
|
f63228 |
+set_ciphers_args(PySSLContext *self, const char *cipherlist);
|
|
|
f63228 |
+
|
|
|
f63228 |
+static PyObject *
|
|
|
f63228 |
+load_verify_locations_args(PySSLContext *self, PyObject *cafile, PyObject *capath, PyObject *cadata);
|
|
|
f63228 |
+
|
|
|
f63228 |
+static int
|
|
|
f63228 |
+set_verify_mode_args(PySSLContext *self, int n);
|
|
|
f63228 |
+
|
|
|
f63228 |
+static PySSLObject *
|
|
|
f63228 |
+newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file,
|
|
|
f63228 |
+ enum py_ssl_server_or_client socket_type,
|
|
|
f63228 |
+ enum py_ssl_cert_requirements certreq,
|
|
|
f63228 |
+ enum py_ssl_version proto_version,
|
|
|
f63228 |
+ PyObject *cacerts_file, const char *ciphers)
|
|
|
f63228 |
+{
|
|
|
f63228 |
+ PySSLObject *self;
|
|
|
f63228 |
+ char *errstr = NULL;
|
|
|
f63228 |
+ SSL_CTX *ctx = NULL;
|
|
|
f63228 |
+
|
|
|
f63228 |
+
|
|
|
f63228 |
+ self = PyObject_New(PySSLObject, &PySSL_Type); /* Create new object */
|
|
|
f63228 |
+ if (self == NULL)
|
|
|
f63228 |
+ return NULL;
|
|
|
f63228 |
+ memset(self->server, '\0', sizeof(char) * X509_NAME_MAXLEN);
|
|
|
f63228 |
+ memset(self->issuer, '\0', sizeof(char) * X509_NAME_MAXLEN);
|
|
|
f63228 |
+
|
|
|
f63228 |
+ self->peer_cert = NULL;
|
|
|
f63228 |
+ self->ssl = NULL;
|
|
|
f63228 |
+ self->ctx = NULL;
|
|
|
f63228 |
+ self->Socket = NULL;
|
|
|
f63228 |
+ self->shutdown_seen_zero = 0;
|
|
|
f63228 |
+
|
|
|
f63228 |
+ /* Make sure the SSL error state is initialized */
|
|
|
f63228 |
+ (void) ERR_get_state();
|
|
|
f63228 |
+ ERR_clear_error();
|
|
|
f63228 |
+
|
|
|
f63228 |
+ if ((socket_type == PY_SSL_SERVER) &&
|
|
|
f63228 |
+ ((key_file == NULL) || (cert_file == NULL))) {
|
|
|
f63228 |
+ errstr = ERRSTR("Both the key & certificate files "
|
|
|
f63228 |
+ "must be specified for server-side operation");
|
|
|
f63228 |
+ goto fail;
|
|
|
f63228 |
+ }
|
|
|
f63228 |
+
|
|
|
f63228 |
+
|
|
|
f63228 |
+ if ((key_file && !cert_file) || (!key_file && cert_file)) {
|
|
|
f63228 |
+ errstr = ERRSTR("Both the key & certificate files "
|
|
|
f63228 |
+ "must be specified");
|
|
|
f63228 |
+ goto fail;
|
|
|
f63228 |
+ }
|
|
|
f63228 |
+
|
|
|
f63228 |
+
|
|
|
f63228 |
+ PyObject *sslctx = context_new_args(&PySSLContext_Type, proto_version);
|
|
|
f63228 |
+ if ((sslctx != NULL) && (PyObject_TypeCheck(sslctx, &PySSLContext_Type))) {
|
|
|
f63228 |
+#if !HAVE_SNI
|
|
|
f63228 |
+ errstr = ERRSTR("setting a socket's "
|
|
|
f63228 |
+ "context is not supported by your OpenSSL library");
|
|
|
f63228 |
+ goto fail;
|
|
|
f63228 |
+#else
|
|
|
f63228 |
+ self->ctx = (PySSLContext *) sslctx;
|
|
|
f63228 |
+ ctx = self->ctx->ctx;
|
|
|
f63228 |
+#endif
|
|
|
f63228 |
+ } else {
|
|
|
f63228 |
+ errstr = ERRSTR("The value must be a SSLContext");
|
|
|
f63228 |
+ goto fail;
|
|
|
f63228 |
+ }
|
|
|
f63228 |
+
|
|
|
f63228 |
+ if (key_file) {
|
|
|
f63228 |
+ load_cert_chain_args(self->ctx, cert_file, key_file, NULL);
|
|
|
f63228 |
+ }
|
|
|
f63228 |
+
|
|
|
f63228 |
+ if (ciphers != NULL) {
|
|
|
f63228 |
+ set_ciphers_args(self->ctx, ciphers);
|
|
|
f63228 |
+ }
|
|
|
f63228 |
+
|
|
|
f63228 |
+
|
|
|
f63228 |
+
|
|
|
f63228 |
+ if (certreq != PY_SSL_CERT_NONE) {
|
|
|
f63228 |
+ if (cacerts_file == Py_None) {
|
|
|
f63228 |
+ errstr = ERRSTR("No root certificates specified for "
|
|
|
f63228 |
+ "verification of other-side certificates.");
|
|
|
f63228 |
+ goto fail;
|
|
|
f63228 |
+ } else {
|
|
|
f63228 |
+ load_verify_locations_args(self->ctx, cacerts_file, NULL, NULL);
|
|
|
f63228 |
+ }
|
|
|
f63228 |
+ }
|
|
|
f63228 |
+
|
|
|
f63228 |
+ /* ssl compatibility */
|
|
|
f63228 |
+ SSL_CTX_set_options(ctx,
|
|
|
f63228 |
+ SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
|
|
|
f63228 |
+
|
|
|
f63228 |
+ set_verify_mode_args(self->ctx, certreq);
|
|
|
f63228 |
+
|
|
|
f63228 |
+ PySSL_BEGIN_ALLOW_THREADS
|
|
|
f63228 |
+ self->ssl = SSL_new(ctx); /* New ssl struct */
|
|
|
f63228 |
+ PySSL_END_ALLOW_THREADS
|
|
|
f63228 |
+ SSL_set_fd(self->ssl, Sock->sock_fd); /* Set the socket for SSL */
|
|
|
f63228 |
+#ifdef SSL_MODE_AUTO_RETRY
|
|
|
f63228 |
+ SSL_set_mode(self->ssl, SSL_MODE_AUTO_RETRY);
|
|
|
f63228 |
+#endif
|
|
|
f63228 |
+
|
|
|
f63228 |
+ /* If the socket is in non-blocking mode or timeout mode, set the BIO
|
|
|
f63228 |
+ * to non-blocking mode (blocking is the default)
|
|
|
f63228 |
+ */
|
|
|
f63228 |
+ if (Sock->sock_timeout >= 0.0) {
|
|
|
f63228 |
+ /* Set both the read and write BIO's to non-blocking mode */
|
|
|
f63228 |
+ BIO_set_nbio(SSL_get_rbio(self->ssl), 1);
|
|
|
f63228 |
+ BIO_set_nbio(SSL_get_wbio(self->ssl), 1);
|
|
|
f63228 |
+ }
|
|
|
f63228 |
+ PySSL_BEGIN_ALLOW_THREADS
|
|
|
f63228 |
+ if (socket_type == PY_SSL_CLIENT)
|
|
|
f63228 |
+ SSL_set_connect_state(self->ssl);
|
|
|
f63228 |
+ else
|
|
|
f63228 |
+ SSL_set_accept_state(self->ssl);
|
|
|
f63228 |
+ PySSL_END_ALLOW_THREADS
|
|
|
f63228 |
+
|
|
|
f63228 |
+ self->Socket = Sock;
|
|
|
f63228 |
+ Py_INCREF(self->Socket);
|
|
|
f63228 |
+ return self;
|
|
|
f63228 |
+ fail:
|
|
|
f63228 |
+ if (errstr)
|
|
|
f63228 |
+ PyErr_SetString(PySSLErrorObject, errstr);
|
|
|
f63228 |
+ Py_DECREF(self);
|
|
|
f63228 |
+ return NULL;
|
|
|
f63228 |
+}
|
|
|
f63228 |
+
|
|
|
f63228 |
static PySSLSocket *
|
|
|
f63228 |
newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
|
|
|
f63228 |
enum py_ssl_server_or_client socket_type,
|
|
|
f63228 |
@@ -526,6 +671,47 @@ newPySSLSocket(PySSLContext *sslctx, PyS
|
|
|
f63228 |
}
|
|
|
f63228 |
|
|
|
f63228 |
|
|
|
f63228 |
+
|
|
|
f63228 |
+
|
|
|
f63228 |
+static PyObject *
|
|
|
f63228 |
+PySSL_sslwrap(PyObject *self, PyObject *args)
|
|
|
f63228 |
+{
|
|
|
f63228 |
+ PySocketSockObject *Sock;
|
|
|
f63228 |
+ int server_side = 0;
|
|
|
f63228 |
+ int verification_mode = PY_SSL_CERT_NONE;
|
|
|
f63228 |
+ int protocol = PY_SSL_VERSION_SSL23;
|
|
|
f63228 |
+ char *key_file = NULL;
|
|
|
f63228 |
+ char *cert_file = NULL;
|
|
|
f63228 |
+ PyObject *cacerts_file;
|
|
|
f63228 |
+ const char *ciphers = NULL;
|
|
|
f63228 |
+
|
|
|
f63228 |
+ if (!PyArg_ParseTuple(args, "O!i|zziizz:sslwrap",
|
|
|
f63228 |
+ PySocketModule.Sock_Type,
|
|
|
f63228 |
+ &Sock,
|
|
|
f63228 |
+ &server_side,
|
|
|
f63228 |
+ &key_file, &cert_file,
|
|
|
f63228 |
+ &verification_mode, &protocol,
|
|
|
f63228 |
+ &cacerts_file, &ciphers))
|
|
|
f63228 |
+ return NULL;
|
|
|
f63228 |
+
|
|
|
f63228 |
+ /*
|
|
|
f63228 |
+ fprintf(stderr,
|
|
|
f63228 |
+ "server_side is %d, keyfile %p, certfile %p, verify_mode %d, "
|
|
|
f63228 |
+ "protocol %d, certs %p\n",
|
|
|
f63228 |
+ server_side, key_file, cert_file, verification_mode,
|
|
|
f63228 |
+ protocol, cacerts_file);
|
|
|
f63228 |
+ */
|
|
|
f63228 |
+
|
|
|
f63228 |
+ return (PyObject *) newPySSLObject(Sock, key_file, cert_file,
|
|
|
f63228 |
+ server_side, verification_mode,
|
|
|
f63228 |
+ protocol, cacerts_file,
|
|
|
f63228 |
+ ciphers);
|
|
|
f63228 |
+}
|
|
|
f63228 |
+
|
|
|
f63228 |
+PyDoc_STRVAR(ssl_doc,
|
|
|
f63228 |
+"sslwrap(socket, server_side, [keyfile, certfile, certs_mode, protocol,\n"
|
|
|
f63228 |
+" cacertsfile, ciphers]) -> sslobject");
|
|
|
f63228 |
+
|
|
|
f63228 |
/* SSL object methods */
|
|
|
f63228 |
|
|
|
f63228 |
static PyObject *PySSL_SSLdo_handshake(PySSLSocket *self)
|
|
|
f63228 |
@@ -1922,6 +2108,11 @@ static PyMethodDef PySSLMethods[] = {
|
|
|
f63228 |
{NULL, NULL}
|
|
|
f63228 |
};
|
|
|
f63228 |
|
|
|
f63228 |
+static PyObject *PySSL_getattr(PySSLObject *self, char *name)
|
|
|
f63228 |
+{
|
|
|
f63228 |
+ return Py_FindMethod(PySSLMethods, (PyObject *)self, name);
|
|
|
f63228 |
+}
|
|
|
f63228 |
+
|
|
|
f63228 |
static PyTypeObject PySSLSocket_Type = {
|
|
|
f63228 |
PyVarObject_HEAD_INIT(NULL, 0)
|
|
|
f63228 |
"_ssl._SSLSocket", /*tp_name*/
|
|
|
f63228 |
@@ -1956,25 +2147,49 @@ static PyTypeObject PySSLSocket_Type = {
|
|
|
f63228 |
ssl_getsetlist, /*tp_getset*/
|
|
|
f63228 |
};
|
|
|
f63228 |
|
|
|
f63228 |
+static PyTypeObject PySSL_Type = {
|
|
|
f63228 |
+ PyVarObject_HEAD_INIT(NULL, 0)
|
|
|
f63228 |
+ "ssl.SSLContext", /*tp_name*/
|
|
|
f63228 |
+ sizeof(PySSLObject), /*tp_basicsize*/
|
|
|
f63228 |
+ 0, /*tp_itemsize*/
|
|
|
f63228 |
+ /* methods */
|
|
|
f63228 |
+ (destructor)PySSL_dealloc, /*tp_dealloc*/
|
|
|
f63228 |
+ 0, /*tp_print*/
|
|
|
f63228 |
+ (getattrfunc)PySSL_getattr, /*tp_getattr*/
|
|
|
f63228 |
+ 0, /*tp_setattr*/
|
|
|
f63228 |
+ 0, /*tp_compare*/
|
|
|
f63228 |
+ 0, /*tp_repr*/
|
|
|
f63228 |
+ 0, /*tp_as_number*/
|
|
|
f63228 |
+ 0, /*tp_as_sequence*/
|
|
|
f63228 |
+ 0, /*tp_as_mapping*/
|
|
|
f63228 |
+ 0, /*tp_hash*/
|
|
|
f63228 |
+};
|
|
|
f63228 |
+
|
|
|
f63228 |
|
|
|
f63228 |
/*
|
|
|
f63228 |
* _SSLContext objects
|
|
|
f63228 |
*/
|
|
|
f63228 |
|
|
|
f63228 |
+
|
|
|
f63228 |
static PyObject *
|
|
|
f63228 |
context_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|
|
f63228 |
{
|
|
|
f63228 |
char *kwlist[] = {"protocol", NULL};
|
|
|
f63228 |
- PySSLContext *self;
|
|
|
f63228 |
int proto_version = PY_SSL_VERSION_SSL23;
|
|
|
f63228 |
- long options;
|
|
|
f63228 |
- SSL_CTX *ctx = NULL;
|
|
|
f63228 |
|
|
|
f63228 |
if (!PyArg_ParseTupleAndKeywords(
|
|
|
f63228 |
args, kwds, "i:_SSLContext", kwlist,
|
|
|
f63228 |
&proto_version))
|
|
|
f63228 |
return NULL;
|
|
|
f63228 |
+ return context_new_args(type, proto_version);
|
|
|
f63228 |
+}
|
|
|
f63228 |
|
|
|
f63228 |
+static PyObject *
|
|
|
f63228 |
+context_new_args(PyTypeObject *type, int proto_version)
|
|
|
f63228 |
+{
|
|
|
f63228 |
+ SSL_CTX *ctx = NULL;
|
|
|
f63228 |
+ PySSLContext *self;
|
|
|
f63228 |
+ long options;
|
|
|
f63228 |
PySSL_BEGIN_ALLOW_THREADS
|
|
|
f63228 |
if (proto_version == PY_SSL_VERSION_TLS1)
|
|
|
f63228 |
ctx = SSL_CTX_new(TLSv1_method());
|
|
|
f63228 |
@@ -2082,11 +2297,16 @@ context_dealloc(PySSLContext *self)
|
|
|
f63228 |
static PyObject *
|
|
|
f63228 |
set_ciphers(PySSLContext *self, PyObject *args)
|
|
|
f63228 |
{
|
|
|
f63228 |
- int ret;
|
|
|
f63228 |
const char *cipherlist;
|
|
|
f63228 |
|
|
|
f63228 |
if (!PyArg_ParseTuple(args, "s:set_ciphers", &cipherlist))
|
|
|
f63228 |
return NULL;
|
|
|
f63228 |
+ return set_ciphers_args(self, cipherlist);
|
|
|
f63228 |
+ }
|
|
|
f63228 |
+
|
|
|
f63228 |
+static PyObject *
|
|
|
f63228 |
+set_ciphers_args(PySSLContext *self, const char *cipherlist){
|
|
|
f63228 |
+ int ret;
|
|
|
f63228 |
ret = SSL_CTX_set_cipher_list(self->ctx, cipherlist);
|
|
|
f63228 |
if (ret == 0) {
|
|
|
f63228 |
/* Clearing the error queue is necessary on some OpenSSL versions,
|
|
|
f63228 |
@@ -2204,9 +2424,17 @@ get_verify_mode(PySSLContext *self, void
|
|
|
f63228 |
static int
|
|
|
f63228 |
set_verify_mode(PySSLContext *self, PyObject *arg, void *c)
|
|
|
f63228 |
{
|
|
|
f63228 |
- int n, mode;
|
|
|
f63228 |
+ int n;
|
|
|
f63228 |
if (!PyArg_Parse(arg, "i", &n))
|
|
|
f63228 |
return -1;
|
|
|
f63228 |
+ return set_verify_mode_args(self, n);
|
|
|
f63228 |
+ }
|
|
|
f63228 |
+
|
|
|
f63228 |
+static int
|
|
|
f63228 |
+set_verify_mode_args(PySSLContext *self, int n)
|
|
|
f63228 |
+{
|
|
|
f63228 |
+ int mode;
|
|
|
f63228 |
+
|
|
|
f63228 |
if (n == PY_SSL_CERT_NONE)
|
|
|
f63228 |
mode = SSL_VERIFY_NONE;
|
|
|
f63228 |
else if (n == PY_SSL_CERT_OPTIONAL)
|
|
|
f63228 |
@@ -2434,10 +2662,6 @@ load_cert_chain(PySSLContext *self, PyOb
|
|
|
f63228 |
char *kwlist[] = {"certfile", "keyfile", "password", NULL};
|
|
|
f63228 |
PyObject *password = NULL;
|
|
|
f63228 |
char *certfile_bytes = NULL, *keyfile_bytes = NULL;
|
|
|
f63228 |
- pem_password_cb *orig_passwd_cb = self->ctx->default_passwd_callback;
|
|
|
f63228 |
- void *orig_passwd_userdata = self->ctx->default_passwd_callback_userdata;
|
|
|
f63228 |
- _PySSLPasswordInfo pw_info = { NULL, NULL, NULL, 0, 0 };
|
|
|
f63228 |
- int r;
|
|
|
f63228 |
|
|
|
f63228 |
errno = 0;
|
|
|
f63228 |
ERR_clear_error();
|
|
|
f63228 |
@@ -2447,6 +2671,17 @@ load_cert_chain(PySSLContext *self, PyOb
|
|
|
f63228 |
Py_FileSystemDefaultEncoding, &keyfile_bytes,
|
|
|
f63228 |
&password))
|
|
|
f63228 |
return NULL;
|
|
|
f63228 |
+ return load_cert_chain_args(self, certfile_bytes, keyfile_bytes, password);
|
|
|
f63228 |
+ }
|
|
|
f63228 |
+
|
|
|
f63228 |
+static PyObject *
|
|
|
f63228 |
+load_cert_chain_args(PySSLContext *self, char *certfile_bytes, char *keyfile_bytes ,PyObject *password){
|
|
|
f63228 |
+
|
|
|
f63228 |
+ pem_password_cb *orig_passwd_cb = self->ctx->default_passwd_callback;
|
|
|
f63228 |
+ void *orig_passwd_userdata = self->ctx->default_passwd_callback_userdata;
|
|
|
f63228 |
+ _PySSLPasswordInfo pw_info = { NULL, NULL, NULL, 0, 0 };
|
|
|
f63228 |
+ int r;
|
|
|
f63228 |
+
|
|
|
f63228 |
if (password && password != Py_None) {
|
|
|
f63228 |
if (PyCallable_Check(password)) {
|
|
|
f63228 |
pw_info.callable = password;
|
|
|
f63228 |
@@ -2598,22 +2833,27 @@ _add_ca_certs(PySSLContext *self, void *
|
|
|
f63228 |
return retval;
|
|
|
f63228 |
}
|
|
|
f63228 |
|
|
|
f63228 |
-
|
|
|
f63228 |
static PyObject *
|
|
|
f63228 |
load_verify_locations(PySSLContext *self, PyObject *args, PyObject *kwds)
|
|
|
f63228 |
{
|
|
|
f63228 |
char *kwlist[] = {"cafile", "capath", "cadata", NULL};
|
|
|
f63228 |
PyObject *cadata = NULL, *cafile = NULL, *capath = NULL;
|
|
|
f63228 |
- PyObject *cafile_bytes = NULL, *capath_bytes = NULL;
|
|
|
f63228 |
- const char *cafile_buf = NULL, *capath_buf = NULL;
|
|
|
f63228 |
- int r = 0, ok = 1;
|
|
|
f63228 |
-
|
|
|
f63228 |
- errno = 0;
|
|
|
f63228 |
if (!PyArg_ParseTupleAndKeywords(args, kwds,
|
|
|
f63228 |
"|OOO:load_verify_locations", kwlist,
|
|
|
f63228 |
&cafile, &capath, &cadata))
|
|
|
f63228 |
return NULL;
|
|
|
f63228 |
+ return load_verify_locations_args(self, cafile, capath, cadata);
|
|
|
f63228 |
+ }
|
|
|
f63228 |
+
|
|
|
f63228 |
|
|
|
f63228 |
+static PyObject *
|
|
|
f63228 |
+load_verify_locations_args(PySSLContext *self, PyObject *cafile, PyObject *capath, PyObject *cadata)
|
|
|
f63228 |
+{
|
|
|
f63228 |
+ PyObject *cafile_bytes = NULL, *capath_bytes = NULL;
|
|
|
f63228 |
+ const char *cafile_buf = NULL, *capath_buf = NULL;
|
|
|
f63228 |
+ int r = 0, ok = 1;
|
|
|
f63228 |
+
|
|
|
f63228 |
+ errno = 0;
|
|
|
f63228 |
if (cafile == Py_None)
|
|
|
f63228 |
cafile = NULL;
|
|
|
f63228 |
if (capath == Py_None)
|
|
|
f63228 |
@@ -3688,6 +3928,8 @@ PySSL_enum_crls(PyObject *self, PyObject
|
|
|
f63228 |
/* List of functions exported by this module. */
|
|
|
f63228 |
|
|
|
f63228 |
static PyMethodDef PySSL_methods[] = {
|
|
|
f63228 |
+ {"sslwrap", PySSL_sslwrap,
|
|
|
f63228 |
+ METH_VARARGS, ssl_doc},
|
|
|
f63228 |
{"_test_decode_cert", PySSL_test_decode_certificate,
|
|
|
f63228 |
METH_VARARGS},
|
|
|
f63228 |
#ifdef HAVE_OPENSSL_RAND
|