Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
static PyObject *PySSL_SSLdo_handshake(PySSLObject *self)
{
	int ret;
	int err;
	int sockstate;

	/* Actually negotiate SSL connection */
	/* XXX If SSL_do_handshake() returns 0, it's also a failure. */
	sockstate = 0;
	do {
                PySocketSockObject *sock
                  = (PySocketSockObject *) PyWeakref_GetObject(self->Socket);
                if (((PyObject*)sock) == Py_None) {
                        _setSSLError("Underlying socket connection gone",
                                     PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
                        return NULL;
                }

		PySSL_BEGIN_ALLOW_THREADS
		ret = SSL_do_handshake(self->ssl);
		err = SSL_get_error(self->ssl, ret);
		PySSL_END_ALLOW_THREADS
		if(PyErr_CheckSignals()) {
			return NULL;
		}
		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,
				ERRSTR("The handshake operation timed out"));
			return NULL;
		} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
			PyErr_SetString(PySSLErrorObject,
				ERRSTR("Underlying socket has been closed."));
			return NULL;
		} else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
			PyErr_SetString(PySSLErrorObject,
			  ERRSTR("Underlying socket too large for select()."));
			return NULL;
		} else if (sockstate == SOCKET_IS_NONBLOCKING) {
			break;
		}
	} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
	if (ret < 1)
		return PySSL_SetError(self, ret, __FILE__, __LINE__);
	self->ssl->debug = 1;

	if (self->peer_cert)
		X509_free (self->peer_cert);
        PySSL_BEGIN_ALLOW_THREADS
	self->peer_cert = SSL_get_peer_certificate(self->ssl);
	PySSL_END_ALLOW_THREADS

	Py_INCREF(Py_None);
	return Py_None;
}
Ejemplo n.º 3
0
static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
{
	PyObject *dest = NULL;
	Py_buffer buf;
	int buf_passed = 0;
	int count = -1;
	char *mem;
	/* XXX this should use Py_ssize_t */
	int len = 1024;
	int sockstate;
	int err;
        int nonblocking;
        PySocketSockObject *sock
          = (PySocketSockObject *) PyWeakref_GetObject(self->Socket);

        if (((PyObject*)sock) == Py_None) {
                _setSSLError("Underlying socket connection gone",
                             PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
                return NULL;
        }

	if (!PyArg_ParseTuple(args, "|Oi:read", &dest, &count))
		return NULL;
        if ((dest == NULL) || (dest == Py_None)) {
		if (!(dest = PyByteArray_FromStringAndSize((char *) 0, len)))
			return NULL;
		mem = PyByteArray_AS_STRING(dest);
        } else if (PyLong_Check(dest)) {
		len = PyLong_AS_LONG(dest);
		if (!(dest = PyByteArray_FromStringAndSize((char *) 0, len)))
			return NULL;
		mem = PyByteArray_AS_STRING(dest);
	} else {
		if (PyObject_GetBuffer(dest, &buf, PyBUF_CONTIG) < 0)
			return NULL;
		mem = buf.buf;
		len = buf.len;
		if ((count > 0) && (count <= len))
			len = count;
		buf_passed = 1;
	}

        /* just in case the blocking state of the socket has been changed */
	nonblocking = (sock->sock_timeout >= 0.0);
        BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking);
        BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking);

	/* first check if there are bytes ready to be read */
	PySSL_BEGIN_ALLOW_THREADS
	count = SSL_pending(self->ssl);
	PySSL_END_ALLOW_THREADS

	if (!count) {
		sockstate = check_socket_and_wait_for_timeout(sock, 0);
		if (sockstate == SOCKET_HAS_TIMED_OUT) {
			PyErr_SetString(PySSLErrorObject,
					"The read operation timed out");
			goto error;
		} else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
			PyErr_SetString(PySSLErrorObject,
				"Underlying socket too large for select().");
			goto error;
		} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
			count = 0;
			goto done;
		}
	}
	do {
		err = 0;
		PySSL_BEGIN_ALLOW_THREADS
		count = SSL_read(self->ssl, mem, len);
		err = SSL_get_error(self->ssl, count);
		PySSL_END_ALLOW_THREADS
		if (PyErr_CheckSignals())
			goto error;
		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 if ((err == SSL_ERROR_ZERO_RETURN) &&
			   (SSL_get_shutdown(self->ssl) ==
			    SSL_RECEIVED_SHUTDOWN))
		{
			count = 0;
			goto done;
		} else {
			sockstate = SOCKET_OPERATION_OK;
		}
		if (sockstate == SOCKET_HAS_TIMED_OUT) {
			PyErr_SetString(PySSLErrorObject,
					"The read operation timed out");
			goto error;
		} else if (sockstate == SOCKET_IS_NONBLOCKING) {
			break;
		}
	} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
	if (count <= 0) {
		PySSL_SetError(self, count, __FILE__, __LINE__);
		goto error;
	}
  done:
	if (!buf_passed) {
		PyObject *res = PyBytes_FromStringAndSize(mem, count);
		Py_DECREF(dest);
		return res;
	} else {
		PyBuffer_Release(&buf);
		return PyLong_FromLong(count);
	}
  error:
	if (!buf_passed) {
		Py_DECREF(dest);
	} else {
		PyBuffer_Release(&buf);
	}
	return NULL;
}
Ejemplo n.º 4
0
static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args)
{
	char *data;
	int len;
	int count;
	int sockstate;
	int err;
        int nonblocking;
        PySocketSockObject *sock
          = (PySocketSockObject *) PyWeakref_GetObject(self->Socket);

        if (((PyObject*)sock) == Py_None) {
                _setSSLError("Underlying socket connection gone",
                             PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
                return NULL;
        }

	if (!PyArg_ParseTuple(args, "y#:write", &data, &count))
		return NULL;

        /* just in case the blocking state of the socket has been changed */
	nonblocking = (sock->sock_timeout >= 0.0);
        BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking);
        BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking);

	sockstate = check_socket_and_wait_for_timeout(sock, 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;
		PySSL_BEGIN_ALLOW_THREADS
		len = SSL_write(self->ssl, data, count);
		err = SSL_get_error(self->ssl, len);
		PySSL_END_ALLOW_THREADS
		if(PyErr_CheckSignals()) {
			return NULL;
		}
		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 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 PyLong_FromLong(len);
	else
		return PySSL_SetError(self, len, __FILE__, __LINE__);
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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;
}