/* SSL socket module SSL support based on patches by Brian E Gallew and Laszlo Kovacs. Re-worked a bit by Bill Janssen to add server-side support and certificate decoding. Chris Stawarz contributed some non-blocking patches. This module is imported by ssl.py. It should *not* be used directly. XXX should partial writes be enabled, SSL_MODE_ENABLE_PARTIAL_WRITE? XXX integrate several "shutdown modes" as suggested in http://bugs.python.org/issue8108#msg102867 ?*/#include "Python.h"#ifdef WITH_THREAD#include "pythread.h"#define PySSL_BEGIN_ALLOW_THREADS { \ PyThreadState *_save = NULL; \ if (_ssl_locks_count>0) {_save = PyEval_SaveThread();}#define PySSL_BLOCK_THREADS if (_ssl_locks_count>0){PyEval_RestoreThread(_save)};#define PySSL_UNBLOCK_THREADS if (_ssl_locks_count>0){_save = PyEval_SaveThread()};#define PySSL_END_ALLOW_THREADS if (_ssl_locks_count>0){PyEval_RestoreThread(_save);} \ }#else /* no WITH_THREAD */#define PySSL_BEGIN_ALLOW_THREADS#define PySSL_BLOCK_THREADS#define PySSL_UNBLOCK_THREADS#define PySSL_END_ALLOW_THREADS#endifenumpy_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};enumpy_ssl_server_or_client{PY_SSL_CLIENT,PY_SSL_SERVER};enumpy_ssl_cert_requirements{PY_SSL_CERT_NONE,PY_SSL_CERT_OPTIONAL,PY_SSL_CERT_REQUIRED};enumpy_ssl_version{PY_SSL_VERSION_SSL2,PY_SSL_VERSION_SSL3,PY_SSL_VERSION_SSL23,PY_SSL_VERSION_TLS1};/* Include symbols from _socket module */#include "socketmodule.h"#if defined(HAVE_POLL_H)#include <poll.h>#elif defined(HAVE_SYS_POLL_H)#include <sys/poll.h>#endif/* Include OpenSSL header files */#include "openssl/rsa.h"#include "openssl/crypto.h"#include "openssl/x509.h"#include "openssl/x509v3.h"#include "openssl/pem.h"#include "openssl/ssl.h"#include "openssl/err.h"#include "openssl/rand.h"/* SSL error object */staticPyObject*PySSLErrorObject;#ifdef WITH_THREAD/* serves as a flag to see whether we've initialized the SSL thread support. *//* 0 means no, greater than 0 means yes */staticunsignedint_ssl_locks_count=0;#endif /* def WITH_THREAD *//* SSL socket object */#define X509_NAME_MAXLEN 256/* RAND_* APIs got added to OpenSSL in 0.9.5 */#if OPENSSL_VERSION_NUMBER >= 0x0090500fL# define HAVE_OPENSSL_RAND 1#else# undef HAVE_OPENSSL_RAND#endiftypedefstruct{PyObject_HEADPySocketSockObject*Socket;/* Socket on which we're layered */SSL_CTX*ctx;SSL*ssl;X509*peer_cert;charserver[X509_NAME_MAXLEN];charissuer[X509_NAME_MAXLEN];intshutdown_seen_zero;}PySSLObject;staticPyTypeObjectPySSL_Type;staticPyObject*PySSL_SSLwrite(PySSLObject*self,PyObject*args);staticPyObject*PySSL_SSLread(PySSLObject*self,PyObject*args);staticintcheck_socket_and_wait_for_timeout(PySocketSockObject*s,intwriting);staticPyObject*PySSL_peercert(PySSLObject*self,PyObject*args);staticPyObject*PySSL_cipher(PySSLObject*self);#define PySSLObject_Check(v) (Py_TYPE(v) == &PySSL_Type)typedefenum{SOCKET_IS_NONBLOCKING,SOCKET_IS_BLOCKING,SOCKET_HAS_TIMED_OUT,SOCKET_HAS_BEEN_CLOSED,SOCKET_TOO_LARGE_FOR_SELECT,SOCKET_OPERATION_OK}timeout_state;/* Wrap error strings with filename and line # */#define STRINGIFY1(x) #x#define STRINGIFY2(x) STRINGIFY1(x)#define ERRSTR1(x,y,z) (x ":" y ": " z)#define ERRSTR(x) ERRSTR1("_ssl.c", STRINGIFY2(__LINE__), x)/* XXX It might be helpful to augment the error message generated below with the name of the SSL function that generated the error. I expect it's obvious most of the time.*/staticPyObject*PySSL_SetError(PySSLObject*obj,intret,char*filename,intlineno){PyObject*v;charbuf[2048];char*errstr;interr;enumpy_ssl_errorp=PY_SSL_ERROR_NONE;assert(ret<=0);if(obj->ssl!=NULL){err=SSL_get_error(obj->ssl,ret);switch(err){caseSSL_ERROR_ZERO_RETURN:errstr="TLS/SSL connection has been closed";p=PY_SSL_ERROR_ZERO_RETURN;break;caseSSL_ERROR_WANT_READ:errstr="The operation did not complete (read)";p=PY_SSL_ERROR_WANT_READ;break;caseSSL_ERROR_WANT_WRITE:p=PY_SSL_ERROR_WANT_WRITE;errstr="The operation did not complete (write)";break;caseSSL_ERROR_WANT_X509_LOOKUP:p=PY_SSL_ERROR_WANT_X509_LOOKUP;errstr="The operation did not complete (X509 lookup)";break;caseSSL_ERROR_WANT_CONNECT:p=PY_SSL_ERROR_WANT_CONNECT;errstr="The operation did not complete (connect)";break;caseSSL_ERROR_SYSCALL:{unsignedlonge=ERR_get_error();if(e==0){if(ret==0||!obj->Socket){p=PY_SSL_ERROR_EOF;errstr="EOF occurred in violation of protocol";}elseif(ret==-1){/* underlying BIO reported an I/O error */ERR_clear_error();returnobj->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;}caseSSL_ERROR_SSL:{unsignedlonge=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";}}else{errstr=ERR_error_string(ERR_peek_last_error(),NULL);}PyOS_snprintf(buf,sizeof(buf),"_ssl.c:%d: %s",lineno,errstr);ERR_clear_error();v=Py_BuildValue("(is)",p,buf);if(v!=NULL){PyErr_SetObject(PySSLErrorObject,v);Py_DECREF(v);}returnNULL;}staticPyObject*_setSSLError(char*errstr,interrcode,char*filename,intlineno){charbuf[2048];PyObject*v;if(errstr==NULL){errcode=ERR_peek_last_error();errstr=ERR_error_string(errcode,NULL);}PyOS_snprintf(buf,sizeof(buf),"_ssl.c:%d: %s",lineno,errstr);ERR_clear_error();v=Py_BuildValue("(is)",errcode,buf);if(v!=NULL){PyErr_SetObject(PySSLErrorObject,v);Py_DECREF(v);}returnNULL;}staticPySSLObject*newPySSLObject(PySocketSockObject*Sock,char*key_file,char*cert_file,enumpy_ssl_server_or_clientsocket_type,enumpy_ssl_cert_requirementscertreq,enumpy_ssl_versionproto_version,char*cacerts_file,char*ciphers){PySSLObject*self;char*errstr=NULL;intret;intverification_mode;self=PyObject_New(PySSLObject,&PySSL_Type);/* Create new object */if(self==NULL)returnNULL;memset(self->server,'\0',sizeof(char)*X509_NAME_MAXLEN);memset(self->issuer,'\0',sizeof(char)*X509_NAME_MAXLEN);self->peer_cert=NULL;self->ssl=NULL;self->ctx=NULL;self->Socket=NULL;/* Make sure the SSL error state is initialized */(void)ERR_get_state();ERR_clear_error();if((key_file&&!cert_file)||(!key_file&&cert_file)){errstr=ERRSTR("Both the key & certificate files ""must be specified");gotofail;}if((socket_type==PY_SSL_SERVER)&&((key_file==NULL)||(cert_file==NULL))){errstr=ERRSTR("Both the key & certificate files ""must be specified for server-side operation");gotofail;}PySSL_BEGIN_ALLOW_THREADSif(proto_version==PY_SSL_VERSION_TLS1)self->ctx=SSL_CTX_new(TLSv1_method());/* Set up context */elseif(proto_version==PY_SSL_VERSION_SSL3)self->ctx=SSL_CTX_new(SSLv3_method());/* Set up context */elseif(proto_version==PY_SSL_VERSION_SSL2)self->ctx=SSL_CTX_new(SSLv2_method());/* Set up context */elseif(proto_version==PY_SSL_VERSION_SSL23)self->ctx=SSL_CTX_new(SSLv23_method());/* Set up context */PySSL_END_ALLOW_THREADSif(self->ctx==NULL){errstr=ERRSTR("Invalid SSL protocol variant specified.");gotofail;}if(ciphers!=NULL){ret=SSL_CTX_set_cipher_list(self->ctx,ciphers);if(ret==0){errstr=ERRSTR("No cipher can be selected.");gotofail;}}if(certreq!=PY_SSL_CERT_NONE){if(cacerts_file==NULL){errstr=ERRSTR("No root certificates specified for ""verification of other-side certificates.");gotofail;}else{PySSL_BEGIN_ALLOW_THREADSret=SSL_CTX_load_verify_locations(self->ctx,cacerts_file,NULL);PySSL_END_ALLOW_THREADSif(ret!=1){_setSSLError(NULL,0,__FILE__,__LINE__);gotofail;}}}if(key_file){PySSL_BEGIN_ALLOW_THREADSret=SSL_CTX_use_PrivateKey_file(self->ctx,key_file,SSL_FILETYPE_PEM);PySSL_END_ALLOW_THREADSif(ret!=1){_setSSLError(NULL,ret,__FILE__,__LINE__);gotofail;}PySSL_BEGIN_ALLOW_THREADSret=SSL_CTX_use_certificate_chain_file(self->ctx,cert_file);PySSL_END_ALLOW_THREADSif(ret!=1){/* fprintf(stderr, "ret is %d, errcode is %lu, %lu, with file \"%s\"\n", ret, ERR_peek_error(), ERR_peek_last_error(), cert_file); */if(ERR_peek_last_error()!=0){_setSSLError(NULL,ret,__FILE__,__LINE__);gotofail;}}}/* ssl compatibility */SSL_CTX_set_options(self->ctx,SSL_OP_ALL);verification_mode=SSL_VERIFY_NONE;if(certreq==PY_SSL_CERT_OPTIONAL)verification_mode=SSL_VERIFY_PEER;elseif(certreq==PY_SSL_CERT_REQUIRED)verification_mode=(SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT);SSL_CTX_set_verify(self->ctx,verification_mode,NULL);/* set verify lvl */PySSL_BEGIN_ALLOW_THREADSself->ssl=SSL_new(self->ctx);/* New ssl struct */PySSL_END_ALLOW_THREADSSSL_set_fd(self->ssl,Sock->sock_fd);/* Set the socket for SSL */#ifdef SSL_MODE_AUTO_RETRYSSL_set_mode(self->ssl,SSL_MODE_AUTO_RETRY);#endif/* 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);}PySSL_BEGIN_ALLOW_THREADSif(socket_type==PY_SSL_CLIENT)SSL_set_connect_state(self->ssl);elseSSL_set_accept_state(self->ssl);PySSL_END_ALLOW_THREADSself->Socket=Sock;Py_INCREF(self->Socket);returnself;fail:if(errstr)PyErr_SetString(PySSLErrorObject,errstr);Py_DECREF(self);returnNULL;}staticPyObject*PySSL_sslwrap(PyObject*self,PyObject*args){PySocketSockObject*Sock;intserver_side=0;intverification_mode=PY_SSL_CERT_NONE;intprotocol=PY_SSL_VERSION_SSL23;char*key_file=NULL;char*cert_file=NULL;char*cacerts_file=NULL;char*ciphers=NULL;if(!PyArg_ParseTuple(args,"O!i|zziizz:sslwrap",PySocketModule.Sock_Type,&Sock,&server_side,&key_file,&cert_file,&verification_mode,&protocol,&cacerts_file,&ciphers))returnNULL;/* fprintf(stderr, "server_side is %d, keyfile %p, certfile %p, verify_mode %d, " "protocol %d, certs %p\n", server_side, key_file, cert_file, verification_mode, protocol, cacerts_file); */return(PyObject*)newPySSLObject(Sock,key_file,cert_file,server_side,verification_mode,protocol,cacerts_file,ciphers);}PyDoc_STRVAR(ssl_doc,"sslwrap(socket, server_side, [keyfile, certfile, certs_mode, protocol,\n"" cacertsfile, ciphers]) -> sslobject");/* SSL object methods */staticPyObject*PySSL_SSLdo_handshake(PySSLObject*self){intret;interr;intsockstate,nonblocking;/* just in case the blocking state of the socket has been changed */nonblocking=(self->Socket->sock_timeout>=0.0);BIO_set_nbio(SSL_get_rbio(self->ssl),nonblocking);BIO_set_nbio(SSL_get_wbio(self->ssl),nonblocking);/* Actually negotiate SSL connection *//* XXX If SSL_do_handshake() returns 0, it's also a failure. */do{PySSL_BEGIN_ALLOW_THREADSret=SSL_do_handshake(self->ssl);err=SSL_get_error(self->ssl,ret);PySSL_END_ALLOW_THREADSif(PyErr_CheckSignals()){returnNULL;}if(err==SSL_ERROR_WANT_READ){sockstate=check_socket_and_wait_for_timeout(self->Socket,0);}elseif(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,ERRSTR("The handshake operation timed out"));returnNULL;}elseif(sockstate==SOCKET_HAS_BEEN_CLOSED){PyErr_SetString(PySSLErrorObject,ERRSTR("Underlying socket has been closed."));returnNULL;}elseif(sockstate==SOCKET_TOO_LARGE_FOR_SELECT){PyErr_SetString(PySSLErrorObject,ERRSTR("Underlying socket too large for select()."));returnNULL;}elseif(sockstate==SOCKET_IS_NONBLOCKING){break;}}while(err==SSL_ERROR_WANT_READ||err==SSL_ERROR_WANT_WRITE);if(ret<1)returnPySSL_SetError(self,ret,__FILE__,__LINE__);self->ssl->debug=1;if(self->peer_cert)X509_free(self->peer_cert);PySSL_BEGIN_ALLOW_THREADSif((self->peer_cert=SSL_get_peer_certificate(self->ssl))){X509_NAME_oneline(X509_get_subject_name(self->peer_cert),self->server,X509_NAME_MAXLEN);X509_NAME_oneline(X509_get_issuer_name(self->peer_cert),self->issuer,X509_NAME_MAXLEN);}PySSL_END_ALLOW_THREADSPy_INCREF(Py_None);returnPy_None;}staticPyObject*PySSL_server(PySSLObject*self){returnPyString_FromString(self->server);}staticPyObject*PySSL_issuer(PySSLObject*self){returnPyString_FromString(self->issuer);}staticPyObject*_create_tuple_for_attribute(ASN1_OBJECT*name,ASN1_STRING*value){charnamebuf[X509_NAME_MAXLEN];intbuflen;PyObject*name_obj;PyObject*value_obj;PyObject*attr;unsignedchar*valuebuf=NULL;buflen=OBJ_obj2txt(namebuf,sizeof(namebuf),name,0);if(buflen<0){_setSSLError(NULL,0,__FILE__,__LINE__);gotofail;}name_obj=PyString_FromStringAndSize(namebuf,buflen);if(name_obj==NULL)gotofail;buflen=ASN1_STRING_to_UTF8(&valuebuf,value);if(buflen<0){_setSSLError(NULL,0,__FILE__,__LINE__);Py_DECREF(name_obj);gotofail;}value_obj=PyUnicode_DecodeUTF8((char*)valuebuf,buflen,"strict");OPENSSL_free(valuebuf);if(value_obj==NULL){Py_DECREF(name_obj);gotofail;}attr=PyTuple_New(2);if(attr==NULL){Py_DECREF(name_obj);Py_DECREF(value_obj);gotofail;}PyTuple_SET_ITEM(attr,0,name_obj);PyTuple_SET_ITEM(attr,1,value_obj);returnattr;fail:returnNULL;}staticPyObject*_create_tuple_for_X509_NAME(X509_NAME*xname){PyObject*dn=NULL;/* tuple which represents the "distinguished name" */PyObject*rdn=NULL;/* tuple to hold a "relative distinguished name" */PyObject*rdnt;PyObject*attr=NULL;/* tuple to hold an attribute */intentry_count=X509_NAME_entry_count(xname);X509_NAME_ENTRY*entry;ASN1_OBJECT*name;ASN1_STRING*value;intindex_counter;intrdn_level=-1;intretcode;dn=PyList_New(0);if(dn==NULL)returnNULL;/* now create another tuple to hold the top-level RDN */rdn=PyList_New(0);if(rdn==NULL)gotofail0;for(index_counter=0;index_counter<entry_count;index_counter++){entry=X509_NAME_get_entry(xname,index_counter);/* check to see if we've gotten to a new RDN */if(rdn_level>=0){if(rdn_level!=entry->set){/* yes, new RDN *//* add old RDN to DN */rdnt=PyList_AsTuple(rdn);Py_DECREF(rdn);if(rdnt==NULL)gotofail0;retcode=PyList_Append(dn,rdnt);Py_DECREF(rdnt);if(retcode<0)gotofail0;/* create new RDN */rdn=PyList_New(0);if(rdn==NULL)gotofail0;}}rdn_level=entry->set;/* now add this attribute to the current RDN */name=X509_NAME_ENTRY_get_object(entry);value=X509_NAME_ENTRY_get_data(entry);attr=_create_tuple_for_attribute(name,value);/* fprintf(stderr, "RDN level %d, attribute %s: %s\n", entry->set, PyString_AS_STRING(PyTuple_GET_ITEM(attr, 0)), PyString_AS_STRING(PyTuple_GET_ITEM(attr, 1))); */if(attr==NULL)gotofail1;retcode=PyList_Append(rdn,attr);Py_DECREF(attr);if(retcode<0)gotofail1;}/* now, there's typically a dangling RDN */if((rdn!=NULL)&&(PyList_Size(rdn)>0)){rdnt=PyList_AsTuple(rdn);Py_DECREF(rdn);if(rdnt==NULL)gotofail0;retcode=PyList_Append(dn,rdnt);Py_DECREF(rdnt);if(retcode<0)gotofail0;}/* convert list to tuple */rdnt=PyList_AsTuple(dn);Py_DECREF(dn);if(rdnt==NULL)returnNULL;returnrdnt;fail1:Py_XDECREF(rdn);fail0:Py_XDECREF(dn);returnNULL;}staticPyObject*_get_peer_alt_names(X509*certificate){/* this code follows the procedure outlined in OpenSSL's crypto/x509v3/v3_prn.c:X509v3_EXT_print() function to extract the STACK_OF(GENERAL_NAME), then iterates through the stack to add the names. */inti,j;PyObject*peer_alt_names=Py_None;PyObject*v,*t;X509_EXTENSION*ext=NULL;GENERAL_NAMES*names=NULL;GENERAL_NAME*name;X509V3_EXT_METHOD*method;BIO*biobuf=NULL;charbuf[2048];char*vptr;intlen;/* Issue #2973: ASN1_item_d2i() API changed in OpenSSL 0.9.6m */#if OPENSSL_VERSION_NUMBER >= 0x009060dfLconstunsignedchar*p;#elseunsignedchar*p;#endifif(certificate==NULL)returnpeer_alt_names;/* get a memory buffer */biobuf=BIO_new(BIO_s_mem());i=0;while((i=X509_get_ext_by_NID(certificate,NID_subject_alt_name,i))>=0){if(peer_alt_names==Py_None){peer_alt_names=PyList_New(0);if(peer_alt_names==NULL)gotofail;}/* now decode the altName */ext=X509_get_ext(certificate,i);if(!(method=X509V3_EXT_get(ext))){PyErr_SetString(PySSLErrorObject,ERRSTR("No method for internalizing subjectAltName!"));gotofail;}p=ext->value->data;if(method->it)names=(GENERAL_NAMES*)(ASN1_item_d2i(NULL,&p,ext->value->length,ASN1_ITEM_ptr(method->it)));elsenames=(GENERAL_NAMES*)(method->d2i(NULL,&p,ext->value->length));for(j=0;j<sk_GENERAL_NAME_num(names);j++){/* get a rendering of each name in the set of names */name=sk_GENERAL_NAME_value(names,j);if(name->type==GEN_DIRNAME){/* we special-case DirName as a tuple of tuples of attributes */t=PyTuple_New(2);if(t==NULL){gotofail;}v=PyString_FromString("DirName");if(v==NULL){Py_DECREF(t);gotofail;}PyTuple_SET_ITEM(t,0,v);v=_create_tuple_for_X509_NAME(name->d.dirn);if(v==NULL){Py_DECREF(t);gotofail;}PyTuple_SET_ITEM(t,1,v);}else{/* for everything else, we use the OpenSSL print form */(void)BIO_reset(biobuf);GENERAL_NAME_print(biobuf,name);len=BIO_gets(biobuf,buf,sizeof(buf)-1);if(len<0){_setSSLError(NULL,0,__FILE__,__LINE__);gotofail;}vptr=strchr(buf,':');if(vptr==NULL)gotofail;t=PyTuple_New(2);if(t==NULL)gotofail;v=PyString_FromStringAndSize(buf,(vptr-buf));if(v==NULL){Py_DECREF(t);gotofail;}PyTuple_SET_ITEM(t,0,v);v=PyString_FromStringAndSize((vptr+1),(len-(vptr-buf+1)));if(v==NULL){Py_DECREF(t);gotofail;}PyTuple_SET_ITEM(t,1,v);}/* and add that rendering to the list */if(PyList_Append(peer_alt_names,t)<0){Py_DECREF(t);gotofail;}Py_DECREF(t);}}BIO_free(biobuf);if(peer_alt_names!=Py_None){v=PyList_AsTuple(peer_alt_names);Py_DECREF(peer_alt_names);returnv;}else{returnpeer_alt_names;}fail:if(biobuf!=NULL)BIO_free(biobuf);if(peer_alt_names!=Py_None){Py_XDECREF(peer_alt_names);}returnNULL;}staticPyObject*_decode_certificate(X509*certificate,intverbose){PyObject*retval=NULL;BIO*biobuf=NULL;PyObject*peer;PyObject*peer_alt_names=NULL;PyObject*issuer;PyObject*version;PyObject*sn_obj;ASN1_INTEGER*serialNumber;charbuf[2048];intlen;ASN1_TIME*notBefore,*notAfter;PyObject*pnotBefore,*pnotAfter;retval=PyDict_New();if(retval==NULL)returnNULL;peer=_create_tuple_for_X509_NAME(X509_get_subject_name(certificate));if(peer==NULL)gotofail0;if(PyDict_SetItemString(retval,(constchar*)"subject",peer)<0){Py_DECREF(peer);gotofail0;}Py_DECREF(peer);if(verbose){issuer=_create_tuple_for_X509_NAME(X509_get_issuer_name(certificate));if(issuer==NULL)gotofail0;if(PyDict_SetItemString(retval,(constchar*)"issuer",issuer)<0){Py_DECREF(issuer);gotofail0;}Py_DECREF(issuer);version=PyInt_FromLong(X509_get_version(certificate)+1);if(PyDict_SetItemString(retval,"version",version)<0){Py_DECREF(version);gotofail0;}Py_DECREF(version);}/* get a memory buffer */biobuf=BIO_new(BIO_s_mem());if(verbose){(void)BIO_reset(biobuf);serialNumber=X509_get_serialNumber(certificate);/* should not exceed 20 octets, 160 bits, so buf is big enough */i2a_ASN1_INTEGER(biobuf,serialNumber);len=BIO_gets(biobuf,buf,sizeof(buf)-1);if(len<0){_setSSLError(NULL,0,__FILE__,__LINE__);gotofail1;}sn_obj=PyString_FromStringAndSize(buf,len);if(sn_obj==NULL)gotofail1;if(PyDict_SetItemString(retval,"serialNumber",sn_obj)<0){Py_DECREF(sn_obj);gotofail1;}Py_DECREF(sn_obj);(void)BIO_reset(biobuf);notBefore=X509_get_notBefore(certificate);ASN1_TIME_print(biobuf,notBefore);len=BIO_gets(biobuf,buf,sizeof(buf)-1);if(len<0){_setSSLError(NULL,0,__FILE__,__LINE__);gotofail1;}pnotBefore=PyString_FromStringAndSize(buf,len);if(pnotBefore==NULL)gotofail1;if(PyDict_SetItemString(retval,"notBefore",pnotBefore)<0){Py_DECREF(pnotBefore);gotofail1;}Py_DECREF(pnotBefore);}(void)BIO_reset(biobuf);notAfter=X509_get_notAfter(certificate);ASN1_TIME_print(biobuf,notAfter);len=BIO_gets(biobuf,buf,sizeof(buf)-1);if(len<0){_setSSLError(NULL,0,__FILE__,__LINE__);gotofail1;}pnotAfter=PyString_FromStringAndSize(buf,len);if(pnotAfter==NULL)gotofail1;if(PyDict_SetItemString(retval,"notAfter",pnotAfter)<0){Py_DECREF(pnotAfter);gotofail1;}Py_DECREF(pnotAfter);/* Now look for subjectAltName */peer_alt_names=_get_peer_alt_names(certificate);if(peer_alt_names==NULL)gotofail1;elseif(peer_alt_names!=Py_None){if(PyDict_SetItemString(retval,"subjectAltName",peer_alt_names)<0){Py_DECREF(peer_alt_names);gotofail1;}Py_DECREF(peer_alt_names);}BIO_free(biobuf);returnretval;fail1:if(biobuf!=NULL)BIO_free(biobuf);fail0:Py_XDECREF(retval);returnNULL;}staticPyObject*PySSL_test_decode_certificate(PyObject*mod,PyObject*args){PyObject*retval=NULL;char*filename=NULL;X509*x=NULL;BIO*cert;intverbose=1;if(!PyArg_ParseTuple(args,"s|i:test_decode_certificate",&filename,&verbose))returnNULL;if((cert=BIO_new(BIO_s_file()))==NULL){PyErr_SetString(PySSLErrorObject,"Can't malloc memory to read file");gotofail0;}if(BIO_read_filename(cert,filename)<=0){PyErr_SetString(PySSLErrorObject,"Can't open file");gotofail0;}x=PEM_read_bio_X509_AUX(cert,NULL,NULL,NULL);if(x==NULL){PyErr_SetString(PySSLErrorObject,"Error decoding PEM-encoded file");gotofail0;}retval=_decode_certificate(x,verbose);fail0:if(cert!=NULL)BIO_free(cert);returnretval;}staticPyObject*PySSL_peercert(PySSLObject*self,PyObject*args){PyObject*retval=NULL;intlen;intverification;PyObject*binary_mode=Py_None;if(!PyArg_ParseTuple(args,"|O:peer_certificate",&binary_mode))returnNULL;if(!self->peer_cert)Py_RETURN_NONE;if(PyObject_IsTrue(binary_mode)){/* return cert in DER-encoded format */unsignedchar*bytes_buf=NULL;bytes_buf=NULL;len=i2d_X509(self->peer_cert,&bytes_buf);if(len<0){PySSL_SetError(self,len,__FILE__,__LINE__);returnNULL;}retval=PyString_FromStringAndSize((constchar*)bytes_buf,len);OPENSSL_free(bytes_buf);returnretval;}else{verification=SSL_CTX_get_verify_mode(self->ctx);if((verification&SSL_VERIFY_PEER)==0)returnPyDict_New();elsereturn_decode_certificate(self->peer_cert,0);}}PyDoc_STRVAR(PySSL_peercert_doc,"peer_certificate([der=False]) -> certificate\n\\n\Returns the certificate for the peer. If no certificate was provided,\n\returns None. If a certificate was provided, but not validated, returns\n\an empty dictionary. Otherwise returns a dict containing information\n\about the peer certificate.\n\\n\If the optional argument is True, returns a DER-encoded copy of the\n\peer certificate, or None if no certificate was provided. This will\n\return the certificate even if it wasn't validated.");staticPyObject*PySSL_cipher(PySSLObject*self){PyObject*retval,*v;SSL_CIPHER*current;char*cipher_name;char*cipher_protocol;if(self->ssl==NULL)returnPy_None;current=SSL_get_current_cipher(self->ssl);if(current==NULL)returnPy_None;retval=PyTuple_New(3);if(retval==NULL)returnNULL;cipher_name=(char*)SSL_CIPHER_get_name(current);if(cipher_name==NULL){PyTuple_SET_ITEM(retval,0,Py_None);}else{v=PyString_FromString(cipher_name);if(v==NULL)gotofail0;PyTuple_SET_ITEM(retval,0,v);}cipher_protocol=SSL_CIPHER_get_version(current);if(cipher_protocol==NULL){PyTuple_SET_ITEM(retval,1,Py_None);}else{v=PyString_FromString(cipher_protocol);if(v==NULL)gotofail0;PyTuple_SET_ITEM(retval,1,v);}v=PyInt_FromLong(SSL_CIPHER_get_bits(current,NULL));if(v==NULL)gotofail0;PyTuple_SET_ITEM(retval,2,v);returnretval;fail0:Py_DECREF(retval);returnNULL;}staticvoidPySSL_dealloc(PySSLObject*self){if(self->peer_cert)/* Possible not to have one? */X509_free(self->peer_cert);if(self->ssl)SSL_free(self->ssl);if(self->ctx)SSL_CTX_free(self->ctx);Py_XDECREF(self->Socket);PyObject_Del(self);}/* If the socket has a timeout, do a select()/poll() on the socket. The argument writing indicates the direction. Returns one of the possibilities in the timeout_state enum (above). */staticintcheck_socket_and_wait_for_timeout(PySocketSockObject*s,intwriting){fd_setfds;structtimevaltv;intrc;/* Nothing to do unless we're in timeout mode (not non-blocking) */if(s->sock_timeout<0.0)returnSOCKET_IS_BLOCKING;elseif(s->sock_timeout==0.0)returnSOCKET_IS_NONBLOCKING;/* Guard against closed socket */if(s->sock_fd<0)returnSOCKET_HAS_BEEN_CLOSED;/* Prefer poll, if available, since you can poll() any fd * which can't be done with select(). */#ifdef HAVE_POLL{structpollfdpollfd;inttimeout;pollfd.fd=s->sock_fd;pollfd.events=writing?POLLOUT:POLLIN;/* s->sock_timeout is in seconds, timeout in ms */timeout=(int)(s->sock_timeout*1000+0.5);PySSL_BEGIN_ALLOW_THREADSrc=poll(&pollfd,1,timeout);PySSL_END_ALLOW_THREADSgotonormal_return;}#endif/* Guard against socket too large for select*/#ifndef Py_SOCKET_FD_CAN_BE_GE_FD_SETSIZEif(s->sock_fd>=FD_SETSIZE)returnSOCKET_TOO_LARGE_FOR_SELECT;#endif/* Construct the arguments to select */tv.tv_sec=(int)s->sock_timeout;tv.tv_usec=(int)((s->sock_timeout-tv.tv_sec)*1e6);FD_ZERO(&fds);FD_SET(s->sock_fd,&fds);/* See if the socket is ready */PySSL_BEGIN_ALLOW_THREADSif(writing)rc=select(s->sock_fd+1,NULL,&fds,NULL,&tv);elserc=select(s->sock_fd+1,&fds,NULL,NULL,&tv);PySSL_END_ALLOW_THREADS#ifdef HAVE_POLLnormal_return:#endif/* Return SOCKET_TIMED_OUT on timeout, SOCKET_OPERATION_OK otherwise (when we are able to write or when there's something to read) */returnrc==0?SOCKET_HAS_TIMED_OUT:SOCKET_OPERATION_OK;}staticPyObject*PySSL_SSLwrite(PySSLObject*self,PyObject*args){Py_bufferbuf;intlen;intsockstate;interr;intnonblocking;if(!PyArg_ParseTuple(args,"s*:write",&buf))returnNULL;/* just in case the blocking state of the socket has been changed */nonblocking=(self->Socket->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(self->Socket,1);if(sockstate==SOCKET_HAS_TIMED_OUT){PyErr_SetString(PySSLErrorObject,"The write operation timed out");gotoerror;}elseif(sockstate==SOCKET_HAS_BEEN_CLOSED){PyErr_SetString(PySSLErrorObject,"Underlying socket has been closed.");gotoerror;}elseif(sockstate==SOCKET_TOO_LARGE_FOR_SELECT){PyErr_SetString(PySSLErrorObject,"Underlying socket too large for select().");gotoerror;}do{PySSL_BEGIN_ALLOW_THREADSlen=SSL_write(self->ssl,buf.buf,buf.len);err=SSL_get_error(self->ssl,len);PySSL_END_ALLOW_THREADSif(PyErr_CheckSignals()){gotoerror;}if(err==SSL_ERROR_WANT_READ){sockstate=check_socket_and_wait_for_timeout(self->Socket,0);}elseif(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");gotoerror;}elseif(sockstate==SOCKET_HAS_BEEN_CLOSED){PyErr_SetString(PySSLErrorObject,"Underlying socket has been closed.");gotoerror;}elseif(sockstate==SOCKET_IS_NONBLOCKING){break;}}while(err==SSL_ERROR_WANT_READ||err==SSL_ERROR_WANT_WRITE);PyBuffer_Release(&buf);if(len>0)returnPyInt_FromLong(len);elsereturnPySSL_SetError(self,len,__FILE__,__LINE__);error:PyBuffer_Release(&buf);returnNULL;}PyDoc_STRVAR(PySSL_SSLwrite_doc,"write(s) -> len\n\\n\Writes the string s into the SSL object. Returns the number\n\of bytes written.");staticPyObject*PySSL_SSLpending(PySSLObject*self){intcount=0;PySSL_BEGIN_ALLOW_THREADScount=SSL_pending(self->ssl);PySSL_END_ALLOW_THREADSif(count<0)returnPySSL_SetError(self,count,__FILE__,__LINE__);elsereturnPyInt_FromLong(count);}PyDoc_STRVAR(PySSL_SSLpending_doc,"pending() -> count\n\\n\Returns the number of already decrypted bytes available for read,\n\pending on the connection.\n");staticPyObject*PySSL_SSLread(PySSLObject*self,PyObject*args){PyObject*buf;intcount=0;intlen=1024;intsockstate;interr;intnonblocking;if(!PyArg_ParseTuple(args,"|i:read",&len))returnNULL;if(!(buf=PyString_FromStringAndSize((char*)0,len)))returnNULL;/* just in case the blocking state of the socket has been changed */nonblocking=(self->Socket->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_THREADScount=SSL_pending(self->ssl);PySSL_END_ALLOW_THREADSif(!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);returnNULL;}elseif(sockstate==SOCKET_TOO_LARGE_FOR_SELECT){PyErr_SetString(PySSLErrorObject,"Underlying socket too large for select().");Py_DECREF(buf);returnNULL;}elseif(sockstate==SOCKET_HAS_BEEN_CLOSED){if(SSL_get_shutdown(self->ssl)!=SSL_RECEIVED_SHUTDOWN){Py_DECREF(buf);PyErr_SetString(PySSLErrorObject,"Socket closed without SSL shutdown handshake");returnNULL;}else{/* should contain a zero-length string */_PyString_Resize(&buf,0);returnbuf;}}}do{PySSL_BEGIN_ALLOW_THREADScount=SSL_read(self->ssl,PyString_AsString(buf),len);err=SSL_get_error(self->ssl,count);PySSL_END_ALLOW_THREADSif(PyErr_CheckSignals()){Py_DECREF(buf);returnNULL;}if(err==SSL_ERROR_WANT_READ){sockstate=check_socket_and_wait_for_timeout(self->Socket,0);}elseif(err==SSL_ERROR_WANT_WRITE){sockstate=check_socket_and_wait_for_timeout(self->Socket,1);}elseif((err==SSL_ERROR_ZERO_RETURN)&&(SSL_get_shutdown(self->ssl)==SSL_RECEIVED_SHUTDOWN)){_PyString_Resize(&buf,0);returnbuf;}else{sockstate=SOCKET_OPERATION_OK;}if(sockstate==SOCKET_HAS_TIMED_OUT){PyErr_SetString(PySSLErrorObject,"The read operation timed out");Py_DECREF(buf);returnNULL;}elseif(sockstate==SOCKET_IS_NONBLOCKING){break;}}while(err==SSL_ERROR_WANT_READ||err==SSL_ERROR_WANT_WRITE);if(count<=0){Py_DECREF(buf);returnPySSL_SetError(self,count,__FILE__,__LINE__);}if(count!=len)_PyString_Resize(&buf,count);returnbuf;}PyDoc_STRVAR(PySSL_SSLread_doc,"read([len]) -> string\n\\n\Read up to len bytes from the SSL socket.");staticPyObject*PySSL_SSLshutdown(PySSLObject*self){interr,ssl_err,sockstate,nonblocking;intzeros=0;/* Guard against closed socket */if(self->Socket->sock_fd<0){PyErr_SetString(PySSLErrorObject,"Underlying socket has been closed.");returnNULL;}/* Just in case the blocking state of the socket has been changed */nonblocking=(self->Socket->sock_timeout>=0.0);BIO_set_nbio(SSL_get_rbio(self->ssl),nonblocking);BIO_set_nbio(SSL_get_wbio(self->ssl),nonblocking);while(1){PySSL_BEGIN_ALLOW_THREADS/* Disable read-ahead so that unwrap can work correctly. * Otherwise OpenSSL might read in too much data, * eating clear text data that happens to be * transmitted after the SSL shutdown. * Should be safe to call repeatedly everytime this * function is used and the shutdown_seen_zero != 0 * condition is met. */if(self->shutdown_seen_zero)SSL_set_read_ahead(self->ssl,0);err=SSL_shutdown(self->ssl);PySSL_END_ALLOW_THREADS/* If err == 1, a secure shutdown with SSL_shutdown() is complete */if(err>0)break;if(err==0){/* Don't loop endlessly; instead preserve legacy behaviour of trying SSL_shutdown() only twice. This looks necessary for OpenSSL < 0.9.8m */if(++zeros>1)break;/* Shutdown was sent, now try receiving */self->shutdown_seen_zero=1;continue;}/* Possibly retry shutdown until timeout or failure */ssl_err=SSL_get_error(self->ssl,err);if(ssl_err==SSL_ERROR_WANT_READ)sockstate=check_socket_and_wait_for_timeout(self->Socket,0);elseif(ssl_err==SSL_ERROR_WANT_WRITE)sockstate=check_socket_and_wait_for_timeout(self->Socket,1);elsebreak;if(sockstate==SOCKET_HAS_TIMED_OUT){if(ssl_err==SSL_ERROR_WANT_READ)PyErr_SetString(PySSLErrorObject,"The read operation timed out");elsePyErr_SetString(PySSLErrorObject,"The write operation timed out");returnNULL;}elseif(sockstate==SOCKET_TOO_LARGE_FOR_SELECT){PyErr_SetString(PySSLErrorObject,"Underlying socket too large for select().");returnNULL;}elseif(sockstate!=SOCKET_OPERATION_OK)/* Retain the SSL error code */break;}if(err<0)returnPySSL_SetError(self,err,__FILE__,__LINE__);else{Py_INCREF(self->Socket);return(PyObject*)(self->Socket);}}PyDoc_STRVAR(PySSL_SSLshutdown_doc,"shutdown(s) -> socket\n\\n\Does the SSL shutdown handshake with the remote end, and returns\n\the underlying socket object.");staticPyMethodDefPySSLMethods[]={{"do_handshake",(PyCFunction)PySSL_SSLdo_handshake,METH_NOARGS},{"write",(PyCFunction)PySSL_SSLwrite,METH_VARARGS,PySSL_SSLwrite_doc},{"read",(PyCFunction)PySSL_SSLread,METH_VARARGS,PySSL_SSLread_doc},{"pending",(PyCFunction)PySSL_SSLpending,METH_NOARGS,PySSL_SSLpending_doc},{"server",(PyCFunction)PySSL_server,METH_NOARGS},{"issuer",(PyCFunction)PySSL_issuer,METH_NOARGS},{"peer_certificate",(PyCFunction)PySSL_peercert,METH_VARARGS,PySSL_peercert_doc},{"cipher",(PyCFunction)PySSL_cipher,METH_NOARGS},{"shutdown",(PyCFunction)PySSL_SSLshutdown,METH_NOARGS,PySSL_SSLshutdown_doc},{NULL,NULL}};staticPyObject*PySSL_getattr(PySSLObject*self,char*name){returnPy_FindMethod(PySSLMethods,(PyObject*)self,name);}staticPyTypeObjectPySSL_Type={PyVarObject_HEAD_INIT(NULL,0)"ssl.SSLContext",/*tp_name*/sizeof(PySSLObject),/*tp_basicsize*/0,/*tp_itemsize*//* methods */(destructor)PySSL_dealloc,/*tp_dealloc*/0,/*tp_print*/(getattrfunc)PySSL_getattr,/*tp_getattr*/0,/*tp_setattr*/0,/*tp_compare*/0,/*tp_repr*/0,/*tp_as_number*/0,/*tp_as_sequence*/0,/*tp_as_mapping*/0,/*tp_hash*/};#ifdef HAVE_OPENSSL_RAND/* helper routines for seeding the SSL PRNG */staticPyObject*PySSL_RAND_add(PyObject*self,PyObject*args){char*buf;intlen;doubleentropy;if(!PyArg_ParseTuple(args,"s#d:RAND_add",&buf,&len,&entropy))returnNULL;RAND_add(buf,len,entropy);Py_INCREF(Py_None);returnPy_None;}PyDoc_STRVAR(PySSL_RAND_add_doc,"RAND_add(string, entropy)\n\\n\Mix string into the OpenSSL PRNG state. entropy (a float) is a lower\n\bound on the entropy contained in string. See RFC 1750.");staticPyObject*PySSL_RAND_status(PyObject*self){returnPyInt_FromLong(RAND_status());}PyDoc_STRVAR(PySSL_RAND_status_doc,"RAND_status() -> 0 or 1\n\\n\Returns 1 if the OpenSSL PRNG has been seeded with enough data and 0 if not.\n\It is necessary to seed the PRNG with RAND_add() on some platforms before\n\using the ssl() function.");staticPyObject*PySSL_RAND_egd(PyObject*self,PyObject*arg){intbytes;if(!PyString_Check(arg))returnPyErr_Format(PyExc_TypeError,"RAND_egd() expected string, found %s",Py_TYPE(arg)->tp_name);bytes=RAND_egd(PyString_AS_STRING(arg));if(bytes==-1){PyErr_SetString(PySSLErrorObject,"EGD connection failed or EGD did not return ""enough data to seed the PRNG");returnNULL;}returnPyInt_FromLong(bytes);}PyDoc_STRVAR(PySSL_RAND_egd_doc,"RAND_egd(path) -> bytes\n\\n\Queries the entropy gather daemon (EGD) on the socket named by 'path'.\n\Returns number of bytes read. Raises SSLError if connection to EGD\n\fails or if it does provide enough data to seed PRNG.");#endif/* List of functions exported by this module. */staticPyMethodDefPySSL_methods[]={{"sslwrap",PySSL_sslwrap,METH_VARARGS,ssl_doc},{"_test_decode_cert",PySSL_test_decode_certificate,METH_VARARGS},#ifdef HAVE_OPENSSL_RAND{"RAND_add",PySSL_RAND_add,METH_VARARGS,PySSL_RAND_add_doc},{"RAND_egd",PySSL_RAND_egd,METH_O,PySSL_RAND_egd_doc},{"RAND_status",(PyCFunction)PySSL_RAND_status,METH_NOARGS,PySSL_RAND_status_doc},#endif{NULL,NULL}/* Sentinel */};#ifdef WITH_THREAD/* an implementation of OpenSSL threading operations in terms of the Python C thread library */staticPyThread_type_lock*_ssl_locks=NULL;staticunsignedlong_ssl_thread_id_function(void){returnPyThread_get_thread_ident();}staticvoid_ssl_thread_locking_function(intmode,intn,constchar*file,intline){/* this function is needed to perform locking on shared data structures. (Note that OpenSSL uses a number of global data structures that will be implicitly shared whenever multiple threads use OpenSSL.) Multi-threaded applications will crash at random if it is not set. locking_function() must be able to handle up to CRYPTO_num_locks() different mutex locks. It sets the n-th lock if mode & CRYPTO_LOCK, and releases it otherwise. file and line are the file number of the function setting the lock. They can be useful for debugging. */if((_ssl_locks==NULL)||(n<0)||((unsigned)n>=_ssl_locks_count))return;if(mode&CRYPTO_LOCK){PyThread_acquire_lock(_ssl_locks[n],1);}else{PyThread_release_lock(_ssl_locks[n]);}}staticint_setup_ssl_threads(void){unsignedinti;if(_ssl_locks==NULL){_ssl_locks_count=CRYPTO_num_locks();_ssl_locks=(PyThread_type_lock*)malloc(sizeof(PyThread_type_lock)*_ssl_locks_count);if(_ssl_locks==NULL)return0;memset(_ssl_locks,0,sizeof(PyThread_type_lock)*_ssl_locks_count);for(i=0;i<_ssl_locks_count;i++){_ssl_locks[i]=PyThread_allocate_lock();if(_ssl_locks[i]==NULL){unsignedintj;for(j=0;j<i;j++){PyThread_free_lock(_ssl_locks[j]);}free(_ssl_locks);return0;}}CRYPTO_set_locking_callback(_ssl_thread_locking_function);CRYPTO_set_id_callback(_ssl_thread_id_function);}return1;}#endif /* def HAVE_THREAD */PyDoc_STRVAR(module_doc,"Implementation module for SSL socket operations. See the socket module\n\for documentation.");PyMODINIT_FUNCinit_ssl(void){PyObject*m,*d,*r;unsignedlonglibver;unsignedintmajor,minor,fix,patch,status;Py_TYPE(&PySSL_Type)=&PyType_Type;m=Py_InitModule3("_ssl",PySSL_methods,module_doc);if(m==NULL)return;d=PyModule_GetDict(m);/* Load _socket module and its C API */if(PySocketModule_ImportModuleAndAPI())return;/* Init OpenSSL */SSL_load_error_strings();SSL_library_init();#ifdef WITH_THREAD/* note that this will start threading if not already started */if(!_setup_ssl_threads()){return;}#endifOpenSSL_add_all_algorithms();/* Add symbols to module dict */PySSLErrorObject=PyErr_NewException("ssl.SSLError",PySocketModule.error,NULL);if(PySSLErrorObject==NULL)return;if(PyDict_SetItemString(d,"SSLError",PySSLErrorObject)!=0)return;if(PyDict_SetItemString(d,"SSLType",(PyObject*)&PySSL_Type)!=0)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);/* cert requirements */PyModule_AddIntConstant(m,"CERT_NONE",PY_SSL_CERT_NONE);PyModule_AddIntConstant(m,"CERT_OPTIONAL",PY_SSL_CERT_OPTIONAL);PyModule_AddIntConstant(m,"CERT_REQUIRED",PY_SSL_CERT_REQUIRED);/* protocol versions */PyModule_AddIntConstant(m,"PROTOCOL_SSLv2",PY_SSL_VERSION_SSL2);PyModule_AddIntConstant(m,"PROTOCOL_SSLv3",PY_SSL_VERSION_SSL3);PyModule_AddIntConstant(m,"PROTOCOL_SSLv23",PY_SSL_VERSION_SSL23);PyModule_AddIntConstant(m,"PROTOCOL_TLSv1",PY_SSL_VERSION_TLS1);/* OpenSSL version *//* SSLeay() gives us the version of the library linked against, which could be different from the headers version. */libver=SSLeay();r=PyLong_FromUnsignedLong(libver);if(r==NULL)return;if(PyModule_AddObject(m,"OPENSSL_VERSION_NUMBER",r))return;status=libver&0xF;libver>>=4;patch=libver&0xFF;libver>>=8;fix=libver&0xFF;libver>>=8;minor=libver&0xFF;libver>>=8;major=libver&0xFF;r=Py_BuildValue("IIIII",major,minor,fix,patch,status);if(r==NULL||PyModule_AddObject(m,"OPENSSL_VERSION_INFO",r))return;r=PyString_FromString(SSLeay_version(SSLEAY_VERSION));if(r==NULL||PyModule_AddObject(m,"OPENSSL_VERSION",r))return;}