| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 1 | /* SSL socket module  | 
 | 2 |  | 
 | 3 |    SSL support based on patches by Brian E Gallew and Laszlo Kovacs. | 
 | 4 |  | 
 | 5 |    This module is imported by socket.py. It should *not* be used | 
 | 6 |    directly. | 
 | 7 |  | 
 | 8 | */ | 
 | 9 |  | 
 | 10 | #include "Python.h" | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 11 | enum py_ssl_error { | 
 | 12 | 	/* these mirror ssl.h */ | 
 | 13 | 	PY_SSL_ERROR_NONE,                  | 
 | 14 | 	PY_SSL_ERROR_SSL,                    | 
 | 15 | 	PY_SSL_ERROR_WANT_READ,              | 
 | 16 | 	PY_SSL_ERROR_WANT_WRITE,             | 
 | 17 | 	PY_SSL_ERROR_WANT_X509_LOOKUP,       | 
 | 18 | 	PY_SSL_ERROR_SYSCALL,     /* look at error stack/return value/errno */ | 
 | 19 | 	PY_SSL_ERROR_ZERO_RETURN,            | 
 | 20 | 	PY_SSL_ERROR_WANT_CONNECT, | 
 | 21 | 	/* start of non ssl.h errorcodes */  | 
 | 22 | 	PY_SSL_ERROR_EOF,         /* special case of SSL_ERROR_SYSCALL */ | 
 | 23 | 	PY_SSL_ERROR_INVALID_ERROR_CODE | 
 | 24 | }; | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 25 |  | 
 | 26 | /* Include symbols from _socket module */ | 
 | 27 | #include "socketmodule.h" | 
 | 28 |  | 
 | 29 | /* Include OpenSSL header files */ | 
 | 30 | #include "openssl/rsa.h" | 
 | 31 | #include "openssl/crypto.h" | 
 | 32 | #include "openssl/x509.h" | 
 | 33 | #include "openssl/pem.h" | 
 | 34 | #include "openssl/ssl.h" | 
 | 35 | #include "openssl/err.h" | 
 | 36 | #include "openssl/rand.h" | 
 | 37 |  | 
 | 38 | /* SSL error object */ | 
 | 39 | static PyObject *PySSLErrorObject; | 
 | 40 |  | 
 | 41 | /* SSL socket object */ | 
 | 42 |  | 
 | 43 | #define X509_NAME_MAXLEN 256 | 
 | 44 |  | 
 | 45 | /* RAND_* APIs got added to OpenSSL in 0.9.5 */ | 
 | 46 | #if OPENSSL_VERSION_NUMBER >= 0x0090500fL | 
 | 47 | # define HAVE_OPENSSL_RAND 1 | 
 | 48 | #else | 
 | 49 | # undef HAVE_OPENSSL_RAND | 
 | 50 | #endif | 
 | 51 |  | 
 | 52 | typedef struct { | 
 | 53 | 	PyObject_HEAD | 
 | 54 | 	PySocketSockObject *Socket;	/* Socket on which we're layered */ | 
 | 55 | 	SSL_CTX* 	ctx; | 
 | 56 | 	SSL*     	ssl; | 
 | 57 | 	X509*    	server_cert; | 
 | 58 | 	BIO*		sbio; | 
 | 59 | 	char    	server[X509_NAME_MAXLEN]; | 
 | 60 | 	char		issuer[X509_NAME_MAXLEN]; | 
 | 61 |  | 
 | 62 | } PySSLObject; | 
 | 63 |  | 
