[Python-checkins] python/dist/src/Modules _ssl.c,1.1,1.2

loewis@sourceforge.net loewis@sourceforge.net
Sat, 20 Apr 2002 00:47:42 -0700


Update of /cvsroot/python/python/dist/src/Modules
In directory usw-pr-cvs1:/tmp/cvs-serv5973/Modules

Modified Files:
	_ssl.c 
Log Message:
Forward port of patch # 500311: Work around for buggy https servers.
Fixes #494762.


Index: _ssl.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/_ssl.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** _ssl.c	16 Feb 2002 18:23:30 -0000	1.1
--- _ssl.c	20 Apr 2002 07:47:40 -0000	1.2
***************
*** 9,12 ****
--- 9,26 ----
  
  #include "Python.h"
+ enum py_ssl_error {
+ 	/* these mirror ssl.h */
+ 	PY_SSL_ERROR_NONE,                 
+ 	PY_SSL_ERROR_SSL,                   
+ 	PY_SSL_ERROR_WANT_READ,             
+ 	PY_SSL_ERROR_WANT_WRITE,            
+ 	PY_SSL_ERROR_WANT_X509_LOOKUP,      
+ 	PY_SSL_ERROR_SYSCALL,     /* look at error stack/return value/errno */
+ 	PY_SSL_ERROR_ZERO_RETURN,           
+ 	PY_SSL_ERROR_WANT_CONNECT,
+ 	/* start of non ssl.h errorcodes */ 
+ 	PY_SSL_ERROR_EOF,         /* special case of SSL_ERROR_SYSCALL */
+ 	PY_SSL_ERROR_INVALID_ERROR_CODE
+ };
  
  /* Include symbols from _socket module */
***************
*** 65,115 ****
  	char *errstr;
  	int err;
  
  	assert(ret <= 0);
      
  	err = SSL_get_error(obj->ssl, ret);
- 	n = PyInt_FromLong(err);
- 	if (n == NULL)
- 		return NULL;
- 	v = PyTuple_New(2);
- 	if (v == NULL) {
- 		Py_DECREF(n);
- 		return NULL;
- 	}
  
