Blame SOURCES/00221-pep466-backport-sslwrap-c-ssl.patch

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