| Jeremy Hylton | 938ace6 | 2002-07-17 16:30:39 +0000 | [diff] [blame] | 64 | static PyTypeObject PySSL_Type; | 
 | 65 | static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args); | 
 | 66 | static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args); | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 67 | static int check_socket_and_wait_for_timeout(PySocketSockObject *s,  | 
 | 68 | 					     int writing); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 69 |  | 
 | 70 | #define PySSLObject_Check(v)	((v)->ob_type == &PySSL_Type) | 
 | 71 |  | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 72 | typedef enum { | 
 | 73 | 	SOCKET_IS_NONBLOCKING, | 
 | 74 | 	SOCKET_IS_BLOCKING, | 
 | 75 | 	SOCKET_HAS_TIMED_OUT, | 
 | 76 | 	SOCKET_HAS_BEEN_CLOSED, | 
 | 77 | 	SOCKET_OPERATION_OK | 
 | 78 | } timeout_state; | 
 | 79 |  | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 80 | /* XXX It might be helpful to augment the error message generated | 
 | 81 |    below with the name of the SSL function that generated the error. | 
 | 82 |    I expect it's obvious most of the time. | 
 | 83 | */ | 
 | 84 |  | 
 | 85 | static PyObject * | 
 | 86 | PySSL_SetError(PySSLObject *obj, int ret) | 
 | 87 | { | 
 | 88 | 	PyObject *v, *n, *s; | 
 | 89 | 	char *errstr; | 
 | 90 | 	int err; | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 91 | 	enum py_ssl_error p; | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 92 |  | 
 | 93 | 	assert(ret <= 0); | 
 | 94 |      | 
 | 95 | 	err = SSL_get_error(obj->ssl, ret); | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 96 |  | 
 | 97 | 	switch (err) { | 
 | 98 | 	case SSL_ERROR_ZERO_RETURN: | 
 | 99 | 		errstr = "TLS/SSL connection has been closed"; | 
| Jeremy Hylton | 4e54730 | 2002-07-02 18:25:00 +0000 | [diff] [blame] | 100 | 		p = PY_SSL_ERROR_ZERO_RETURN; | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 101 | 		break; | 
 | 102 | 	case SSL_ERROR_WANT_READ: | 
 | 103 | 		errstr = "The operation did not complete (read)"; | 
| Jeremy Hylton | 4e54730 | 2002-07-02 18:25:00 +0000 | [diff] [blame] | 104 | 		p = PY_SSL_ERROR_WANT_READ; | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 105 | 		break; | 
 | 106 | 	case SSL_ERROR_WANT_WRITE: | 
| Jeremy Hylton | 4e54730 | 2002-07-02 18:25:00 +0000 | [diff] [blame] | 107 | 		p = PY_SSL_ERROR_WANT_WRITE; | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 108 | 		errstr = "The operation did not complete (write)"; | 
 | 109 | 		break; | 
 | 110 | 	case SSL_ERROR_WANT_X509_LOOKUP: | 
| Jeremy Hylton | 4e54730 | 2002-07-02 18:25:00 +0000 | [diff] [blame] | 111 | 		p = PY_SSL_ERROR_WANT_X509_LOOKUP; | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 112 | 		errstr = "The operation did not complete (X509 lookup)"; | 
 | 113 | 		break; | 
 | 114 | 	case SSL_ERROR_WANT_CONNECT: | 
| Jeremy Hylton | 4e54730 | 2002-07-02 18:25:00 +0000 | [diff] [blame] | 115 | 		p = PY_SSL_ERROR_WANT_CONNECT; | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 116 | 		errstr = "The operation did not complete (connect)"; | 
 | 117 | 		break; | 
 | 118 | 	case SSL_ERROR_SYSCALL: | 
 | 119 | 	{ | 
 | 120 | 		unsigned long e = ERR_get_error(); | 
| Jeremy Hylton | 4e54730 | 2002-07-02 18:25:00 +0000 | [diff] [blame] | 121 | 		if (e == 0) { | 
| Neal Norwitz | a9002f8 | 2003-06-30 03:25:20 +0000 | [diff] [blame] | 122 | 			if (ret == 0 || !obj->Socket) { | 
| Jeremy Hylton | 4e54730 | 2002-07-02 18:25:00 +0000 | [diff] [blame] | 123 | 				p = PY_SSL_ERROR_EOF; | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 124 | 				errstr = "EOF occurred in violation of protocol"; | 
| Jeremy Hylton | 4e54730 | 2002-07-02 18:25:00 +0000 | [diff] [blame] | 125 | 			} else if (ret == -1) { | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 126 | 				/* the underlying BIO reported an I/O error */ | 
 | 127 | 				return obj->Socket->errorhandler(); | 
| Jeremy Hylton | 4e54730 | 2002-07-02 18:25:00 +0000 | [diff] [blame] | 128 | 			} else {  /* possible? */ | 
 | 129 | 				p = PY_SSL_ERROR_SYSCALL; | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 130 | 				errstr = "Some I/O error occurred"; | 
 | 131 | 			} | 
 | 132 | 		} else { | 
| Jeremy Hylton | 4e54730 | 2002-07-02 18:25:00 +0000 | [diff] [blame] | 133 | 			p = PY_SSL_ERROR_SYSCALL; | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 134 | 			/* XXX Protected by global interpreter lock */ | 
 | 135 | 			errstr = ERR_error_string(e, NULL); | 
 | 136 | 		} | 
 | 137 | 		break; | 
 | 138 | 	}    | 
 | 139 | 	case SSL_ERROR_SSL: | 
 | 140 | 	{ | 
 | 141 | 		unsigned long e = ERR_get_error(); | 
| Jeremy Hylton | 4e54730 | 2002-07-02 18:25:00 +0000 | [diff] [blame] | 142 | 		p = PY_SSL_ERROR_SSL; | 
 | 143 | 		if (e != 0)  | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 144 | 			/* XXX Protected by global interpreter lock */ | 
 | 145 | 			errstr = ERR_error_string(e, NULL); | 
| Jeremy Hylton | 4e54730 | 2002-07-02 18:25:00 +0000 | [diff] [blame] | 146 | 		else { /* possible? */ | 
 | 147 | 			errstr = "A failure in the SSL library occurred"; | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 148 | 		} | 
 | 149 | 		break; | 
 | 150 | 	} | 
 | 151 | 	default: | 
| Jeremy Hylton | 4e54730 | 2002-07-02 18:25:00 +0000 | [diff] [blame] | 152 | 		p = PY_SSL_ERROR_INVALID_ERROR_CODE; | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 153 | 		errstr = "Invalid error code"; | 
 | 154 | 	} | 
 | 155 | 	n = PyInt_FromLong((long) p); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 156 | 	if (n == NULL) | 
 | 157 | 		return NULL; | 
 | 158 | 	v = PyTuple_New(2); | 
 | 159 | 	if (v == NULL) { | 
 | 160 | 		Py_DECREF(n); | 
 | 161 | 		return NULL; | 
 | 162 | 	} | 
 | 163 |  | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 164 | 	s = PyString_FromString(errstr); | 
 | 165 | 	if (s == NULL) { | 
 | 166 | 		Py_DECREF(v); | 
 | 167 | 		Py_DECREF(n); | 
 | 168 | 	} | 
 | 169 | 	PyTuple_SET_ITEM(v, 0, n); | 
 | 170 | 	PyTuple_SET_ITEM(v, 1, s); | 
 | 171 | 	PyErr_SetObject(PySSLErrorObject, v); | 
| Michael W. Hudson | 5910d81 | 2004-08-04 14:59:00 +0000 | [diff] [blame] | 172 | 	Py_DECREF(v); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 173 | 	return NULL; | 
 | 174 | } | 
 | 175 |  | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 176 | static PySSLObject * | 
 | 177 | newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file) | 
 | 178 | { | 
 | 179 | 	PySSLObject *self; | 
 | 180 | 	char *errstr = NULL; | 
 | 181 | 	int ret; | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 182 | 	int err; | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 183 | 	int sockstate; | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 184 |  | 
 | 185 | 	self = PyObject_New(PySSLObject, &PySSL_Type); /* Create new object */ | 
 | 186 | 	if (self == NULL){ | 
 | 187 | 		errstr = "newPySSLObject error"; | 
 | 188 | 		goto fail; | 
 | 189 | 	} | 
 | 190 | 	memset(self->server, '\0', sizeof(char) * X509_NAME_MAXLEN); | 
 | 191 | 	memset(self->issuer, '\0', sizeof(char) * X509_NAME_MAXLEN); | 
 | 192 | 	self->server_cert = NULL; | 
 | 193 | 	self->ssl = NULL; | 
 | 194 | 	self->ctx = NULL; | 
 | 195 | 	self->Socket = NULL; | 
 | 196 |  | 
 | 197 | 	if ((key_file && !cert_file) || (!key_file && cert_file)) { | 
 | 198 | 		errstr = "Both the key & certificate files must be specified"; | 
 | 199 | 		goto fail; | 
 | 200 | 	} | 
 | 201 |  | 
| Martin v. Löwis | 09c35f7 | 2002-07-28 09:57:45 +0000 | [diff] [blame] | 202 | 	Py_BEGIN_ALLOW_THREADS | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 203 | 	self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */ | 
| Martin v. Löwis | 09c35f7 | 2002-07-28 09:57:45 +0000 | [diff] [blame] | 204 | 	Py_END_ALLOW_THREADS | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 205 | 	if (self->ctx == NULL) { | 
 | 206 | 		errstr = "SSL_CTX_new error"; | 
 | 207 | 		goto fail; | 
 | 208 | 	} | 
 | 209 |  | 
 | 210 | 	if (key_file) { | 
| Martin v. Löwis | 09c35f7 | 2002-07-28 09:57:45 +0000 | [diff] [blame] | 211 | 		Py_BEGIN_ALLOW_THREADS | 
 | 212 | 		ret = SSL_CTX_use_PrivateKey_file(self->ctx, key_file, | 
 | 213 | 						SSL_FILETYPE_PEM); | 
 | 214 | 		Py_END_ALLOW_THREADS | 
 | 215 | 		if (ret < 1) { | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 216 | 			errstr = "SSL_CTX_use_PrivateKey_file error"; | 
 | 217 | 			goto fail; | 
 | 218 | 		} | 
 | 219 |  | 
| Martin v. Löwis | 09c35f7 | 2002-07-28 09:57:45 +0000 | [diff] [blame] | 220 | 		Py_BEGIN_ALLOW_THREADS | 
 | 221 | 		ret = SSL_CTX_use_certificate_chain_file(self->ctx, | 
 | 222 | 						       cert_file); | 
 | 223 | 		Py_END_ALLOW_THREADS | 
| Andrew M. Kuchling | 27d3dda | 2004-07-10 21:36:55 +0000 | [diff] [blame] | 224 | 		SSL_CTX_set_options(self->ctx, SSL_OP_ALL); /* ssl compatibility */ | 
| Martin v. Löwis | 09c35f7 | 2002-07-28 09:57:45 +0000 | [diff] [blame] | 225 | 		if (ret < 1) { | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 226 | 			errstr = "SSL_CTX_use_certificate_chain_file error"; | 
 | 227 | 			goto fail; | 
 | 228 | 		} | 
 | 229 | 	} | 
 | 230 |  | 
| Martin v. Löwis | 09c35f7 | 2002-07-28 09:57:45 +0000 | [diff] [blame] | 231 | 	Py_BEGIN_ALLOW_THREADS | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 232 | 	SSL_CTX_set_verify(self->ctx, | 
 | 233 | 			   SSL_VERIFY_NONE, NULL); /* set verify lvl */ | 
 | 234 | 	self->ssl = SSL_new(self->ctx); /* New ssl struct */ | 
| Martin v. Löwis | 09c35f7 | 2002-07-28 09:57:45 +0000 | [diff] [blame] | 235 | 	Py_END_ALLOW_THREADS | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 236 | 	SSL_set_fd(self->ssl, Sock->sock_fd);	/* Set the socket for SSL */ | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 237 |  | 
| Walter Dörwald | f0dfc7a | 2003-10-20 14:01:56 +0000 | [diff] [blame] | 238 | 	/* If the socket is in non-blocking mode or timeout mode, set the BIO | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 239 | 	 * to non-blocking mode (blocking is the default) | 
 | 240 | 	 */ | 
 | 241 | 	if (Sock->sock_timeout >= 0.0) { | 
 | 242 | 		/* Set both the read and write BIO's to non-blocking mode */ | 
 | 243 | 		BIO_set_nbio(SSL_get_rbio(self->ssl), 1); | 
 | 244 | 		BIO_set_nbio(SSL_get_wbio(self->ssl), 1); | 
 | 245 | 	} | 
 | 246 |  | 
| Martin v. Löwis | 09c35f7 | 2002-07-28 09:57:45 +0000 | [diff] [blame] | 247 | 	Py_BEGIN_ALLOW_THREADS | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 248 | 	SSL_set_connect_state(self->ssl); | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 249 | 	Py_END_ALLOW_THREADS | 
| Martin v. Löwis | 09c35f7 | 2002-07-28 09:57:45 +0000 | [diff] [blame] | 250 |  | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 251 | 	/* Actually negotiate SSL connection */ | 
 | 252 | 	/* XXX If SSL_connect() returns 0, it's also a failure. */ | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 253 | 	sockstate = 0; | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 254 | 	do { | 
 | 255 | 		Py_BEGIN_ALLOW_THREADS | 
 | 256 | 		ret = SSL_connect(self->ssl); | 
 | 257 | 		err = SSL_get_error(self->ssl, ret); | 
 | 258 | 		Py_END_ALLOW_THREADS | 
| Martin v. Löwis | afec8e3 | 2003-06-28 07:40:23 +0000 | [diff] [blame] | 259 | 		if(PyErr_CheckSignals()) { | 
 | 260 |                         goto fail; | 
 | 261 | 		} | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 262 | 		if (err == SSL_ERROR_WANT_READ) { | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 263 | 			sockstate = check_socket_and_wait_for_timeout(Sock, 0); | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 264 | 		} else if (err == SSL_ERROR_WANT_WRITE) { | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 265 | 			sockstate = check_socket_and_wait_for_timeout(Sock, 1); | 
 | 266 | 		} else { | 
 | 267 | 			sockstate = SOCKET_OPERATION_OK; | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 268 | 		} | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 269 | 	    if (sockstate == SOCKET_HAS_TIMED_OUT) { | 
 | 270 | 			PyErr_SetString(PySSLErrorObject, "The connect operation timed out"); | 
| Martin v. Löwis | afec8e3 | 2003-06-28 07:40:23 +0000 | [diff] [blame] | 271 | 			goto fail; | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 272 | 		} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { | 
 | 273 | 			PyErr_SetString(PySSLErrorObject, "Underlying socket has been closed."); | 
 | 274 | 			goto fail; | 
 | 275 | 		} else if (sockstate == SOCKET_IS_NONBLOCKING) { | 
 | 276 | 			break; | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 277 | 		} | 
 | 278 | 	} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 279 | 	if (ret <= 0) { | 
 | 280 | 		PySSL_SetError(self, ret); | 
 | 281 | 		goto fail; | 
 | 282 | 	} | 
 | 283 | 	self->ssl->debug = 1; | 
 | 284 |  | 
| Martin v. Löwis | 09c35f7 | 2002-07-28 09:57:45 +0000 | [diff] [blame] | 285 | 	Py_BEGIN_ALLOW_THREADS | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 286 | 	if ((self->server_cert = SSL_get_peer_certificate(self->ssl))) { | 
 | 287 | 		X509_NAME_oneline(X509_get_subject_name(self->server_cert), | 
 | 288 | 				  self->server, X509_NAME_MAXLEN); | 
 | 289 | 		X509_NAME_oneline(X509_get_issuer_name(self->server_cert), | 
 | 290 | 				  self->issuer, X509_NAME_MAXLEN); | 
 | 291 | 	} | 
| Martin v. Löwis | 09c35f7 | 2002-07-28 09:57:45 +0000 | [diff] [blame] | 292 | 	Py_END_ALLOW_THREADS | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 293 | 	self->Socket = Sock; | 
 | 294 | 	Py_INCREF(self->Socket); | 
 | 295 | 	return self; | 
 | 296 |  fail: | 
 | 297 | 	if (errstr) | 
 | 298 | 		PyErr_SetString(PySSLErrorObject, errstr); | 
 | 299 | 	Py_DECREF(self); | 
 | 300 | 	return NULL; | 
 | 301 | } | 
 | 302 |  | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 303 | static PyObject * | 
 | 304 | PySocket_ssl(PyObject *self, PyObject *args) | 
 | 305 | { | 
 | 306 | 	PySSLObject *rv; | 
 | 307 | 	PySocketSockObject *Sock; | 
 | 308 | 	char *key_file = NULL; | 
 | 309 | 	char *cert_file = NULL; | 
 | 310 |  | 
 | 311 | 	if (!PyArg_ParseTuple(args, "O!|zz:ssl", | 
 | 312 | 			      PySocketModule.Sock_Type, | 
 | 313 | 			      (PyObject*)&Sock, | 
 | 314 | 			      &key_file, &cert_file)) | 
 | 315 | 		return NULL; | 
 | 316 |  | 
 | 317 | 	rv = newPySSLObject(Sock, key_file, cert_file); | 
 | 318 | 	if (rv == NULL) | 
 | 319 | 		return NULL; | 
 | 320 | 	return (PyObject *)rv; | 
 | 321 | } | 
 | 322 |  | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 323 | PyDoc_STRVAR(ssl_doc, | 
 | 324 | "ssl(socket, [keyfile, certfile]) -> sslobject"); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 325 |  | 
 | 326 | /* SSL object methods */ | 
 | 327 |  | 
 | 328 | static PyObject * | 
 | 329 | PySSL_server(PySSLObject *self) | 
 | 330 | { | 
 | 331 | 	return PyString_FromString(self->server); | 
 | 332 | } | 
 | 333 |  | 
 | 334 | static PyObject * | 
 | 335 | PySSL_issuer(PySSLObject *self) | 
 | 336 | { | 
 | 337 | 	return PyString_FromString(self->issuer); | 
 | 338 | } | 
 | 339 |  | 
 | 340 |  | 
 | 341 | static void PySSL_dealloc(PySSLObject *self) | 
 | 342 | { | 
 | 343 | 	if (self->server_cert)	/* Possible not to have one? */ | 
 | 344 | 		X509_free (self->server_cert); | 
 | 345 | 	if (self->ssl) | 
 | 346 | 	    SSL_free(self->ssl); | 
 | 347 | 	if (self->ctx) | 
 | 348 | 	    SSL_CTX_free(self->ctx); | 
 | 349 | 	Py_XDECREF(self->Socket); | 
 | 350 | 	PyObject_Del(self); | 
 | 351 | } | 
 | 352 |  | 
