SSL EOF
Ng Pheng Siong
ngps at madcap.dyndns.org
Thu Feb 1 12:05:00 EST 2001
According to Clarence Gardner <clarence at netlojix.com>:
> Here is the relevant code. I don't know what error==6 signifies, but even
> if the other side closed improperly, I don't think that's so significant as to
> warrant making these sockets behave differently from non-ssl ones.
>
> count = SSL_read(self->ssl, PyString_AsString(buf), len);
> res = SSL_get_error(self->ssl, count);
>
> switch (res) {
> case 0: /* Good return value! */
> break;
> case 6:
> PyErr_SetString(SSLErrorObject, "EOF");
> Py_DECREF(buf);
> return NULL;
> break;
> case 5:
> default:
> return PyErr_SetFromErrno(SSLErrorObject);
> break;
>
For comparison, here's what M2Crypto's ssl_read() looks like:
PyObject *ssl_read(SSL *ssl, int num) {
PyObject *obj;
void *buf;
int r, err;
if (!(buf = PyMem_Malloc(num))) {
PyErr_SetString(PyExc_MemoryError, "ssl_read");
return NULL;
}
Py_BEGIN_ALLOW_THREADS
r = SSL_read(ssl, buf, num);
Py_END_ALLOW_THREADS
switch (SSL_get_error(ssl, r)) {
case SSL_ERROR_NONE:
case SSL_ERROR_ZERO_RETURN:
buf = PyMem_Realloc(buf, r);
obj = PyString_FromStringAndSize(buf, r);
break;
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_X509_LOOKUP:
Py_INCREF(Py_None);
obj = Py_None;
break;
case SSL_ERROR_SSL:
PyErr_SetString(_ssl_err, ERR_reason_error_string(ERR_get_error()));
obj = NULL;
break;
case SSL_ERROR_SYSCALL:
err = ERR_get_error();
if (err)
PyErr_SetString(_ssl_err, ERR_reason_error_string(err));
else if (r == 0)
PyErr_SetString(_ssl_err, "unexpected eof");
else if (r == -1)
PyErr_SetFromErrno(_ssl_err);
obj = NULL;
break;
}
PyMem_Free(buf);
return obj;
}
And Python code using that, from M2Crypto's https extension to Medusa:
def recv(self, buffer_size):
try:
result = self.socket._read_nbio(buffer_size)
if result is None:
return ''
elif result == '':
self.socket.set_shutdown(SSL.SSL_SENT_SHUTDOWN|SSL.SSL_RECEIVED_SHUTDOWN)
return ''
else:
self.server.bytes_in.increment(len(result))
return result
except SSL.SSLError, why:
self.socket.set_shutdown(SSL.SSL_SENT_SHUTDOWN|SSL.SSL_RECEIVED_SHUTDOWN)
self.close()
self.log_info('recv: closing channel %s %s' % (repr(self), why))
return ''
So, in M2Crypto, ssl_read() does return a '' on eof; if the other side
failed to close properly, an SSL.SSLError exception is raised with the
error "unexpected eof".
M2Crypto works with both Python 1.5.2 and Python 2.0. Get it here:
http://www.post1.com/home/ngps/m2
Cheers.
--
Ng Pheng Siong <ngps at post1.com> * http://www.post1.com/home/ngps
More information about the Python-list
mailing list