! 	switch (SSL_get_error(obj->ssl, ret)) {
  	case SSL_ERROR_ZERO_RETURN:
  		errstr = "TLS/SSL connection has been closed";
  		break;
  	case SSL_ERROR_WANT_READ:
  		errstr = "The operation did not complete (read)";
  		break;
  	case SSL_ERROR_WANT_WRITE:
  		errstr = "The operation did not complete (write)";
  		break;
  	case SSL_ERROR_WANT_X509_LOOKUP:
  		errstr = "The operation did not complete (X509 lookup)";
  		break;
  	case SSL_ERROR_SYSCALL:
- 	case SSL_ERROR_SSL:
  	{
  		unsigned long e = ERR_get_error();
! 		if (e == 0) {
! 			/* an EOF was observed that violates the protocol */
! 			errstr = "EOF occurred in violation of protocol";
! 		} else if (e == -1) {
! 			/* the underlying BIO reported an I/O error */
! 			Py_DECREF(v);
! 			Py_DECREF(n);
! 			return obj->Socket->errorhandler();
  		} else {
  			/* XXX Protected by global interpreter lock */
  			errstr = ERR_error_string(e, NULL);
  		}
  		break;
  	}
  	default:
  		errstr = "Invalid error code";
  	}
  	s = PyString_FromString(errstr);
  	if (s == NULL) {
--- 79,155 ----
  	char *errstr;
  	int err;
+ 	enum py_ssl_error p;
  
  	assert(ret <= 0);
      
  	err = SSL_get_error(obj->ssl, ret);
  
! 	switch (err) {
  	case SSL_ERROR_ZERO_RETURN:
  		errstr = "TLS/SSL connection has been closed";
+ 		p=PY_SSL_ERROR_ZERO_RETURN;
  		break;
  	case SSL_ERROR_WANT_READ:
  		errstr = "The operation did not complete (read)";
+ 		p=PY_SSL_ERROR_WANT_READ;
  		break;
  	case SSL_ERROR_WANT_WRITE:
+ 		p=PY_SSL_ERROR_WANT_WRITE;
  		errstr = "The operation did not complete (write)";
  		break;
  	case SSL_ERROR_WANT_X509_LOOKUP:
+ 		p=PY_SSL_ERROR_WANT_X509_LOOKUP;
  		errstr = "The operation did not complete (X509 lookup)";
  		break;
+ 	case SSL_ERROR_WANT_CONNECT:
+ 		p=PY_SSL_ERROR_WANT_CONNECT;
+ 		errstr = "The operation did not complete (connect)";
+ 		break;
  	case SSL_ERROR_SYSCALL:
  	{
  		unsigned long e = ERR_get_error();
! 		if(e==0){
! 			if(ret==0){
! 				p=PY_SSL_ERROR_EOF;
! 				errstr = "EOF occurred in violation of protocol";
! 			}else if(ret==-1){
! 				/* the underlying BIO reported an I/O error */
! 				return obj->Socket->errorhandler();
! 			}else{  /* possible? */
! 				p=PY_SSL_ERROR_SYSCALL;
! 				errstr = "Some I/O error occurred";
! 			}
  		} else {
+ 			p=PY_SSL_ERROR_SYSCALL;
+ 			/* XXX Protected by global interpreter lock */
+ 			errstr = ERR_error_string(e, NULL);
+ 		}
+ 		break;
+ 	}   
+ 	case SSL_ERROR_SSL:
+ 	{
+ 		unsigned long e = ERR_get_error();
+ 		p=PY_SSL_ERROR_SSL;
+ 		if (e !=0) {
  			/* XXX Protected by global interpreter lock */
  			errstr = ERR_error_string(e, NULL);
+ 		} else { /* possible? */
+ 			errstr="A failure in the SSL library occurred";
  		}
  		break;
  	}
  	default:
+ 		p=PY_SSL_ERROR_INVALID_ERROR_CODE;
  		errstr = "Invalid error code";
  	}
+ 	n = PyInt_FromLong((long) p);
+ 	if (n == NULL)
+ 		return NULL;
+ 	v = PyTuple_New(2);
+ 	if (v == NULL) {
+ 		Py_DECREF(n);
+ 		return NULL;
+ 	}
+ 
  	s = PyString_FromString(errstr);
  	if (s == NULL) {
***************
*** 448,461 ****
  		return;
  	PyModule_AddIntConstant(m, "SSL_ERROR_ZERO_RETURN",
! 				SSL_ERROR_ZERO_RETURN);
  	PyModule_AddIntConstant(m, "SSL_ERROR_WANT_READ",
! 				SSL_ERROR_WANT_READ);
  	PyModule_AddIntConstant(m, "SSL_ERROR_WANT_WRITE",
! 				SSL_ERROR_WANT_WRITE);
  	PyModule_AddIntConstant(m, "SSL_ERROR_WANT_X509_LOOKUP",
! 				SSL_ERROR_WANT_X509_LOOKUP);
  	PyModule_AddIntConstant(m, "SSL_ERROR_SYSCALL",
! 				SSL_ERROR_SYSCALL);
  	PyModule_AddIntConstant(m, "SSL_ERROR_SSL",
! 				SSL_ERROR_SSL);
  }
--- 488,509 ----
  		return;
  	PyModule_AddIntConstant(m, "SSL_ERROR_ZERO_RETURN",
! 				PY_SSL_ERROR_ZERO_RETURN);
  	PyModule_AddIntConstant(m, "SSL_ERROR_WANT_READ",
! 				PY_SSL_ERROR_WANT_READ);
  	PyModule_AddIntConstant(m, "SSL_ERROR_WANT_WRITE",
! 				PY_SSL_ERROR_WANT_WRITE);
  	PyModule_AddIntConstant(m, "SSL_ERROR_WANT_X509_LOOKUP",
! 				PY_SSL_ERROR_WANT_X509_LOOKUP);
  	PyModule_AddIntConstant(m, "SSL_ERROR_SYSCALL",
! 				PY_SSL_ERROR_SYSCALL);
  	PyModule_AddIntConstant(m, "SSL_ERROR_SSL",
! 				PY_SSL_ERROR_SSL);
! 	PyModule_AddIntConstant(m, "SSL_ERROR_WANT_CONNECT",
! 				PY_SSL_ERROR_WANT_CONNECT);
! 	/* non ssl.h errorcodes */
! 	PyModule_AddIntConstant(m, "SSL_ERROR_EOF",
! 				PY_SSL_ERROR_EOF);
! 	PyModule_AddIntConstant(m, "SSL_ERROR_INVALID_ERROR_CODE",
! 				PY_SSL_ERROR_INVALID_ERROR_CODE);
! 
  }