| Guido van Rossum | 99d4abf | 2003-01-27 22:22:50 +0000 | [diff] [blame] | 353 | /* If the socket has a timeout, do a select() on the socket. | 
 | 354 |    The argument writing indicates the direction. | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 355 |    Returns one of the possibilities in the timeout_state enum (above). | 
| Guido van Rossum | 99d4abf | 2003-01-27 22:22:50 +0000 | [diff] [blame] | 356 |  */ | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 357 |  | 
| Guido van Rossum | 99d4abf | 2003-01-27 22:22:50 +0000 | [diff] [blame] | 358 | static int | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 359 | check_socket_and_wait_for_timeout(PySocketSockObject *s, int writing) | 
| Guido van Rossum | 99d4abf | 2003-01-27 22:22:50 +0000 | [diff] [blame] | 360 | { | 
 | 361 | 	fd_set fds; | 
 | 362 | 	struct timeval tv; | 
 | 363 | 	int rc; | 
 | 364 |  | 
 | 365 | 	/* Nothing to do unless we're in timeout mode (not non-blocking) */ | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 366 | 	if (s->sock_timeout < 0.0) | 
 | 367 | 		return SOCKET_IS_BLOCKING; | 
 | 368 | 	else if (s->sock_timeout == 0.0) | 
 | 369 | 		return SOCKET_IS_NONBLOCKING; | 
| Guido van Rossum | 99d4abf | 2003-01-27 22:22:50 +0000 | [diff] [blame] | 370 |  | 
 | 371 | 	/* Guard against closed socket */ | 
 | 372 | 	if (s->sock_fd < 0) | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 373 | 		return SOCKET_HAS_BEEN_CLOSED; | 
| Guido van Rossum | 99d4abf | 2003-01-27 22:22:50 +0000 | [diff] [blame] | 374 |  | 
 | 375 | 	/* Construct the arguments to select */ | 
 | 376 | 	tv.tv_sec = (int)s->sock_timeout; | 
 | 377 | 	tv.tv_usec = (int)((s->sock_timeout - tv.tv_sec) * 1e6); | 
 | 378 | 	FD_ZERO(&fds); | 
 | 379 | 	FD_SET(s->sock_fd, &fds); | 
 | 380 |  | 
 | 381 | 	/* See if the socket is ready */ | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 382 | 	Py_BEGIN_ALLOW_THREADS | 
| Guido van Rossum | 99d4abf | 2003-01-27 22:22:50 +0000 | [diff] [blame] | 383 | 	if (writing) | 
 | 384 | 		rc = select(s->sock_fd+1, NULL, &fds, NULL, &tv); | 
 | 385 | 	else | 
 | 386 | 		rc = select(s->sock_fd+1, &fds, NULL, NULL, &tv); | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 387 | 	Py_END_ALLOW_THREADS | 
| Guido van Rossum | 99d4abf | 2003-01-27 22:22:50 +0000 | [diff] [blame] | 388 |  | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 389 | 	/* Return SOCKET_TIMED_OUT on timeout, SOCKET_OPERATION_OK otherwise | 
 | 390 | 	   (when we are able to write or when there's something to read) */ | 
 | 391 | 	return rc == 0 ? SOCKET_HAS_TIMED_OUT : SOCKET_OPERATION_OK; | 
| Guido van Rossum | 99d4abf | 2003-01-27 22:22:50 +0000 | [diff] [blame] | 392 | } | 
 | 393 |  | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 394 | static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args) | 
 | 395 | { | 
 | 396 | 	char *data; | 
 | 397 | 	int len; | 
| Martin v. Löwis | 405a795 | 2003-10-27 14:24:37 +0000 | [diff] [blame] | 398 | 	int count; | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 399 | 	int sockstate; | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 400 | 	int err; | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 401 |  | 
| Martin v. Löwis | 405a795 | 2003-10-27 14:24:37 +0000 | [diff] [blame] | 402 | 	if (!PyArg_ParseTuple(args, "s#:write", &data, &count)) | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 403 | 		return NULL; | 
 | 404 |  | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 405 | 	sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); | 
 | 406 | 	if (sockstate == SOCKET_HAS_TIMED_OUT) { | 
| Guido van Rossum | 99d4abf | 2003-01-27 22:22:50 +0000 | [diff] [blame] | 407 | 		PyErr_SetString(PySSLErrorObject, "The write operation timed out"); | 
 | 408 | 		return NULL; | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 409 | 	} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { | 
 | 410 | 		PyErr_SetString(PySSLErrorObject, "Underlying socket has been closed."); | 
 | 411 | 		return NULL; | 
| Guido van Rossum | 99d4abf | 2003-01-27 22:22:50 +0000 | [diff] [blame] | 412 | 	} | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 413 | 	do { | 
 | 414 | 		err = 0; | 
 | 415 | 		Py_BEGIN_ALLOW_THREADS | 
| Martin v. Löwis | 405a795 | 2003-10-27 14:24:37 +0000 | [diff] [blame] | 416 | 		len = SSL_write(self->ssl, data, count); | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 417 | 		err = SSL_get_error(self->ssl, len); | 
 | 418 | 		Py_END_ALLOW_THREADS | 
| Martin v. Löwis | afec8e3 | 2003-06-28 07:40:23 +0000 | [diff] [blame] | 419 | 		if(PyErr_CheckSignals()) { | 
 | 420 | 			return NULL; | 
 | 421 | 		} | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 422 | 		if (err == SSL_ERROR_WANT_READ) { | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 423 | 			sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 424 | 		} else if (err == SSL_ERROR_WANT_WRITE) { | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 425 | 			sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); | 
 | 426 | 		} else { | 
 | 427 | 			sockstate = SOCKET_OPERATION_OK; | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 428 | 		} | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 429 | 	    if (sockstate == SOCKET_HAS_TIMED_OUT) { | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 430 | 			PyErr_SetString(PySSLErrorObject, "The write operation timed out"); | 
 | 431 | 			return NULL; | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 432 | 		} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { | 
 | 433 | 			PyErr_SetString(PySSLErrorObject, "Underlying socket has been closed."); | 
 | 434 | 			return NULL; | 
 | 435 | 		} else if (sockstate == SOCKET_IS_NONBLOCKING) { | 
 | 436 | 			break; | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 437 | 		} | 
 | 438 | 	} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 439 | 	if (len > 0) | 
 | 440 | 		return PyInt_FromLong(len); | 
 | 441 | 	else | 
 | 442 | 		return PySSL_SetError(self, len); | 
 | 443 | } | 
 | 444 |  | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 445 | PyDoc_STRVAR(PySSL_SSLwrite_doc, | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 446 | "write(s) -> len\n\ | 
 | 447 | \n\ | 
 | 448 | Writes the string s into the SSL object.  Returns the number\n\ | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 449 | of bytes written."); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 450 |  | 
 | 451 | static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args) | 
 | 452 | { | 
 | 453 | 	PyObject *buf; | 
 | 454 | 	int count = 0; | 
 | 455 | 	int len = 1024; | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 456 | 	int sockstate; | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 457 | 	int err; | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 458 |  | 
 | 459 | 	if (!PyArg_ParseTuple(args, "|i:read", &len)) | 
 | 460 | 		return NULL; | 
 | 461 |  | 
 | 462 | 	if (!(buf = PyString_FromStringAndSize((char *) 0, len))) | 
 | 463 | 		return NULL; | 
 | 464 |  | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 465 | 	sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); | 
 | 466 | 	if (sockstate == SOCKET_HAS_TIMED_OUT) { | 
| Guido van Rossum | 99d4abf | 2003-01-27 22:22:50 +0000 | [diff] [blame] | 467 | 		PyErr_SetString(PySSLErrorObject, "The read operation timed out"); | 
| Neal Norwitz | a9002f8 | 2003-06-30 03:25:20 +0000 | [diff] [blame] | 468 | 		Py_DECREF(buf); | 
| Guido van Rossum | 99d4abf | 2003-01-27 22:22:50 +0000 | [diff] [blame] | 469 | 		return NULL; | 
 | 470 | 	} | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 471 | 	do { | 
 | 472 | 		err = 0; | 
 | 473 | 		Py_BEGIN_ALLOW_THREADS | 
 | 474 | 		count = SSL_read(self->ssl, PyString_AsString(buf), len); | 
 | 475 | 		err = SSL_get_error(self->ssl, count); | 
 | 476 | 		Py_END_ALLOW_THREADS | 
| Martin v. Löwis | afec8e3 | 2003-06-28 07:40:23 +0000 | [diff] [blame] | 477 | 		if(PyErr_CheckSignals()) { | 
 | 478 | 			Py_DECREF(buf); | 
 | 479 | 			return NULL; | 
 | 480 | 		} | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 481 | 		if (err == SSL_ERROR_WANT_READ) { | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 482 | 			sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 483 | 		} else if (err == SSL_ERROR_WANT_WRITE) { | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 484 | 			sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); | 
 | 485 | 		} else { | 
 | 486 | 			sockstate = SOCKET_OPERATION_OK; | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 487 | 		} | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 488 | 	    if (sockstate == SOCKET_HAS_TIMED_OUT) { | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 489 | 			PyErr_SetString(PySSLErrorObject, "The read operation timed out"); | 
| Martin v. Löwis | afec8e3 | 2003-06-28 07:40:23 +0000 | [diff] [blame] | 490 | 			Py_DECREF(buf); | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 491 | 			return NULL; | 
| Andrew M. Kuchling | 9c3efe3 | 2004-07-10 21:15:17 +0000 | [diff] [blame] | 492 | 		} else if (sockstate == SOCKET_IS_NONBLOCKING) { | 
 | 493 | 			break; | 
| Guido van Rossum | 4f707ac | 2003-01-31 18:13:18 +0000 | [diff] [blame] | 494 | 		} | 
 | 495 | 	} while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 496 |  	if (count <= 0) { | 
 | 497 | 		Py_DECREF(buf); | 
 | 498 | 		return PySSL_SetError(self, count); | 
 | 499 | 	} | 
| Tim Peters | 5de9842 | 2002-04-27 18:44:32 +0000 | [diff] [blame] | 500 | 	if (count != len) | 
 | 501 | 		_PyString_Resize(&buf, count); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 502 | 	return buf; | 
 | 503 | } | 
 | 504 |  | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 505 | PyDoc_STRVAR(PySSL_SSLread_doc, | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 506 | "read([len]) -> string\n\ | 
 | 507 | \n\ | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 508 | Read up to len bytes from the SSL socket."); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 509 |  | 
 | 510 | static PyMethodDef PySSLMethods[] = { | 
 | 511 | 	{"write", (PyCFunction)PySSL_SSLwrite, METH_VARARGS, | 
 | 512 | 	          PySSL_SSLwrite_doc}, | 
 | 513 | 	{"read", (PyCFunction)PySSL_SSLread, METH_VARARGS, | 
 | 514 | 	          PySSL_SSLread_doc}, | 
 | 515 | 	{"server", (PyCFunction)PySSL_server, METH_NOARGS}, | 
 | 516 | 	{"issuer", (PyCFunction)PySSL_issuer, METH_NOARGS}, | 
 | 517 | 	{NULL, NULL} | 
 | 518 | }; | 
 | 519 |  | 
 | 520 | static PyObject *PySSL_getattr(PySSLObject *self, char *name) | 
 | 521 | { | 
 | 522 | 	return Py_FindMethod(PySSLMethods, (PyObject *)self, name); | 
 | 523 | } | 
 | 524 |  | 
| Jeremy Hylton | 938ace6 | 2002-07-17 16:30:39 +0000 | [diff] [blame] | 525 | static PyTypeObject PySSL_Type = { | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 526 | 	PyObject_HEAD_INIT(NULL) | 
 | 527 | 	0,				/*ob_size*/ | 
 | 528 | 	"socket.SSL",			/*tp_name*/ | 
 | 529 | 	sizeof(PySSLObject),		/*tp_basicsize*/ | 
 | 530 | 	0,				/*tp_itemsize*/ | 
 | 531 | 	/* methods */ | 
 | 532 | 	(destructor)PySSL_dealloc,	/*tp_dealloc*/ | 
 | 533 | 	0,				/*tp_print*/ | 
 | 534 | 	(getattrfunc)PySSL_getattr,	/*tp_getattr*/ | 
 | 535 | 	0,				/*tp_setattr*/ | 
 | 536 | 	0,				/*tp_compare*/ | 
 | 537 | 	0,				/*tp_repr*/ | 
 | 538 | 	0,				/*tp_as_number*/ | 
 | 539 | 	0,				/*tp_as_sequence*/ | 
 | 540 | 	0,				/*tp_as_mapping*/ | 
 | 541 | 	0,				/*tp_hash*/ | 
 | 542 | }; | 
 | 543 |  | 
 | 544 | #ifdef HAVE_OPENSSL_RAND | 
 | 545 |  | 
 | 546 | /* helper routines for seeding the SSL PRNG */ | 
 | 547 | static PyObject * | 
 | 548 | PySSL_RAND_add(PyObject *self, PyObject *args) | 
 | 549 | { | 
 | 550 |     char *buf; | 
 | 551 |     int len; | 
 | 552 |     double entropy; | 
 | 553 |  | 
 | 554 |     if (!PyArg_ParseTuple(args, "s#d:RAND_add", &buf, &len, &entropy)) | 
 | 555 | 	return NULL; | 
 | 556 |     RAND_add(buf, len, entropy); | 
 | 557 |     Py_INCREF(Py_None); | 
 | 558 |     return Py_None; | 
 | 559 | } | 
 | 560 |  | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 561 | PyDoc_STRVAR(PySSL_RAND_add_doc, | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 562 | "RAND_add(string, entropy)\n\ | 
 | 563 | \n\ | 
 | 564 | Mix string into the OpenSSL PRNG state.  entropy (a float) is a lower\n\ | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 565 | bound on the entropy contained in string."); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 566 |  | 
 | 567 | static PyObject * | 
 | 568 | PySSL_RAND_status(PyObject *self) | 
 | 569 | { | 
 | 570 |     return PyInt_FromLong(RAND_status()); | 
 | 571 | } | 
 | 572 |  | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 573 | PyDoc_STRVAR(PySSL_RAND_status_doc, | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 574 | "RAND_status() -> 0 or 1\n\ | 
 | 575 | \n\ | 
 | 576 | Returns 1 if the OpenSSL PRNG has been seeded with enough data and 0 if not.\n\ | 
 | 577 | It is necessary to seed the PRNG with RAND_add() on some platforms before\n\ | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 578 | using the ssl() function."); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 579 |  | 
 | 580 | static PyObject * | 
 | 581 | PySSL_RAND_egd(PyObject *self, PyObject *arg) | 
 | 582 | { | 
 | 583 |     int bytes; | 
 | 584 |  | 
 | 585 |     if (!PyString_Check(arg)) | 
 | 586 | 	return PyErr_Format(PyExc_TypeError, | 
 | 587 | 			    "RAND_egd() expected string, found %s", | 
 | 588 | 			    arg->ob_type->tp_name); | 
 | 589 |     bytes = RAND_egd(PyString_AS_STRING(arg)); | 
 | 590 |     if (bytes == -1) { | 
 | 591 | 	PyErr_SetString(PySSLErrorObject, | 
 | 592 | 			"EGD connection failed or EGD did not return " | 
 | 593 | 			"enough data to seed the PRNG"); | 
 | 594 | 	return NULL; | 
 | 595 |     } | 
 | 596 |     return PyInt_FromLong(bytes); | 
 | 597 | } | 
 | 598 |  | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 599 | PyDoc_STRVAR(PySSL_RAND_egd_doc, | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 600 | "RAND_egd(path) -> bytes\n\ | 
 | 601 | \n\ | 
 | 602 | Queries the entropy gather daemon (EGD) on socket path.  Returns number\n\ | 
 | 603 | of bytes read.  Raises socket.sslerror if connection to EGD fails or\n\ | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 604 | if it does provide enough data to seed PRNG."); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 605 |  | 
 | 606 | #endif | 
 | 607 |  | 
 | 608 | /* List of functions exported by this module. */ | 
 | 609 |  | 
 | 610 | static PyMethodDef PySSL_methods[] = { | 
 | 611 | 	{"ssl",			PySocket_ssl, | 
 | 612 | 	 METH_VARARGS, ssl_doc}, | 
 | 613 | #ifdef HAVE_OPENSSL_RAND | 
 | 614 | 	{"RAND_add",            PySSL_RAND_add, METH_VARARGS,  | 
 | 615 | 	 PySSL_RAND_add_doc}, | 
 | 616 | 	{"RAND_egd",            PySSL_RAND_egd, METH_O, | 
 | 617 | 	 PySSL_RAND_egd_doc}, | 
 | 618 | 	{"RAND_status",         (PyCFunction)PySSL_RAND_status, METH_NOARGS, | 
 | 619 | 	 PySSL_RAND_status_doc}, | 
 | 620 | #endif | 
 | 621 | 	{NULL,			NULL}		 /* Sentinel */ | 
 | 622 | }; | 
 | 623 |  | 
 | 624 |  | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 625 | PyDoc_STRVAR(module_doc, | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 626 | "Implementation module for SSL socket operations.  See the socket module\n\ | 
| Martin v. Löwis | 14f8b4c | 2002-06-13 20:33:02 +0000 | [diff] [blame] | 627 | for documentation."); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 628 |  | 
| Mark Hammond | fe51c6d | 2002-08-02 02:27:13 +0000 | [diff] [blame] | 629 | PyMODINIT_FUNC | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 630 | init_ssl(void) | 
 | 631 | { | 
 | 632 | 	PyObject *m, *d; | 
 | 633 |  | 
 | 634 | 	PySSL_Type.ob_type = &PyType_Type; | 
 | 635 |  | 
 | 636 | 	m = Py_InitModule3("_ssl", PySSL_methods, module_doc); | 
 | 637 | 	d = PyModule_GetDict(m); | 
 | 638 |  | 
 | 639 | 	/* Load _socket module and its C API */ | 
 | 640 | 	if (PySocketModule_ImportModuleAndAPI()) | 
 | 641 |  	    	return; | 
 | 642 |  | 
 | 643 | 	/* Init OpenSSL */ | 
 | 644 | 	SSL_load_error_strings(); | 
 | 645 | 	SSLeay_add_ssl_algorithms(); | 
 | 646 |  | 
 | 647 | 	/* Add symbols to module dict */ | 
| Brett Cannon | 06c3479 | 2004-03-23 23:16:54 +0000 | [diff] [blame] | 648 | 	PySSLErrorObject = PyErr_NewException("socket.sslerror", | 
 | 649 |                                                PySocketModule.error, | 
 | 650 |                                                NULL); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 651 | 	if (PySSLErrorObject == NULL) | 
 | 652 | 		return; | 
 | 653 | 	PyDict_SetItemString(d, "sslerror", PySSLErrorObject); | 
 | 654 | 	if (PyDict_SetItemString(d, "SSLType", | 
 | 655 | 				 (PyObject *)&PySSL_Type) != 0) | 
 | 656 | 		return; | 
 | 657 | 	PyModule_AddIntConstant(m, "SSL_ERROR_ZERO_RETURN", | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 658 | 				PY_SSL_ERROR_ZERO_RETURN); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 659 | 	PyModule_AddIntConstant(m, "SSL_ERROR_WANT_READ", | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 660 | 				PY_SSL_ERROR_WANT_READ); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 661 | 	PyModule_AddIntConstant(m, "SSL_ERROR_WANT_WRITE", | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 662 | 				PY_SSL_ERROR_WANT_WRITE); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 663 | 	PyModule_AddIntConstant(m, "SSL_ERROR_WANT_X509_LOOKUP", | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 664 | 				PY_SSL_ERROR_WANT_X509_LOOKUP); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 665 | 	PyModule_AddIntConstant(m, "SSL_ERROR_SYSCALL", | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 666 | 				PY_SSL_ERROR_SYSCALL); | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 667 | 	PyModule_AddIntConstant(m, "SSL_ERROR_SSL", | 
| Martin v. Löwis | 6af3e2d | 2002-04-20 07:47:40 +0000 | [diff] [blame] | 668 | 				PY_SSL_ERROR_SSL); | 
 | 669 | 	PyModule_AddIntConstant(m, "SSL_ERROR_WANT_CONNECT", | 
 | 670 | 				PY_SSL_ERROR_WANT_CONNECT); | 
 | 671 | 	/* non ssl.h errorcodes */ | 
 | 672 | 	PyModule_AddIntConstant(m, "SSL_ERROR_EOF", | 
 | 673 | 				PY_SSL_ERROR_EOF); | 
 | 674 | 	PyModule_AddIntConstant(m, "SSL_ERROR_INVALID_ERROR_CODE", | 
 | 675 | 				PY_SSL_ERROR_INVALID_ERROR_CODE); | 
 | 676 |  | 
| Marc-André Lemburg | a5d2b4c | 2002-02-16 18:23:30 +0000 | [diff] [blame] | 677 | } |