Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
a4c2a5c9
Commit
a4c2a5c9
authored
May 05, 2010
by
Antoine Pitrou
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Untabify Modules/_ssl.c
parent
91165c0b
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
1346 additions
and
1346 deletions
+1346
-1346
Modules/_ssl.c
Modules/_ssl.c
+1346
-1346
No files found.
Modules/_ssl.c
View file @
a4c2a5c9
...
@@ -19,14 +19,14 @@
...
@@ -19,14 +19,14 @@
#ifdef WITH_THREAD
#ifdef WITH_THREAD
#include "pythread.h"
#include "pythread.h"
#define PySSL_BEGIN_ALLOW_THREADS { \
#define PySSL_BEGIN_ALLOW_THREADS { \
PyThreadState *_save = NULL; \
PyThreadState *_save = NULL; \
if (_ssl_locks_count>0) {_save = PyEval_SaveThread();}
if (_ssl_locks_count>0) {_save = PyEval_SaveThread();}
#define PySSL_BLOCK_THREADS
if (_ssl_locks_count>0){PyEval_RestoreThread(_save)};
#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_UNBLOCK_THREADS
if (_ssl_locks_count>0){_save = PyEval_SaveThread()};
#define PySSL_END_ALLOW_THREADS
if (_ssl_locks_count>0){PyEval_RestoreThread(_save);} \
#define PySSL_END_ALLOW_THREADS
if (_ssl_locks_count>0){PyEval_RestoreThread(_save);} \
}
}
#else
/* no WITH_THREAD */
#else
/* no WITH_THREAD */
#define PySSL_BEGIN_ALLOW_THREADS
#define PySSL_BEGIN_ALLOW_THREADS
#define PySSL_BLOCK_THREADS
#define PySSL_BLOCK_THREADS
...
@@ -36,36 +36,36 @@
...
@@ -36,36 +36,36 @@
#endif
#endif
enum
py_ssl_error
{
enum
py_ssl_error
{
/* these mirror ssl.h */
/* these mirror ssl.h */
PY_SSL_ERROR_NONE
,
PY_SSL_ERROR_NONE
,
PY_SSL_ERROR_SSL
,
PY_SSL_ERROR_SSL
,
PY_SSL_ERROR_WANT_READ
,
PY_SSL_ERROR_WANT_READ
,
PY_SSL_ERROR_WANT_WRITE
,
PY_SSL_ERROR_WANT_WRITE
,
PY_SSL_ERROR_WANT_X509_LOOKUP
,
PY_SSL_ERROR_WANT_X509_LOOKUP
,
PY_SSL_ERROR_SYSCALL
,
/* look at error stack/return value/errno */
PY_SSL_ERROR_SYSCALL
,
/* look at error stack/return value/errno */
PY_SSL_ERROR_ZERO_RETURN
,
PY_SSL_ERROR_ZERO_RETURN
,
PY_SSL_ERROR_WANT_CONNECT
,
PY_SSL_ERROR_WANT_CONNECT
,
/* start of non ssl.h errorcodes */
/* start of non ssl.h errorcodes */
PY_SSL_ERROR_EOF
,
/* special case of SSL_ERROR_SYSCALL */
PY_SSL_ERROR_EOF
,
/* special case of SSL_ERROR_SYSCALL */
PY_SSL_ERROR_INVALID_ERROR_CODE
PY_SSL_ERROR_INVALID_ERROR_CODE
};
};
enum
py_ssl_server_or_client
{
enum
py_ssl_server_or_client
{
PY_SSL_CLIENT
,
PY_SSL_CLIENT
,
PY_SSL_SERVER
PY_SSL_SERVER
};
};
enum
py_ssl_cert_requirements
{
enum
py_ssl_cert_requirements
{
PY_SSL_CERT_NONE
,
PY_SSL_CERT_NONE
,
PY_SSL_CERT_OPTIONAL
,
PY_SSL_CERT_OPTIONAL
,
PY_SSL_CERT_REQUIRED
PY_SSL_CERT_REQUIRED
};
};
enum
py_ssl_version
{
enum
py_ssl_version
{
PY_SSL_VERSION_SSL2
,
PY_SSL_VERSION_SSL2
,
PY_SSL_VERSION_SSL3
,
PY_SSL_VERSION_SSL3
,
PY_SSL_VERSION_SSL23
,
PY_SSL_VERSION_SSL23
,
PY_SSL_VERSION_TLS1
PY_SSL_VERSION_TLS1
};
};
/* Include symbols from _socket module */
/* Include symbols from _socket module */
...
@@ -111,14 +111,14 @@ static unsigned int _ssl_locks_count = 0;
...
@@ -111,14 +111,14 @@ static unsigned int _ssl_locks_count = 0;
#endif
#endif
typedef
struct
{
typedef
struct
{
PyObject_HEAD
PyObject_HEAD
PySocketSockObject
*
Socket
;
/* Socket on which we're layered */
PySocketSockObject
*
Socket
;
/* Socket on which we're layered */
SSL_CTX
*
ctx
;
SSL_CTX
*
ctx
;
SSL
*
ssl
;
SSL
*
ssl
;
X509
*
peer_cert
;
X509
*
peer_cert
;
char
server
[
X509_NAME_MAXLEN
];
char
server
[
X509_NAME_MAXLEN
];
char
issuer
[
X509_NAME_MAXLEN
];
char
issuer
[
X509_NAME_MAXLEN
];
int
shutdown_seen_zero
;
int
shutdown_seen_zero
;
}
PySSLObject
;
}
PySSLObject
;
...
@@ -126,19 +126,19 @@ static PyTypeObject PySSL_Type;
...
@@ -126,19 +126,19 @@ static PyTypeObject PySSL_Type;
static
PyObject
*
PySSL_SSLwrite
(
PySSLObject
*
self
,
PyObject
*
args
);
static
PyObject
*
PySSL_SSLwrite
(
PySSLObject
*
self
,
PyObject
*
args
);
static
PyObject
*
PySSL_SSLread
(
PySSLObject
*
self
,
PyObject
*
args
);
static
PyObject
*
PySSL_SSLread
(
PySSLObject
*
self
,
PyObject
*
args
);
static
int
check_socket_and_wait_for_timeout
(
PySocketSockObject
*
s
,
static
int
check_socket_and_wait_for_timeout
(
PySocketSockObject
*
s
,
int
writing
);
int
writing
);
static
PyObject
*
PySSL_peercert
(
PySSLObject
*
self
,
PyObject
*
args
);
static
PyObject
*
PySSL_peercert
(
PySSLObject
*
self
,
PyObject
*
args
);
static
PyObject
*
PySSL_cipher
(
PySSLObject
*
self
);
static
PyObject
*
PySSL_cipher
(
PySSLObject
*
self
);
#define PySSLObject_Check(v)
(Py_TYPE(v) == &PySSL_Type)
#define PySSLObject_Check(v)
(Py_TYPE(v) == &PySSL_Type)
typedef
enum
{
typedef
enum
{
SOCKET_IS_NONBLOCKING
,
SOCKET_IS_NONBLOCKING
,
SOCKET_IS_BLOCKING
,
SOCKET_IS_BLOCKING
,
SOCKET_HAS_TIMED_OUT
,
SOCKET_HAS_TIMED_OUT
,
SOCKET_HAS_BEEN_CLOSED
,
SOCKET_HAS_BEEN_CLOSED
,
SOCKET_TOO_LARGE_FOR_SELECT
,
SOCKET_TOO_LARGE_FOR_SELECT
,
SOCKET_OPERATION_OK
SOCKET_OPERATION_OK
}
timeout_state
;
}
timeout_state
;
/* Wrap error strings with filename and line # */
/* Wrap error strings with filename and line # */
...
@@ -155,294 +155,294 @@ typedef enum {
...
@@ -155,294 +155,294 @@ typedef enum {
static
PyObject
*
static
PyObject
*
PySSL_SetError
(
PySSLObject
*
obj
,
int
ret
,
char
*
filename
,
int
lineno
)
PySSL_SetError
(
PySSLObject
*
obj
,
int
ret
,
char
*
filename
,
int
lineno
)
{
{
PyObject
*
v
;
PyObject
*
v
;
char
buf
[
2048
];
char
buf
[
2048
];
char
*
errstr
;
char
*
errstr
;
int
err
;
int
err
;
enum
py_ssl_error
p
=
PY_SSL_ERROR_NONE
;
enum
py_ssl_error
p
=
PY_SSL_ERROR_NONE
;
assert
(
ret
<=
0
);
assert
(
ret
<=
0
);
if
(
obj
->
ssl
!=
NULL
)
{
if
(
obj
->
ssl
!=
NULL
)
{
err
=
SSL_get_error
(
obj
->
ssl
,
ret
);
err
=
SSL_get_error
(
obj
->
ssl
,
ret
);
switch
(
err
)
{
switch
(
err
)
{
case
SSL_ERROR_ZERO_RETURN
:
case
SSL_ERROR_ZERO_RETURN
:
errstr
=
"TLS/SSL connection has been closed"
;
errstr
=
"TLS/SSL connection has been closed"
;
p
=
PY_SSL_ERROR_ZERO_RETURN
;
p
=
PY_SSL_ERROR_ZERO_RETURN
;
break
;
break
;
case
SSL_ERROR_WANT_READ
:
case
SSL_ERROR_WANT_READ
:
errstr
=
"The operation did not complete (read)"
;
errstr
=
"The operation did not complete (read)"
;
p
=
PY_SSL_ERROR_WANT_READ
;
p
=
PY_SSL_ERROR_WANT_READ
;
break
;
break
;
case
SSL_ERROR_WANT_WRITE
:
case
SSL_ERROR_WANT_WRITE
:
p
=
PY_SSL_ERROR_WANT_WRITE
;
p
=
PY_SSL_ERROR_WANT_WRITE
;
errstr
=
"The operation did not complete (write)"
;
errstr
=
"The operation did not complete (write)"
;
break
;
break
;
case
SSL_ERROR_WANT_X509_LOOKUP
:
case
SSL_ERROR_WANT_X509_LOOKUP
:
p
=
PY_SSL_ERROR_WANT_X509_LOOKUP
;
p
=
PY_SSL_ERROR_WANT_X509_LOOKUP
;
errstr
=
errstr
=
"The operation did not complete (X509 lookup)"
;
"The operation did not complete (X509 lookup)"
;
break
;
break
;
case
SSL_ERROR_WANT_CONNECT
:
case
SSL_ERROR_WANT_CONNECT
:
p
=
PY_SSL_ERROR_WANT_CONNECT
;
p
=
PY_SSL_ERROR_WANT_CONNECT
;
errstr
=
"The operation did not complete (connect)"
;
errstr
=
"The operation did not complete (connect)"
;
break
;
break
;
case
SSL_ERROR_SYSCALL
:
case
SSL_ERROR_SYSCALL
:
{
{
unsigned
long
e
=
ERR_get_error
();
unsigned
long
e
=
ERR_get_error
();
if
(
e
==
0
)
{
if
(
e
==
0
)
{
if
(
ret
==
0
||
!
obj
->
Socket
)
{
if
(
ret
==
0
||
!
obj
->
Socket
)
{
p
=
PY_SSL_ERROR_EOF
;
p
=
PY_SSL_ERROR_EOF
;
errstr
=
errstr
=
"EOF occurred in violation of protocol"
;
"EOF occurred in violation of protocol"
;
}
else
if
(
ret
==
-
1
)
{
}
else
if
(
ret
==
-
1
)
{
/* underlying BIO reported an I/O error */
/* underlying BIO reported an I/O error */
return
obj
->
Socket
->
errorhandler
();
return
obj
->
Socket
->
errorhandler
();
}
else
{
/* possible? */
}
else
{
/* possible? */
p
=
PY_SSL_ERROR_SYSCALL
;
p
=
PY_SSL_ERROR_SYSCALL
;
errstr
=
"Some I/O error occurred"
;
errstr
=
"Some I/O error occurred"
;
}
}
}
else
{
}
else
{
p
=
PY_SSL_ERROR_SYSCALL
;
p
=
PY_SSL_ERROR_SYSCALL
;
/* XXX Protected by global interpreter lock */
/* XXX Protected by global interpreter lock */
errstr
=
ERR_error_string
(
e
,
NULL
);
errstr
=
ERR_error_string
(
e
,
NULL
);
}
}
break
;
break
;
}
}
case
SSL_ERROR_SSL
:
case
SSL_ERROR_SSL
:
{
{
unsigned
long
e
=
ERR_get_error
();
unsigned
long
e
=
ERR_get_error
();
p
=
PY_SSL_ERROR_SSL
;
p
=
PY_SSL_ERROR_SSL
;
if
(
e
!=
0
)
if
(
e
!=
0
)
/* XXX Protected by global interpreter lock */
/* XXX Protected by global interpreter lock */
errstr
=
ERR_error_string
(
e
,
NULL
);
errstr
=
ERR_error_string
(
e
,
NULL
);
else
{
/* possible? */
else
{
/* possible? */
errstr
=
errstr
=
"A failure in the SSL library occurred"
;
"A failure in the SSL library occurred"
;
}
}
break
;
break
;
}
}
default:
default:
p
=
PY_SSL_ERROR_INVALID_ERROR_CODE
;
p
=
PY_SSL_ERROR_INVALID_ERROR_CODE
;
errstr
=
"Invalid error code"
;
errstr
=
"Invalid error code"
;
}
}
}
else
{
}
else
{
errstr
=
ERR_error_string
(
ERR_peek_last_error
(),
NULL
);
errstr
=
ERR_error_string
(
ERR_peek_last_error
(),
NULL
);
}
}
PyOS_snprintf
(
buf
,
sizeof
(
buf
),
"_ssl.c:%d: %s"
,
lineno
,
errstr
);
PyOS_snprintf
(
buf
,
sizeof
(
buf
),
"_ssl.c:%d: %s"
,
lineno
,
errstr
);
v
=
Py_BuildValue
(
"(is)"
,
p
,
buf
);
v
=
Py_BuildValue
(
"(is)"
,
p
,
buf
);
if
(
v
!=
NULL
)
{
if
(
v
!=
NULL
)
{
PyErr_SetObject
(
PySSLErrorObject
,
v
);
PyErr_SetObject
(
PySSLErrorObject
,
v
);
Py_DECREF
(
v
);
Py_DECREF
(
v
);
}
}
return
NULL
;
return
NULL
;
}
}
static
PyObject
*
static
PyObject
*
_setSSLError
(
char
*
errstr
,
int
errcode
,
char
*
filename
,
int
lineno
)
{
_setSSLError
(
char
*
errstr
,
int
errcode
,
char
*
filename
,
int
lineno
)
{
char
buf
[
2048
];
char
buf
[
2048
];
PyObject
*
v
;
PyObject
*
v
;
if
(
errstr
==
NULL
)
{
if
(
errstr
==
NULL
)
{
errcode
=
ERR_peek_last_error
();
errcode
=
ERR_peek_last_error
();
errstr
=
ERR_error_string
(
errcode
,
NULL
);
errstr
=
ERR_error_string
(
errcode
,
NULL
);
}
}
PyOS_snprintf
(
buf
,
sizeof
(
buf
),
"_ssl.c:%d: %s"
,
lineno
,
errstr
);
PyOS_snprintf
(
buf
,
sizeof
(
buf
),
"_ssl.c:%d: %s"
,
lineno
,
errstr
);
v
=
Py_BuildValue
(
"(is)"
,
errcode
,
buf
);
v
=
Py_BuildValue
(
"(is)"
,
errcode
,
buf
);
if
(
v
!=
NULL
)
{
if
(
v
!=
NULL
)
{
PyErr_SetObject
(
PySSLErrorObject
,
v
);
PyErr_SetObject
(
PySSLErrorObject
,
v
);
Py_DECREF
(
v
);
Py_DECREF
(
v
);
}
}
return
NULL
;
return
NULL
;
}
}
static
PySSLObject
*
static
PySSLObject
*
newPySSLObject
(
PySocketSockObject
*
Sock
,
char
*
key_file
,
char
*
cert_file
,
newPySSLObject
(
PySocketSockObject
*
Sock
,
char
*
key_file
,
char
*
cert_file
,
enum
py_ssl_server_or_client
socket_type
,
enum
py_ssl_server_or_client
socket_type
,
enum
py_ssl_cert_requirements
certreq
,
enum
py_ssl_cert_requirements
certreq
,
enum
py_ssl_version
proto_version
,
enum
py_ssl_version
proto_version
,
char
*
cacerts_file
,
char
*
ciphers
)
char
*
cacerts_file
,
char
*
ciphers
)
{
{
PySSLObject
*
self
;
PySSLObject
*
self
;
char
*
errstr
=
NULL
;
char
*
errstr
=
NULL
;
int
ret
;
int
ret
;
int
verification_mode
;
int
verification_mode
;
self
=
PyObject_New
(
PySSLObject
,
&
PySSL_Type
);
/* Create new object */
self
=
PyObject_New
(
PySSLObject
,
&
PySSL_Type
);
/* Create new object */
if
(
self
==
NULL
)
if
(
self
==
NULL
)
return
NULL
;
return
NULL
;
memset
(
self
->
server
,
'\0'
,
sizeof
(
char
)
*
X509_NAME_MAXLEN
);
memset
(
self
->
server
,
'\0'
,
sizeof
(
char
)
*
X509_NAME_MAXLEN
);
memset
(
self
->
issuer
,
'\0'
,
sizeof
(
char
)
*
X509_NAME_MAXLEN
);
memset
(
self
->
issuer
,
'\0'
,
sizeof
(
char
)
*
X509_NAME_MAXLEN
);
self
->
peer_cert
=
NULL
;
self
->
peer_cert
=
NULL
;
self
->
ssl
=
NULL
;
self
->
ssl
=
NULL
;
self
->
ctx
=
NULL
;
self
->
ctx
=
NULL
;
self
->
Socket
=
NULL
;
self
->
Socket
=
NULL
;
/* Make sure the SSL error state is initialized */
/* Make sure the SSL error state is initialized */
(
void
)
ERR_get_state
();
(
void
)
ERR_get_state
();
ERR_clear_error
();
ERR_clear_error
();
if
((
key_file
&&
!
cert_file
)
||
(
!
key_file
&&
cert_file
))
{
if
((
key_file
&&
!
cert_file
)
||
(
!
key_file
&&
cert_file
))
{
errstr
=
ERRSTR
(
"Both the key & certificate files "
errstr
=
ERRSTR
(
"Both the key & certificate files "
"must be specified"
);
"must be specified"
);
goto
fail
;
goto
fail
;
}
}
if
((
socket_type
==
PY_SSL_SERVER
)
&&
if
((
socket_type
==
PY_SSL_SERVER
)
&&
((
key_file
==
NULL
)
||
(
cert_file
==
NULL
)))
{
((
key_file
==
NULL
)
||
(
cert_file
==
NULL
)))
{
errstr
=
ERRSTR
(
"Both the key & certificate files "
errstr
=
ERRSTR
(
"Both the key & certificate files "
"must be specified for server-side operation"
);
"must be specified for server-side operation"
);
goto
fail
;
goto
fail
;
}
}
PySSL_BEGIN_ALLOW_THREADS
PySSL_BEGIN_ALLOW_THREADS
if
(
proto_version
==
PY_SSL_VERSION_TLS1
)
if
(
proto_version
==
PY_SSL_VERSION_TLS1
)
self
->
ctx
=
SSL_CTX_new
(
TLSv1_method
());
/* Set up context */
self
->
ctx
=
SSL_CTX_new
(
TLSv1_method
());
/* Set up context */
else
if
(
proto_version
==
PY_SSL_VERSION_SSL3
)
else
if
(
proto_version
==
PY_SSL_VERSION_SSL3
)
self
->
ctx
=
SSL_CTX_new
(
SSLv3_method
());
/* Set up context */
self
->
ctx
=
SSL_CTX_new
(
SSLv3_method
());
/* Set up context */
else
if
(
proto_version
==
PY_SSL_VERSION_SSL2
)
else
if
(
proto_version
==
PY_SSL_VERSION_SSL2
)
self
->
ctx
=
SSL_CTX_new
(
SSLv2_method
());
/* Set up context */
self
->
ctx
=
SSL_CTX_new
(
SSLv2_method
());
/* Set up context */
else
if
(
proto_version
==
PY_SSL_VERSION_SSL23
)
else
if
(
proto_version
==
PY_SSL_VERSION_SSL23
)
self
->
ctx
=
SSL_CTX_new
(
SSLv23_method
());
/* Set up context */
self
->
ctx
=
SSL_CTX_new
(
SSLv23_method
());
/* Set up context */
PySSL_END_ALLOW_THREADS
PySSL_END_ALLOW_THREADS
if
(
self
->
ctx
==
NULL
)
{
if
(
self
->
ctx
==
NULL
)
{
errstr
=
ERRSTR
(
"Invalid SSL protocol variant specified."
);
errstr
=
ERRSTR
(
"Invalid SSL protocol variant specified."
);
goto
fail
;
goto
fail
;
}
}
if
(
ciphers
!=
NULL
)
{
if
(
ciphers
!=
NULL
)
{
ret
=
SSL_CTX_set_cipher_list
(
self
->
ctx
,
ciphers
);
ret
=
SSL_CTX_set_cipher_list
(
self
->
ctx
,
ciphers
);
if
(
ret
==
0
)
{
if
(
ret
==
0
)
{
errstr
=
ERRSTR
(
"No cipher can be selected."
);
errstr
=
ERRSTR
(
"No cipher can be selected."
);
goto
fail
;
goto
fail
;
}
}
}
}
if
(
certreq
!=
PY_SSL_CERT_NONE
)
{
if
(
certreq
!=
PY_SSL_CERT_NONE
)
{
if
(
cacerts_file
==
NULL
)
{
if
(
cacerts_file
==
NULL
)
{
errstr
=
ERRSTR
(
"No root certificates specified for "
errstr
=
ERRSTR
(
"No root certificates specified for "
"verification of other-side certificates."
);
"verification of other-side certificates."
);
goto
fail
;
goto
fail
;
}
else
{
}
else
{
PySSL_BEGIN_ALLOW_THREADS
PySSL_BEGIN_ALLOW_THREADS
ret
=
SSL_CTX_load_verify_locations
(
self
->
ctx
,
ret
=
SSL_CTX_load_verify_locations
(
self
->
ctx
,
cacerts_file
,
cacerts_file
,
NULL
);
NULL
);
PySSL_END_ALLOW_THREADS
PySSL_END_ALLOW_THREADS
if
(
ret
!=
1
)
{
if
(
ret
!=
1
)
{
_setSSLError
(
NULL
,
0
,
__FILE__
,
__LINE__
);
_setSSLError
(
NULL
,
0
,
__FILE__
,
__LINE__
);
goto
fail
;
goto
fail
;
}
}
}
}
}
}
if
(
key_file
)
{
if
(
key_file
)
{
PySSL_BEGIN_ALLOW_THREADS
PySSL_BEGIN_ALLOW_THREADS
ret
=
SSL_CTX_use_PrivateKey_file
(
self
->
ctx
,
key_file
,
ret
=
SSL_CTX_use_PrivateKey_file
(
self
->
ctx
,
key_file
,
SSL_FILETYPE_PEM
);
SSL_FILETYPE_PEM
);
PySSL_END_ALLOW_THREADS
PySSL_END_ALLOW_THREADS
if
(
ret
!=
1
)
{
if
(
ret
!=
1
)
{
_setSSLError
(
NULL
,
ret
,
__FILE__
,
__LINE__
);
_setSSLError
(
NULL
,
ret
,
__FILE__
,
__LINE__
);
goto
fail
;
goto
fail
;
}
}
PySSL_BEGIN_ALLOW_THREADS
PySSL_BEGIN_ALLOW_THREADS
ret
=
SSL_CTX_use_certificate_chain_file
(
self
->
ctx
,
ret
=
SSL_CTX_use_certificate_chain_file
(
self
->
ctx
,
cert_file
);
cert_file
);
PySSL_END_ALLOW_THREADS
PySSL_END_ALLOW_THREADS
if
(
ret
!=
1
)
{
if
(
ret
!=
1
)
{
/*
/*
fprintf(stderr, "ret is %d, errcode is %lu, %lu, with file \"%s\"\n",
fprintf(stderr, "ret is %d, errcode is %lu, %lu, with file \"%s\"\n",
ret, ERR_peek_error(), ERR_peek_last_error(), cert_file);
ret, ERR_peek_error(), ERR_peek_last_error(), cert_file);
*/
*/
if
(
ERR_peek_last_error
()
!=
0
)
{
if
(
ERR_peek_last_error
()
!=
0
)
{
_setSSLError
(
NULL
,
ret
,
__FILE__
,
__LINE__
);
_setSSLError
(
NULL
,
ret
,
__FILE__
,
__LINE__
);
goto
fail
;
goto
fail
;
}
}
}
}
}
}
/* ssl compatibility */
/* ssl compatibility */
SSL_CTX_set_options
(
self
->
ctx
,
SSL_OP_ALL
);
SSL_CTX_set_options
(
self
->
ctx
,
SSL_OP_ALL
);
verification_mode
=
SSL_VERIFY_NONE
;
verification_mode
=
SSL_VERIFY_NONE
;
if
(
certreq
==
PY_SSL_CERT_OPTIONAL
)
if
(
certreq
==
PY_SSL_CERT_OPTIONAL
)
verification_mode
=
SSL_VERIFY_PEER
;
verification_mode
=
SSL_VERIFY_PEER
;
else
if
(
certreq
==
PY_SSL_CERT_REQUIRED
)
else
if
(
certreq
==
PY_SSL_CERT_REQUIRED
)
verification_mode
=
(
SSL_VERIFY_PEER
|
verification_mode
=
(
SSL_VERIFY_PEER
|
SSL_VERIFY_FAIL_IF_NO_PEER_CERT
);
SSL_VERIFY_FAIL_IF_NO_PEER_CERT
);
SSL_CTX_set_verify
(
self
->
ctx
,
verification_mode
,
SSL_CTX_set_verify
(
self
->
ctx
,
verification_mode
,
NULL
);
/* set verify lvl */
NULL
);
/* set verify lvl */
PySSL_BEGIN_ALLOW_THREADS
PySSL_BEGIN_ALLOW_THREADS
self
->
ssl
=
SSL_new
(
self
->
ctx
);
/* New ssl struct */
self
->
ssl
=
SSL_new
(
self
->
ctx
);
/* New ssl struct */
PySSL_END_ALLOW_THREADS
PySSL_END_ALLOW_THREADS
SSL_set_fd
(
self
->
ssl
,
Sock
->
sock_fd
);
/* Set the socket for SSL */
SSL_set_fd
(
self
->
ssl
,
Sock
->
sock_fd
);
/* Set the socket for SSL */
#ifdef SSL_MODE_AUTO_RETRY
#ifdef SSL_MODE_AUTO_RETRY
SSL_set_mode
(
self
->
ssl
,
SSL_MODE_AUTO_RETRY
);
SSL_set_mode
(
self
->
ssl
,
SSL_MODE_AUTO_RETRY
);
#endif
#endif
/* If the socket is in non-blocking mode or timeout mode, set the BIO
/* If the socket is in non-blocking mode or timeout mode, set the BIO
* to non-blocking mode (blocking is the default)
* to non-blocking mode (blocking is the default)
*/
*/
if
(
Sock
->
sock_timeout
>=
0
.
0
)
{
if
(
Sock
->
sock_timeout
>=
0
.
0
)
{
/* Set both the read and write BIO's to non-blocking mode */
/* 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_rbio
(
self
->
ssl
),
1
);
BIO_set_nbio
(
SSL_get_wbio
(
self
->
ssl
),
1
);
BIO_set_nbio
(
SSL_get_wbio
(
self
->
ssl
),
1
);
}
}
PySSL_BEGIN_ALLOW_THREADS
PySSL_BEGIN_ALLOW_THREADS
if
(
socket_type
==
PY_SSL_CLIENT
)
if
(
socket_type
==
PY_SSL_CLIENT
)
SSL_set_connect_state
(
self
->
ssl
);
SSL_set_connect_state
(
self
->
ssl
);
else
else
SSL_set_accept_state
(
self
->
ssl
);
SSL_set_accept_state
(
self
->
ssl
);
PySSL_END_ALLOW_THREADS
PySSL_END_ALLOW_THREADS
self
->
Socket
=
Sock
;
self
->
Socket
=
Sock
;
Py_INCREF
(
self
->
Socket
);
Py_INCREF
(
self
->
Socket
);
return
self
;
return
self
;
fail:
fail:
if
(
errstr
)
if
(
errstr
)
PyErr_SetString
(
PySSLErrorObject
,
errstr
);
PyErr_SetString
(
PySSLErrorObject
,
errstr
);
Py_DECREF
(
self
);
Py_DECREF
(
self
);
return
NULL
;
return
NULL
;
}
}
static
PyObject
*
static
PyObject
*
PySSL_sslwrap
(
PyObject
*
self
,
PyObject
*
args
)
PySSL_sslwrap
(
PyObject
*
self
,
PyObject
*
args
)
{
{
PySocketSockObject
*
Sock
;
PySocketSockObject
*
Sock
;
int
server_side
=
0
;
int
server_side
=
0
;
int
verification_mode
=
PY_SSL_CERT_NONE
;
int
verification_mode
=
PY_SSL_CERT_NONE
;
int
protocol
=
PY_SSL_VERSION_SSL23
;
int
protocol
=
PY_SSL_VERSION_SSL23
;
char
*
key_file
=
NULL
;
char
*
key_file
=
NULL
;
char
*
cert_file
=
NULL
;
char
*
cert_file
=
NULL
;
char
*
cacerts_file
=
NULL
;
char
*
cacerts_file
=
NULL
;
char
*
ciphers
=
NULL
;
char
*
ciphers
=
NULL
;
if
(
!
PyArg_ParseTuple
(
args
,
"O!i|zziizz:sslwrap"
,
if
(
!
PyArg_ParseTuple
(
args
,
"O!i|zziizz:sslwrap"
,
PySocketModule
.
Sock_Type
,
PySocketModule
.
Sock_Type
,
&
Sock
,
&
Sock
,
&
server_side
,
&
server_side
,
&
key_file
,
&
cert_file
,
&
key_file
,
&
cert_file
,
&
verification_mode
,
&
protocol
,
&
verification_mode
,
&
protocol
,
&
cacerts_file
,
&
ciphers
))
&
cacerts_file
,
&
ciphers
))
return
NULL
;
return
NULL
;
/*
/*
fprintf(stderr,
fprintf(stderr,
"server_side is %d, keyfile %p, certfile %p, verify_mode %d, "
"server_side is %d, keyfile %p, certfile %p, verify_mode %d, "
"protocol %d, certs %p\n",
"protocol %d, certs %p\n",
server_side, key_file, cert_file, verification_mode,
server_side, key_file, cert_file, verification_mode,
protocol, cacerts_file);
protocol, cacerts_file);
*/
*/
return
(
PyObject
*
)
newPySSLObject
(
Sock
,
key_file
,
cert_file
,
return
(
PyObject
*
)
newPySSLObject
(
Sock
,
key_file
,
cert_file
,
server_side
,
verification_mode
,
server_side
,
verification_mode
,
protocol
,
cacerts_file
,
protocol
,
cacerts_file
,
ciphers
);
ciphers
);
}
}
PyDoc_STRVAR
(
ssl_doc
,
PyDoc_STRVAR
(
ssl_doc
,
...
@@ -453,577 +453,577 @@ PyDoc_STRVAR(ssl_doc,
...
@@ -453,577 +453,577 @@ PyDoc_STRVAR(ssl_doc,
static
PyObject
*
PySSL_SSLdo_handshake
(
PySSLObject
*
self
)
static
PyObject
*
PySSL_SSLdo_handshake
(
PySSLObject
*
self
)
{
{
int
ret
;
int
ret
;
int
err
;
int
err
;
int
sockstate
,
nonblocking
;
int
sockstate
,
nonblocking
;
/* just in case the blocking state of the socket has been changed */
/* just in case the blocking state of the socket has been changed */
nonblocking
=
(
self
->
Socket
->
sock_timeout
>=
0
.
0
);
nonblocking
=
(
self
->
Socket
->
sock_timeout
>=
0
.
0
);
BIO_set_nbio
(
SSL_get_rbio
(
self
->
ssl
),
nonblocking
);
BIO_set_nbio
(
SSL_get_rbio
(
self
->
ssl
),
nonblocking
);
BIO_set_nbio
(
SSL_get_wbio
(
self
->
ssl
),
nonblocking
);
BIO_set_nbio
(
SSL_get_wbio
(
self
->
ssl
),
nonblocking
);
/* Actually negotiate SSL connection */
/* Actually negotiate SSL connection */
/* XXX If SSL_do_handshake() returns 0, it's also a failure. */
/* XXX If SSL_do_handshake() returns 0, it's also a failure. */
do
{
do
{
PySSL_BEGIN_ALLOW_THREADS
PySSL_BEGIN_ALLOW_THREADS
ret
=
SSL_do_handshake
(
self
->
ssl
);
ret
=
SSL_do_handshake
(
self
->
ssl
);
err
=
SSL_get_error
(
self
->
ssl
,
ret
);
err
=
SSL_get_error
(
self
->
ssl
,
ret
);
PySSL_END_ALLOW_THREADS
PySSL_END_ALLOW_THREADS
if
(
PyErr_CheckSignals
())
{
if
(
PyErr_CheckSignals
())
{
return
NULL
;
return
NULL
;
}
}
if
(
err
==
SSL_ERROR_WANT_READ
)
{
if
(
err
==
SSL_ERROR_WANT_READ
)
{
sockstate
=
check_socket_and_wait_for_timeout
(
self
->
Socket
,
0
);
sockstate
=
check_socket_and_wait_for_timeout
(
self
->
Socket
,
0
);
}
else
if
(
err
==
SSL_ERROR_WANT_WRITE
)
{
}
else
if
(
err
==
SSL_ERROR_WANT_WRITE
)
{
sockstate
=
check_socket_and_wait_for_timeout
(
self
->
Socket
,
1
);
sockstate
=
check_socket_and_wait_for_timeout
(
self
->
Socket
,
1
);
}
else
{
}
else
{
sockstate
=
SOCKET_OPERATION_OK
;
sockstate
=
SOCKET_OPERATION_OK
;
}
}
if
(
sockstate
==
SOCKET_HAS_TIMED_OUT
)
{
if
(
sockstate
==
SOCKET_HAS_TIMED_OUT
)
{
PyErr_SetString
(
PySSLErrorObject
,
PyErr_SetString
(
PySSLErrorObject
,
ERRSTR
(
"The handshake operation timed out"
));
ERRSTR
(
"The handshake operation timed out"
));
return
NULL
;
return
NULL
;
}
else
if
(
sockstate
==
SOCKET_HAS_BEEN_CLOSED
)
{
}
else
if
(
sockstate
==
SOCKET_HAS_BEEN_CLOSED
)
{
PyErr_SetString
(
PySSLErrorObject
,
PyErr_SetString
(
PySSLErrorObject
,
ERRSTR
(
"Underlying socket has been closed."
));
ERRSTR
(
"Underlying socket has been closed."
));
return
NULL
;
return
NULL
;
}
else
if
(
sockstate
==
SOCKET_TOO_LARGE_FOR_SELECT
)
{
}
else
if
(
sockstate
==
SOCKET_TOO_LARGE_FOR_SELECT
)
{
PyErr_SetString
(
PySSLErrorObject
,
PyErr_SetString
(
PySSLErrorObject
,
ERRSTR
(
"Underlying socket too large for select()."
));
ERRSTR
(
"Underlying socket too large for select()."
));
return
NULL
;
return
NULL
;
}
else
if
(
sockstate
==
SOCKET_IS_NONBLOCKING
)
{
}
else
if
(
sockstate
==
SOCKET_IS_NONBLOCKING
)
{
break
;
break
;
}
}
}
while
(
err
==
SSL_ERROR_WANT_READ
||
err
==
SSL_ERROR_WANT_WRITE
);
}
while
(
err
==
SSL_ERROR_WANT_READ
||
err
==
SSL_ERROR_WANT_WRITE
);
if
(
ret
<
1
)
if
(
ret
<
1
)
return
PySSL_SetError
(
self
,
ret
,
__FILE__
,
__LINE__
);
return
PySSL_SetError
(
self
,
ret
,
__FILE__
,
__LINE__
);
self
->
ssl
->
debug
=
1
;
self
->
ssl
->
debug
=
1
;
if
(
self
->
peer_cert
)
if
(
self
->
peer_cert
)
X509_free
(
self
->
peer_cert
);
X509_free
(
self
->
peer_cert
);
PySSL_BEGIN_ALLOW_THREADS
PySSL_BEGIN_ALLOW_THREADS
if
((
self
->
peer_cert
=
SSL_get_peer_certificate
(
self
->
ssl
)))
{
if
((
self
->
peer_cert
=
SSL_get_peer_certificate
(
self
->
ssl
)))
{
X509_NAME_oneline
(
X509_get_subject_name
(
self
->
peer_cert
),
X509_NAME_oneline
(
X509_get_subject_name
(
self
->
peer_cert
),
self
->
server
,
X509_NAME_MAXLEN
);
self
->
server
,
X509_NAME_MAXLEN
);
X509_NAME_oneline
(
X509_get_issuer_name
(
self
->
peer_cert
),
X509_NAME_oneline
(
X509_get_issuer_name
(
self
->
peer_cert
),
self
->
issuer
,
X509_NAME_MAXLEN
);
self
->
issuer
,
X509_NAME_MAXLEN
);
}
}
PySSL_END_ALLOW_THREADS
PySSL_END_ALLOW_THREADS
Py_INCREF
(
Py_None
);
Py_INCREF
(
Py_None
);
return
Py_None
;
return
Py_None
;
}
}
static
PyObject
*
static
PyObject
*
PySSL_server
(
PySSLObject
*
self
)
PySSL_server
(
PySSLObject
*
self
)
{
{
return
PyString_FromString
(
self
->
server
);
return
PyString_FromString
(
self
->
server
);
}
}
static
PyObject
*
static
PyObject
*
PySSL_issuer
(
PySSLObject
*
self
)
PySSL_issuer
(
PySSLObject
*
self
)
{
{
return
PyString_FromString
(
self
->
issuer
);
return
PyString_FromString
(
self
->
issuer
);
}
}
static
PyObject
*
static
PyObject
*
_create_tuple_for_attribute
(
ASN1_OBJECT
*
name
,
ASN1_STRING
*
value
)
{
_create_tuple_for_attribute
(
ASN1_OBJECT
*
name
,
ASN1_STRING
*
value
)
{
char
namebuf
[
X509_NAME_MAXLEN
];
char
namebuf
[
X509_NAME_MAXLEN
];
int
buflen
;
int
buflen
;
PyObject
*
name_obj
;
PyObject
*
name_obj
;
PyObject
*
value_obj
;
PyObject
*
value_obj
;
PyObject
*
attr
;
PyObject
*
attr
;
unsigned
char
*
valuebuf
=
NULL
;
unsigned
char
*
valuebuf
=
NULL
;
buflen
=
OBJ_obj2txt
(
namebuf
,
sizeof
(
namebuf
),
name
,
0
);
buflen
=
OBJ_obj2txt
(
namebuf
,
sizeof
(
namebuf
),
name
,
0
);
if
(
buflen
<
0
)
{
if
(
buflen
<
0
)
{
_setSSLError
(
NULL
,
0
,
__FILE__
,
__LINE__
);
_setSSLError
(
NULL
,
0
,
__FILE__
,
__LINE__
);
goto
fail
;
goto
fail
;
}
}
name_obj
=
PyString_FromStringAndSize
(
namebuf
,
buflen
);
name_obj
=
PyString_FromStringAndSize
(
namebuf
,
buflen
);
if
(
name_obj
==
NULL
)
if
(
name_obj
==
NULL
)
goto
fail
;
goto
fail
;
buflen
=
ASN1_STRING_to_UTF8
(
&
valuebuf
,
value
);
buflen
=
ASN1_STRING_to_UTF8
(
&
valuebuf
,
value
);
if
(
buflen
<
0
)
{
if
(
buflen
<
0
)
{
_setSSLError
(
NULL
,
0
,
__FILE__
,
__LINE__
);
_setSSLError
(
NULL
,
0
,
__FILE__
,
__LINE__
);
Py_DECREF
(
name_obj
);
Py_DECREF
(
name_obj
);
goto
fail
;
goto
fail
;
}
}
value_obj
=
PyUnicode_DecodeUTF8
((
char
*
)
valuebuf
,
value_obj
=
PyUnicode_DecodeUTF8
((
char
*
)
valuebuf
,
buflen
,
"strict"
);
buflen
,
"strict"
);
OPENSSL_free
(
valuebuf
);
OPENSSL_free
(
valuebuf
);
if
(
value_obj
==
NULL
)
{
if
(
value_obj
==
NULL
)
{
Py_DECREF
(
name_obj
);
Py_DECREF
(
name_obj
);
goto
fail
;
goto
fail
;
}
}
attr
=
PyTuple_New
(
2
);
attr
=
PyTuple_New
(
2
);
if
(
attr
==
NULL
)
{
if
(
attr
==
NULL
)
{
Py_DECREF
(
name_obj
);
Py_DECREF
(
name_obj
);
Py_DECREF
(
value_obj
);
Py_DECREF
(
value_obj
);
goto
fail
;
goto
fail
;
}
}
PyTuple_SET_ITEM
(
attr
,
0
,
name_obj
);
PyTuple_SET_ITEM
(
attr
,
0
,
name_obj
);
PyTuple_SET_ITEM
(
attr
,
1
,
value_obj
);
PyTuple_SET_ITEM
(
attr
,
1
,
value_obj
);
return
attr
;
return
attr
;
fail:
fail:
return
NULL
;
return
NULL
;
}
}
static
PyObject
*
static
PyObject
*
_create_tuple_for_X509_NAME
(
X509_NAME
*
xname
)
_create_tuple_for_X509_NAME
(
X509_NAME
*
xname
)
{
{
PyObject
*
dn
=
NULL
;
/* tuple which represents the "distinguished name" */
PyObject
*
dn
=
NULL
;
/* tuple which represents the "distinguished name" */
PyObject
*
rdn
=
NULL
;
/* tuple to hold a "relative distinguished name" */
PyObject
*
rdn
=
NULL
;
/* tuple to hold a "relative distinguished name" */
PyObject
*
rdnt
;
PyObject
*
rdnt
;
PyObject
*
attr
=
NULL
;
/* tuple to hold an attribute */
PyObject
*
attr
=
NULL
;
/* tuple to hold an attribute */
int
entry_count
=
X509_NAME_entry_count
(
xname
);
int
entry_count
=
X509_NAME_entry_count
(
xname
);
X509_NAME_ENTRY
*
entry
;
X509_NAME_ENTRY
*
entry
;
ASN1_OBJECT
*
name
;
ASN1_OBJECT
*
name
;
ASN1_STRING
*
value
;
ASN1_STRING
*
value
;
int
index_counter
;
int
index_counter
;
int
rdn_level
=
-
1
;
int
rdn_level
=
-
1
;
int
retcode
;
int
retcode
;
dn
=
PyList_New
(
0
);
dn
=
PyList_New
(
0
);
if
(
dn
==
NULL
)
if
(
dn
==
NULL
)
return
NULL
;
return
NULL
;
/* now create another tuple to hold the top-level RDN */
/* now create another tuple to hold the top-level RDN */
rdn
=
PyList_New
(
0
);
rdn
=
PyList_New
(
0
);
if
(
rdn
==
NULL
)
if
(
rdn
==
NULL
)
goto
fail0
;
goto
fail0
;
for
(
index_counter
=
0
;
for
(
index_counter
=
0
;
index_counter
<
entry_count
;
index_counter
<
entry_count
;
index_counter
++
)
index_counter
++
)
{
{
entry
=
X509_NAME_get_entry
(
xname
,
index_counter
);
entry
=
X509_NAME_get_entry
(
xname
,
index_counter
);
/* check to see if we've gotten to a new RDN */
/* check to see if we've gotten to a new RDN */
if
(
rdn_level
>=
0
)
{
if
(
rdn_level
>=
0
)
{
if
(
rdn_level
!=
entry
->
set
)
{
if
(
rdn_level
!=
entry
->
set
)
{
/* yes, new RDN */
/* yes, new RDN */
/* add old RDN to DN */
/* add old RDN to DN */
rdnt
=
PyList_AsTuple
(
rdn
);
rdnt
=
PyList_AsTuple
(
rdn
);
Py_DECREF
(
rdn
);
Py_DECREF
(
rdn
);
if
(
rdnt
==
NULL
)
if
(
rdnt
==
NULL
)
goto
fail0
;
goto
fail0
;
retcode
=
PyList_Append
(
dn
,
rdnt
);
retcode
=
PyList_Append
(
dn
,
rdnt
);
Py_DECREF
(
rdnt
);
Py_DECREF
(
rdnt
);
if
(
retcode
<
0
)
if
(
retcode
<
0
)
goto
fail0
;
goto
fail0
;
/* create new RDN */
/* create new RDN */
rdn
=
PyList_New
(
0
);
rdn
=
PyList_New
(
0
);
if
(
rdn
==
NULL
)
if
(
rdn
==
NULL
)
goto
fail0
;
goto
fail0
;
}
}
}
}
rdn_level
=
entry
->
set
;
rdn_level
=
entry
->
set
;
/* now add this attribute to the current RDN */
/* now add this attribute to the current RDN */
name
=
X509_NAME_ENTRY_get_object
(
entry
);
name
=
X509_NAME_ENTRY_get_object
(
entry
);
value
=
X509_NAME_ENTRY_get_data
(
entry
);
value
=
X509_NAME_ENTRY_get_data
(
entry
);
attr
=
_create_tuple_for_attribute
(
name
,
value
);
attr
=
_create_tuple_for_attribute
(
name
,
value
);
/*
/*
fprintf(stderr, "RDN level %d, attribute %s: %s\n",
fprintf(stderr, "RDN level %d, attribute %s: %s\n",
entry->set,
entry->set,
PyString_AS_STRING(PyTuple_GET_ITEM(attr, 0)),
PyString_AS_STRING(PyTuple_GET_ITEM(attr, 0)),
PyString_AS_STRING(PyTuple_GET_ITEM(attr, 1)));
PyString_AS_STRING(PyTuple_GET_ITEM(attr, 1)));
*/
*/
if
(
attr
==
NULL
)
if
(
attr
==
NULL
)
goto
fail1
;
goto
fail1
;
retcode
=
PyList_Append
(
rdn
,
attr
);
retcode
=
PyList_Append
(
rdn
,
attr
);
Py_DECREF
(
attr
);
Py_DECREF
(
attr
);
if
(
retcode
<
0
)
if
(
retcode
<
0
)
goto
fail1
;
goto
fail1
;
}
}
/* now, there's typically a dangling RDN */
/* now, there's typically a dangling RDN */
if
((
rdn
!=
NULL
)
&&
(
PyList_Size
(
rdn
)
>
0
))
{
if
((
rdn
!=
NULL
)
&&
(
PyList_Size
(
rdn
)
>
0
))
{
rdnt
=
PyList_AsTuple
(
rdn
);
rdnt
=
PyList_AsTuple
(
rdn
);
Py_DECREF
(
rdn
);
Py_DECREF
(
rdn
);
if
(
rdnt
==
NULL
)
if
(
rdnt
==
NULL
)
goto
fail0
;
goto
fail0
;
retcode
=
PyList_Append
(
dn
,
rdnt
);
retcode
=
PyList_Append
(
dn
,
rdnt
);
Py_DECREF
(
rdnt
);
Py_DECREF
(
rdnt
);
if
(
retcode
<
0
)
if
(
retcode
<
0
)
goto
fail0
;
goto
fail0
;
}
}
/* convert list to tuple */
/* convert list to tuple */
rdnt
=
PyList_AsTuple
(
dn
);
rdnt
=
PyList_AsTuple
(
dn
);
Py_DECREF
(
dn
);
Py_DECREF
(
dn
);
if
(
rdnt
==
NULL
)
if
(
rdnt
==
NULL
)
return
NULL
;
return
NULL
;
return
rdnt
;
return
rdnt
;
fail1:
fail1:
Py_XDECREF
(
rdn
);
Py_XDECREF
(
rdn
);
fail0:
fail0:
Py_XDECREF
(
dn
);
Py_XDECREF
(
dn
);
return
NULL
;
return
NULL
;
}
}
static
PyObject
*
static
PyObject
*
_get_peer_alt_names
(
X509
*
certificate
)
{
_get_peer_alt_names
(
X509
*
certificate
)
{
/* this code follows the procedure outlined in
/* this code follows the procedure outlined in
OpenSSL's crypto/x509v3/v3_prn.c:X509v3_EXT_print()
OpenSSL's crypto/x509v3/v3_prn.c:X509v3_EXT_print()
function to extract the STACK_OF(GENERAL_NAME),
function to extract the STACK_OF(GENERAL_NAME),
then iterates through the stack to add the
then iterates through the stack to add the
names. */
names. */
int
i
,
j
;
int
i
,
j
;
PyObject
*
peer_alt_names
=
Py_None
;
PyObject
*
peer_alt_names
=
Py_None
;
PyObject
*
v
,
*
t
;
PyObject
*
v
,
*
t
;
X509_EXTENSION
*
ext
=
NULL
;
X509_EXTENSION
*
ext
=
NULL
;
GENERAL_NAMES
*
names
=
NULL
;
GENERAL_NAMES
*
names
=
NULL
;
GENERAL_NAME
*
name
;
GENERAL_NAME
*
name
;
X509V3_EXT_METHOD
*
method
;
X509V3_EXT_METHOD
*
method
;
BIO
*
biobuf
=
NULL
;
BIO
*
biobuf
=
NULL
;
char
buf
[
2048
];
char
buf
[
2048
];
char
*
vptr
;
char
*
vptr
;
int
len
;
int
len
;
/* Issue #2973: ASN1_item_d2i() API changed in OpenSSL 0.9.6m */
/* Issue #2973: ASN1_item_d2i() API changed in OpenSSL 0.9.6m */
#if OPENSSL_VERSION_NUMBER >= 0x009060dfL
#if OPENSSL_VERSION_NUMBER >= 0x009060dfL
const
unsigned
char
*
p
;
const
unsigned
char
*
p
;
#else
#else
unsigned
char
*
p
;
unsigned
char
*
p
;
#endif
#endif
if
(
certificate
==
NULL
)
if
(
certificate
==
NULL
)
return
peer_alt_names
;
return
peer_alt_names
;
/* get a memory buffer */
/* get a memory buffer */
biobuf
=
BIO_new
(
BIO_s_mem
());
biobuf
=
BIO_new
(
BIO_s_mem
());
i
=
0
;
i
=
0
;
while
((
i
=
X509_get_ext_by_NID
(
while
((
i
=
X509_get_ext_by_NID
(
certificate
,
NID_subject_alt_name
,
i
))
>=
0
)
{
certificate
,
NID_subject_alt_name
,
i
))
>=
0
)
{
if
(
peer_alt_names
==
Py_None
)
{
if
(
peer_alt_names
==
Py_None
)
{
peer_alt_names
=
PyList_New
(
0
);
peer_alt_names
=
PyList_New
(
0
);
if
(
peer_alt_names
==
NULL
)
if
(
peer_alt_names
==
NULL
)
goto
fail
;
goto
fail
;
}
}
/* now decode the altName */
/* now decode the altName */
ext
=
X509_get_ext
(
certificate
,
i
);
ext
=
X509_get_ext
(
certificate
,
i
);
if
(
!
(
method
=
X509V3_EXT_get
(
ext
)))
{
if
(
!
(
method
=
X509V3_EXT_get
(
ext
)))
{
PyErr_SetString
(
PySSLErrorObject
,
PyErr_SetString
(
PySSLErrorObject
,
ERRSTR
(
"No method for internalizing subjectAltName!"
));
ERRSTR
(
"No method for internalizing subjectAltName!"
));
goto
fail
;
goto
fail
;
}
}
p
=
ext
->
value
->
data
;
p
=
ext
->
value
->
data
;
if
(
method
->
it
)
if
(
method
->
it
)
names
=
(
GENERAL_NAMES
*
)
(
ASN1_item_d2i
(
NULL
,
names
=
(
GENERAL_NAMES
*
)
(
ASN1_item_d2i
(
NULL
,
&
p
,
&
p
,
ext
->
value
->
length
,
ext
->
value
->
length
,
ASN1_ITEM_ptr
(
method
->
it
)));
ASN1_ITEM_ptr
(
method
->
it
)));
else
else
names
=
(
GENERAL_NAMES
*
)
(
method
->
d2i
(
NULL
,
names
=
(
GENERAL_NAMES
*
)
(
method
->
d2i
(
NULL
,
&
p
,
&
p
,
ext
->
value
->
length
));
ext
->
value
->
length
));
for
(
j
=
0
;
j
<
sk_GENERAL_NAME_num
(
names
);
j
++
)
{
for
(
j
=
0
;
j
<
sk_GENERAL_NAME_num
(
names
);
j
++
)
{
/* get a rendering of each name in the set of names */
/* get a rendering of each name in the set of names */
name
=
sk_GENERAL_NAME_value
(
names
,
j
);
name
=
sk_GENERAL_NAME_value
(
names
,
j
);
if
(
name
->
type
==
GEN_DIRNAME
)
{
if
(
name
->
type
==
GEN_DIRNAME
)
{
/* we special-case DirName as a tuple of tuples of attributes */
/* we special-case DirName as a tuple of tuples of attributes */
t
=
PyTuple_New
(
2
);
t
=
PyTuple_New
(
2
);
if
(
t
==
NULL
)
{
if
(
t
==
NULL
)
{
goto
fail
;
goto
fail
;
}
}
v
=
PyString_FromString
(
"DirName"
);
v
=
PyString_FromString
(
"DirName"
);
if
(
v
==
NULL
)
{
if
(
v
==
NULL
)
{
Py_DECREF
(
t
);
Py_DECREF
(
t
);
goto
fail
;
goto
fail
;
}
}
PyTuple_SET_ITEM
(
t
,
0
,
v
);
PyTuple_SET_ITEM
(
t
,
0
,
v
);
v
=
_create_tuple_for_X509_NAME
(
name
->
d
.
dirn
);
v
=
_create_tuple_for_X509_NAME
(
name
->
d
.
dirn
);
if
(
v
==
NULL
)
{
if
(
v
==
NULL
)
{
Py_DECREF
(
t
);
Py_DECREF
(
t
);
goto
fail
;
goto
fail
;
}
}
PyTuple_SET_ITEM
(
t
,
1
,
v
);
PyTuple_SET_ITEM
(
t
,
1
,
v
);
}
else
{
}
else
{
/* for everything else, we use the OpenSSL print form */
/* for everything else, we use the OpenSSL print form */
(
void
)
BIO_reset
(
biobuf
);
(
void
)
BIO_reset
(
biobuf
);
GENERAL_NAME_print
(
biobuf
,
name
);
GENERAL_NAME_print
(
biobuf
,
name
);
len
=
BIO_gets
(
biobuf
,
buf
,
sizeof
(
buf
)
-
1
);
len
=
BIO_gets
(
biobuf
,
buf
,
sizeof
(
buf
)
-
1
);
if
(
len
<
0
)
{
if
(
len
<
0
)
{
_setSSLError
(
NULL
,
0
,
__FILE__
,
__LINE__
);
_setSSLError
(
NULL
,
0
,
__FILE__
,
__LINE__
);
goto
fail
;
goto
fail
;
}
}
vptr
=
strchr
(
buf
,
':'
);
vptr
=
strchr
(
buf
,
':'
);
if
(
vptr
==
NULL
)
if
(
vptr
==
NULL
)
goto
fail
;
goto
fail
;
t
=
PyTuple_New
(
2
);
t
=
PyTuple_New
(
2
);
if
(
t
==
NULL
)
if
(
t
==
NULL
)
goto
fail
;
goto
fail
;
v
=
PyString_FromStringAndSize
(
buf
,
(
vptr
-
buf
));
v
=
PyString_FromStringAndSize
(
buf
,
(
vptr
-
buf
));
if
(
v
==
NULL
)
{
if
(
v
==
NULL
)
{
Py_DECREF
(
t
);
Py_DECREF
(
t
);
goto
fail
;
goto
fail
;
}
}
PyTuple_SET_ITEM
(
t
,
0
,
v
);
PyTuple_SET_ITEM
(
t
,
0
,
v
);
v
=
PyString_FromStringAndSize
((
vptr
+
1
),
(
len
-
(
vptr
-
buf
+
1
)));
v
=
PyString_FromStringAndSize
((
vptr
+
1
),
(
len
-
(
vptr
-
buf
+
1
)));
if
(
v
==
NULL
)
{
if
(
v
==
NULL
)
{
Py_DECREF
(
t
);
Py_DECREF
(
t
);
goto
fail
;
goto
fail
;
}
}
PyTuple_SET_ITEM
(
t
,
1
,
v
);
PyTuple_SET_ITEM
(
t
,
1
,
v
);
}
}
/* and add that rendering to the list */
/* and add that rendering to the list */
if
(
PyList_Append
(
peer_alt_names
,
t
)
<
0
)
{
if
(
PyList_Append
(
peer_alt_names
,
t
)
<
0
)
{
Py_DECREF
(
t
);
Py_DECREF
(
t
);
goto
fail
;
goto
fail
;
}
}
Py_DECREF
(
t
);
Py_DECREF
(
t
);
}
}
}
}
BIO_free
(
biobuf
);
BIO_free
(
biobuf
);
if
(
peer_alt_names
!=
Py_None
)
{
if
(
peer_alt_names
!=
Py_None
)
{
v
=
PyList_AsTuple
(
peer_alt_names
);
v
=
PyList_AsTuple
(
peer_alt_names
);
Py_DECREF
(
peer_alt_names
);
Py_DECREF
(
peer_alt_names
);
return
v
;
return
v
;
}
else
{
}
else
{
return
peer_alt_names
;
return
peer_alt_names
;
}
}
fail:
fail:
if
(
biobuf
!=
NULL
)
if
(
biobuf
!=
NULL
)
BIO_free
(
biobuf
);
BIO_free
(
biobuf
);
if
(
peer_alt_names
!=
Py_None
)
{
if
(
peer_alt_names
!=
Py_None
)
{
Py_XDECREF
(
peer_alt_names
);
Py_XDECREF
(
peer_alt_names
);
}
}
return
NULL
;
return
NULL
;
}
}
static
PyObject
*
static
PyObject
*
_decode_certificate
(
X509
*
certificate
,
int
verbose
)
{
_decode_certificate
(
X509
*
certificate
,
int
verbose
)
{
PyObject
*
retval
=
NULL
;
PyObject
*
retval
=
NULL
;
BIO
*
biobuf
=
NULL
;
BIO
*
biobuf
=
NULL
;
PyObject
*
peer
;
PyObject
*
peer
;
PyObject
*
peer_alt_names
=
NULL
;
PyObject
*
peer_alt_names
=
NULL
;
PyObject
*
issuer
;
PyObject
*
issuer
;
PyObject
*
version
;
PyObject
*
version
;
PyObject
*
sn_obj
;
PyObject
*
sn_obj
;
ASN1_INTEGER
*
serialNumber
;
ASN1_INTEGER
*
serialNumber
;
char
buf
[
2048
];
char
buf
[
2048
];
int
len
;
int
len
;
ASN1_TIME
*
notBefore
,
*
notAfter
;
ASN1_TIME
*
notBefore
,
*
notAfter
;
PyObject
*
pnotBefore
,
*
pnotAfter
;
PyObject
*
pnotBefore
,
*
pnotAfter
;
retval
=
PyDict_New
();
retval
=
PyDict_New
();
if
(
retval
==
NULL
)
if
(
retval
==
NULL
)
return
NULL
;
return
NULL
;
peer
=
_create_tuple_for_X509_NAME
(
peer
=
_create_tuple_for_X509_NAME
(
X509_get_subject_name
(
certificate
));
X509_get_subject_name
(
certificate
));
if
(
peer
==
NULL
)
if
(
peer
==
NULL
)
goto
fail0
;
goto
fail0
;
if
(
PyDict_SetItemString
(
retval
,
(
const
char
*
)
"subject"
,
peer
)
<
0
)
{
if
(
PyDict_SetItemString
(
retval
,
(
const
char
*
)
"subject"
,
peer
)
<
0
)
{
Py_DECREF
(
peer
);
Py_DECREF
(
peer
);
goto
fail0
;
goto
fail0
;
}
}
Py_DECREF
(
peer
);
Py_DECREF
(
peer
);
if
(
verbose
)
{
if
(
verbose
)
{
issuer
=
_create_tuple_for_X509_NAME
(
issuer
=
_create_tuple_for_X509_NAME
(
X509_get_issuer_name
(
certificate
));
X509_get_issuer_name
(
certificate
));
if
(
issuer
==
NULL
)
if
(
issuer
==
NULL
)
goto
fail0
;
goto
fail0
;
if
(
PyDict_SetItemString
(
retval
,
(
const
char
*
)
"issuer"
,
issuer
)
<
0
)
{
if
(
PyDict_SetItemString
(
retval
,
(
const
char
*
)
"issuer"
,
issuer
)
<
0
)
{
Py_DECREF
(
issuer
);
Py_DECREF
(
issuer
);
goto
fail0
;
goto
fail0
;
}
}
Py_DECREF
(
issuer
);
Py_DECREF
(
issuer
);
version
=
PyInt_FromLong
(
X509_get_version
(
certificate
)
+
1
);
version
=
PyInt_FromLong
(
X509_get_version
(
certificate
)
+
1
);
if
(
PyDict_SetItemString
(
retval
,
"version"
,
version
)
<
0
)
{
if
(
PyDict_SetItemString
(
retval
,
"version"
,
version
)
<
0
)
{
Py_DECREF
(
version
);
Py_DECREF
(
version
);
goto
fail0
;
goto
fail0
;
}
}
Py_DECREF
(
version
);
Py_DECREF
(
version
);
}
}
/* get a memory buffer */
/* get a memory buffer */
biobuf
=
BIO_new
(
BIO_s_mem
());
biobuf
=
BIO_new
(
BIO_s_mem
());
if
(
verbose
)
{
if
(
verbose
)
{
(
void
)
BIO_reset
(
biobuf
);
(
void
)
BIO_reset
(
biobuf
);
serialNumber
=
X509_get_serialNumber
(
certificate
);
serialNumber
=
X509_get_serialNumber
(
certificate
);
/* should not exceed 20 octets, 160 bits, so buf is big enough */
/* should not exceed 20 octets, 160 bits, so buf is big enough */
i2a_ASN1_INTEGER
(
biobuf
,
serialNumber
);
i2a_ASN1_INTEGER
(
biobuf
,
serialNumber
);
len
=
BIO_gets
(
biobuf
,
buf
,
sizeof
(
buf
)
-
1
);
len
=
BIO_gets
(
biobuf
,
buf
,
sizeof
(
buf
)
-
1
);
if
(
len
<
0
)
{
if
(
len
<
0
)
{
_setSSLError
(
NULL
,
0
,
__FILE__
,
__LINE__
);
_setSSLError
(
NULL
,
0
,
__FILE__
,
__LINE__
);
goto
fail1
;
goto
fail1
;
}
}
sn_obj
=
PyString_FromStringAndSize
(
buf
,
len
);
sn_obj
=
PyString_FromStringAndSize
(
buf
,
len
);
if
(
sn_obj
==
NULL
)
if
(
sn_obj
==
NULL
)
goto
fail1
;
goto
fail1
;
if
(
PyDict_SetItemString
(
retval
,
"serialNumber"
,
sn_obj
)
<
0
)
{
if
(
PyDict_SetItemString
(
retval
,
"serialNumber"
,
sn_obj
)
<
0
)
{
Py_DECREF
(
sn_obj
);
Py_DECREF
(
sn_obj
);
goto
fail1
;
goto
fail1
;
}
}
Py_DECREF
(
sn_obj
);
Py_DECREF
(
sn_obj
);
(
void
)
BIO_reset
(
biobuf
);
(
void
)
BIO_reset
(
biobuf
);
notBefore
=
X509_get_notBefore
(
certificate
);
notBefore
=
X509_get_notBefore
(
certificate
);
ASN1_TIME_print
(
biobuf
,
notBefore
);
ASN1_TIME_print
(
biobuf
,
notBefore
);
len
=
BIO_gets
(
biobuf
,
buf
,
sizeof
(
buf
)
-
1
);
len
=
BIO_gets
(
biobuf
,
buf
,
sizeof
(
buf
)
-
1
);
if
(
len
<
0
)
{
if
(
len
<
0
)
{
_setSSLError
(
NULL
,
0
,
__FILE__
,
__LINE__
);
_setSSLError
(
NULL
,
0
,
__FILE__
,
__LINE__
);
goto
fail1
;
goto
fail1
;
}
}
pnotBefore
=
PyString_FromStringAndSize
(
buf
,
len
);
pnotBefore
=
PyString_FromStringAndSize
(
buf
,
len
);
if
(
pnotBefore
==
NULL
)
if
(
pnotBefore
==
NULL
)
goto
fail1
;
goto
fail1
;
if
(
PyDict_SetItemString
(
retval
,
"notBefore"
,
pnotBefore
)
<
0
)
{
if
(
PyDict_SetItemString
(
retval
,
"notBefore"
,
pnotBefore
)
<
0
)
{
Py_DECREF
(
pnotBefore
);
Py_DECREF
(
pnotBefore
);
goto
fail1
;
goto
fail1
;
}
}
Py_DECREF
(
pnotBefore
);
Py_DECREF
(
pnotBefore
);
}
}
(
void
)
BIO_reset
(
biobuf
);
(
void
)
BIO_reset
(
biobuf
);
notAfter
=
X509_get_notAfter
(
certificate
);
notAfter
=
X509_get_notAfter
(
certificate
);
ASN1_TIME_print
(
biobuf
,
notAfter
);
ASN1_TIME_print
(
biobuf
,
notAfter
);
len
=
BIO_gets
(
biobuf
,
buf
,
sizeof
(
buf
)
-
1
);
len
=
BIO_gets
(
biobuf
,
buf
,
sizeof
(
buf
)
-
1
);
if
(
len
<
0
)
{
if
(
len
<
0
)
{
_setSSLError
(
NULL
,
0
,
__FILE__
,
__LINE__
);
_setSSLError
(
NULL
,
0
,
__FILE__
,
__LINE__
);
goto
fail1
;
goto
fail1
;
}
}
pnotAfter
=
PyString_FromStringAndSize
(
buf
,
len
);
pnotAfter
=
PyString_FromStringAndSize
(
buf
,
len
);
if
(
pnotAfter
==
NULL
)
if
(
pnotAfter
==
NULL
)
goto
fail1
;
goto
fail1
;
if
(
PyDict_SetItemString
(
retval
,
"notAfter"
,
pnotAfter
)
<
0
)
{
if
(
PyDict_SetItemString
(
retval
,
"notAfter"
,
pnotAfter
)
<
0
)
{
Py_DECREF
(
pnotAfter
);
Py_DECREF
(
pnotAfter
);
goto
fail1
;
goto
fail1
;
}
}
Py_DECREF
(
pnotAfter
);
Py_DECREF
(
pnotAfter
);
/* Now look for subjectAltName */
/* Now look for subjectAltName */
peer_alt_names
=
_get_peer_alt_names
(
certificate
);
peer_alt_names
=
_get_peer_alt_names
(
certificate
);
if
(
peer_alt_names
==
NULL
)
if
(
peer_alt_names
==
NULL
)
goto
fail1
;
goto
fail1
;
else
if
(
peer_alt_names
!=
Py_None
)
{
else
if
(
peer_alt_names
!=
Py_None
)
{
if
(
PyDict_SetItemString
(
retval
,
"subjectAltName"
,
if
(
PyDict_SetItemString
(
retval
,
"subjectAltName"
,
peer_alt_names
)
<
0
)
{
peer_alt_names
)
<
0
)
{
Py_DECREF
(
peer_alt_names
);
Py_DECREF
(
peer_alt_names
);
goto
fail1
;
goto
fail1
;
}
}
Py_DECREF
(
peer_alt_names
);
Py_DECREF
(
peer_alt_names
);
}
}
BIO_free
(
biobuf
);
BIO_free
(
biobuf
);
return
retval
;
return
retval
;
fail1:
fail1:
if
(
biobuf
!=
NULL
)
if
(
biobuf
!=
NULL
)
BIO_free
(
biobuf
);
BIO_free
(
biobuf
);
fail0:
fail0:
Py_XDECREF
(
retval
);
Py_XDECREF
(
retval
);
return
NULL
;
return
NULL
;
}
}
static
PyObject
*
static
PyObject
*
PySSL_test_decode_certificate
(
PyObject
*
mod
,
PyObject
*
args
)
{
PySSL_test_decode_certificate
(
PyObject
*
mod
,
PyObject
*
args
)
{
PyObject
*
retval
=
NULL
;
PyObject
*
retval
=
NULL
;
char
*
filename
=
NULL
;
char
*
filename
=
NULL
;
X509
*
x
=
NULL
;
X509
*
x
=
NULL
;
BIO
*
cert
;
BIO
*
cert
;
int
verbose
=
1
;
int
verbose
=
1
;
if
(
!
PyArg_ParseTuple
(
args
,
"s|i:test_decode_certificate"
,
&
filename
,
&
verbose
))
if
(
!
PyArg_ParseTuple
(
args
,
"s|i:test_decode_certificate"
,
&
filename
,
&
verbose
))
return
NULL
;
return
NULL
;
if
((
cert
=
BIO_new
(
BIO_s_file
()))
==
NULL
)
{
if
((
cert
=
BIO_new
(
BIO_s_file
()))
==
NULL
)
{
PyErr_SetString
(
PySSLErrorObject
,
"Can't malloc memory to read file"
);
PyErr_SetString
(
PySSLErrorObject
,
"Can't malloc memory to read file"
);
goto
fail0
;
goto
fail0
;
}
}
if
(
BIO_read_filename
(
cert
,
filename
)
<=
0
)
{
if
(
BIO_read_filename
(
cert
,
filename
)
<=
0
)
{
PyErr_SetString
(
PySSLErrorObject
,
"Can't open file"
);
PyErr_SetString
(
PySSLErrorObject
,
"Can't open file"
);
goto
fail0
;
goto
fail0
;
}
}
x
=
PEM_read_bio_X509_AUX
(
cert
,
NULL
,
NULL
,
NULL
);
x
=
PEM_read_bio_X509_AUX
(
cert
,
NULL
,
NULL
,
NULL
);
if
(
x
==
NULL
)
{
if
(
x
==
NULL
)
{
PyErr_SetString
(
PySSLErrorObject
,
"Error decoding PEM-encoded file"
);
PyErr_SetString
(
PySSLErrorObject
,
"Error decoding PEM-encoded file"
);
goto
fail0
;
goto
fail0
;
}
}
retval
=
_decode_certificate
(
x
,
verbose
);
retval
=
_decode_certificate
(
x
,
verbose
);
fail0:
fail0:
if
(
cert
!=
NULL
)
BIO_free
(
cert
);
if
(
cert
!=
NULL
)
BIO_free
(
cert
);
return
retval
;
return
retval
;
}
}
static
PyObject
*
static
PyObject
*
PySSL_peercert
(
PySSLObject
*
self
,
PyObject
*
args
)
PySSL_peercert
(
PySSLObject
*
self
,
PyObject
*
args
)
{
{
PyObject
*
retval
=
NULL
;
PyObject
*
retval
=
NULL
;
int
len
;
int
len
;
int
verification
;
int
verification
;
PyObject
*
binary_mode
=
Py_None
;
PyObject
*
binary_mode
=
Py_None
;
if
(
!
PyArg_ParseTuple
(
args
,
"|O:peer_certificate"
,
&
binary_mode
))
if
(
!
PyArg_ParseTuple
(
args
,
"|O:peer_certificate"
,
&
binary_mode
))
return
NULL
;
return
NULL
;
if
(
!
self
->
peer_cert
)
if
(
!
self
->
peer_cert
)
Py_RETURN_NONE
;
Py_RETURN_NONE
;
if
(
PyObject_IsTrue
(
binary_mode
))
{
if
(
PyObject_IsTrue
(
binary_mode
))
{
/* return cert in DER-encoded format */
/* return cert in DER-encoded format */
unsigned
char
*
bytes_buf
=
NULL
;
unsigned
char
*
bytes_buf
=
NULL
;
bytes_buf
=
NULL
;
bytes_buf
=
NULL
;
len
=
i2d_X509
(
self
->
peer_cert
,
&
bytes_buf
);
len
=
i2d_X509
(
self
->
peer_cert
,
&
bytes_buf
);
if
(
len
<
0
)
{
if
(
len
<
0
)
{
PySSL_SetError
(
self
,
len
,
__FILE__
,
__LINE__
);
PySSL_SetError
(
self
,
len
,
__FILE__
,
__LINE__
);
return
NULL
;
return
NULL
;
}
}
retval
=
PyString_FromStringAndSize
((
const
char
*
)
bytes_buf
,
len
);
retval
=
PyString_FromStringAndSize
((
const
char
*
)
bytes_buf
,
len
);
OPENSSL_free
(
bytes_buf
);
OPENSSL_free
(
bytes_buf
);
return
retval
;
return
retval
;
}
else
{
}
else
{
verification
=
SSL_CTX_get_verify_mode
(
self
->
ctx
);
verification
=
SSL_CTX_get_verify_mode
(
self
->
ctx
);
if
((
verification
&
SSL_VERIFY_PEER
)
==
0
)
if
((
verification
&
SSL_VERIFY_PEER
)
==
0
)
return
PyDict_New
();
return
PyDict_New
();
else
else
return
_decode_certificate
(
self
->
peer_cert
,
0
);
return
_decode_certificate
(
self
->
peer_cert
,
0
);
}
}
}
}
PyDoc_STRVAR
(
PySSL_peercert_doc
,
PyDoc_STRVAR
(
PySSL_peercert_doc
,
...
@@ -1040,60 +1040,60 @@ return the certificate even if it wasn't validated.");
...
@@ -1040,60 +1040,60 @@ return the certificate even if it wasn't validated.");
static
PyObject
*
PySSL_cipher
(
PySSLObject
*
self
)
{
static
PyObject
*
PySSL_cipher
(
PySSLObject
*
self
)
{
PyObject
*
retval
,
*
v
;
PyObject
*
retval
,
*
v
;
SSL_CIPHER
*
current
;
SSL_CIPHER
*
current
;
char
*
cipher_name
;
char
*
cipher_name
;
char
*
cipher_protocol
;
char
*
cipher_protocol
;
if
(
self
->
ssl
==
NULL
)
if
(
self
->
ssl
==
NULL
)
return
Py_None
;
return
Py_None
;
current
=
SSL_get_current_cipher
(
self
->
ssl
);
current
=
SSL_get_current_cipher
(
self
->
ssl
);
if
(
current
==
NULL
)
if
(
current
==
NULL
)
return
Py_None
;
return
Py_None
;
retval
=
PyTuple_New
(
3
);
retval
=
PyTuple_New
(
3
);
if
(
retval
==
NULL
)
if
(
retval
==
NULL
)
return
NULL
;
return
NULL
;
cipher_name
=
(
char
*
)
SSL_CIPHER_get_name
(
current
);
cipher_name
=
(
char
*
)
SSL_CIPHER_get_name
(
current
);
if
(
cipher_name
==
NULL
)
{
if
(
cipher_name
==
NULL
)
{
PyTuple_SET_ITEM
(
retval
,
0
,
Py_None
);
PyTuple_SET_ITEM
(
retval
,
0
,
Py_None
);
}
else
{
}
else
{
v
=
PyString_FromString
(
cipher_name
);
v
=
PyString_FromString
(
cipher_name
);
if
(
v
==
NULL
)
if
(
v
==
NULL
)
goto
fail0
;
goto
fail0
;
PyTuple_SET_ITEM
(
retval
,
0
,
v
);
PyTuple_SET_ITEM
(
retval
,
0
,
v
);
}
}
cipher_protocol
=
SSL_CIPHER_get_version
(
current
);
cipher_protocol
=
SSL_CIPHER_get_version
(
current
);
if
(
cipher_protocol
==
NULL
)
{
if
(
cipher_protocol
==
NULL
)
{
PyTuple_SET_ITEM
(
retval
,
1
,
Py_None
);
PyTuple_SET_ITEM
(
retval
,
1
,
Py_None
);
}
else
{
}
else
{
v
=
PyString_FromString
(
cipher_protocol
);
v
=
PyString_FromString
(
cipher_protocol
);
if
(
v
==
NULL
)
if
(
v
==
NULL
)
goto
fail0
;
goto
fail0
;
PyTuple_SET_ITEM
(
retval
,
1
,
v
);
PyTuple_SET_ITEM
(
retval
,
1
,
v
);
}
}
v
=
PyInt_FromLong
(
SSL_CIPHER_get_bits
(
current
,
NULL
));
v
=
PyInt_FromLong
(
SSL_CIPHER_get_bits
(
current
,
NULL
));
if
(
v
==
NULL
)
if
(
v
==
NULL
)
goto
fail0
;
goto
fail0
;
PyTuple_SET_ITEM
(
retval
,
2
,
v
);
PyTuple_SET_ITEM
(
retval
,
2
,
v
);
return
retval
;
return
retval
;
fail0:
fail0:
Py_DECREF
(
retval
);
Py_DECREF
(
retval
);
return
NULL
;
return
NULL
;
}
}
static
void
PySSL_dealloc
(
PySSLObject
*
self
)
static
void
PySSL_dealloc
(
PySSLObject
*
self
)
{
{
if
(
self
->
peer_cert
)
/* Possible not to have one? */
if
(
self
->
peer_cert
)
/* Possible not to have one? */
X509_free
(
self
->
peer_cert
);
X509_free
(
self
->
peer_cert
);
if
(
self
->
ssl
)
if
(
self
->
ssl
)
SSL_free
(
self
->
ssl
);
SSL_free
(
self
->
ssl
);
if
(
self
->
ctx
)
if
(
self
->
ctx
)
SSL_CTX_free
(
self
->
ctx
);
SSL_CTX_free
(
self
->
ctx
);
Py_XDECREF
(
self
->
Socket
);
Py_XDECREF
(
self
->
Socket
);
PyObject_Del
(
self
);
PyObject_Del
(
self
);
}
}
/* If the socket has a timeout, do a select()/poll() on the socket.
/* If the socket has a timeout, do a select()/poll() on the socket.
...
@@ -1104,137 +1104,137 @@ static void PySSL_dealloc(PySSLObject *self)
...
@@ -1104,137 +1104,137 @@ static void PySSL_dealloc(PySSLObject *self)
static
int
static
int
check_socket_and_wait_for_timeout
(
PySocketSockObject
*
s
,
int
writing
)
check_socket_and_wait_for_timeout
(
PySocketSockObject
*
s
,
int
writing
)
{
{
fd_set
fds
;
fd_set
fds
;
struct
timeval
tv
;
struct
timeval
tv
;
int
rc
;
int
rc
;
/* Nothing to do unless we're in timeout mode (not non-blocking) */
/* Nothing to do unless we're in timeout mode (not non-blocking) */
if
(
s
->
sock_timeout
<
0
.
0
)
if
(
s
->
sock_timeout
<
0
.
0
)
return
SOCKET_IS_BLOCKING
;
return
SOCKET_IS_BLOCKING
;
else
if
(
s
->
sock_timeout
==
0
.
0
)
else
if
(
s
->
sock_timeout
==
0
.
0
)
return
SOCKET_IS_NONBLOCKING
;
return
SOCKET_IS_NONBLOCKING
;
/* Guard against closed socket */
/* Guard against closed socket */
if
(
s
->
sock_fd
<
0
)
if
(
s
->
sock_fd
<
0
)
return
SOCKET_HAS_BEEN_CLOSED
;
return
SOCKET_HAS_BEEN_CLOSED
;
/* Prefer poll, if available, since you can poll() any fd
/* Prefer poll, if available, since you can poll() any fd
* which can't be done with select(). */
* which can't be done with select(). */
#ifdef HAVE_POLL
#ifdef HAVE_POLL
{
{
struct
pollfd
pollfd
;
struct
pollfd
pollfd
;
int
timeout
;
int
timeout
;
pollfd
.
fd
=
s
->
sock_fd
;
pollfd
.
fd
=
s
->
sock_fd
;
pollfd
.
events
=
writing
?
POLLOUT
:
POLLIN
;
pollfd
.
events
=
writing
?
POLLOUT
:
POLLIN
;
/* s->sock_timeout is in seconds, timeout in ms */
/* s->sock_timeout is in seconds, timeout in ms */
timeout
=
(
int
)(
s
->
sock_timeout
*
1000
+
0
.
5
);
timeout
=
(
int
)(
s
->
sock_timeout
*
1000
+
0
.
5
);
PySSL_BEGIN_ALLOW_THREADS
PySSL_BEGIN_ALLOW_THREADS
rc
=
poll
(
&
pollfd
,
1
,
timeout
);
rc
=
poll
(
&
pollfd
,
1
,
timeout
);
PySSL_END_ALLOW_THREADS
PySSL_END_ALLOW_THREADS
goto
normal_return
;
goto
normal_return
;
}
}
#endif
#endif
/* Guard against socket too large for select*/
/* Guard against socket too large for select*/
#ifndef Py_SOCKET_FD_CAN_BE_GE_FD_SETSIZE
#ifndef Py_SOCKET_FD_CAN_BE_GE_FD_SETSIZE
if
(
s
->
sock_fd
>=
FD_SETSIZE
)
if
(
s
->
sock_fd
>=
FD_SETSIZE
)
return
SOCKET_TOO_LARGE_FOR_SELECT
;
return
SOCKET_TOO_LARGE_FOR_SELECT
;
#endif
#endif
/* Construct the arguments to select */
/* Construct the arguments to select */
tv
.
tv_sec
=
(
int
)
s
->
sock_timeout
;
tv
.
tv_sec
=
(
int
)
s
->
sock_timeout
;
tv
.
tv_usec
=
(
int
)((
s
->
sock_timeout
-
tv
.
tv_sec
)
*
1e6
);
tv
.
tv_usec
=
(
int
)((
s
->
sock_timeout
-
tv
.
tv_sec
)
*
1e6
);
FD_ZERO
(
&
fds
);
FD_ZERO
(
&
fds
);
FD_SET
(
s
->
sock_fd
,
&
fds
);
FD_SET
(
s
->
sock_fd
,
&
fds
);
/* See if the socket is ready */
/* See if the socket is ready */
PySSL_BEGIN_ALLOW_THREADS
PySSL_BEGIN_ALLOW_THREADS
if
(
writing
)
if
(
writing
)
rc
=
select
(
s
->
sock_fd
+
1
,
NULL
,
&
fds
,
NULL
,
&
tv
);
rc
=
select
(
s
->
sock_fd
+
1
,
NULL
,
&
fds
,
NULL
,
&
tv
);
else
else
rc
=
select
(
s
->
sock_fd
+
1
,
&
fds
,
NULL
,
NULL
,
&
tv
);
rc
=
select
(
s
->
sock_fd
+
1
,
&
fds
,
NULL
,
NULL
,
&
tv
);
PySSL_END_ALLOW_THREADS
PySSL_END_ALLOW_THREADS
#ifdef HAVE_POLL
#ifdef HAVE_POLL
normal_return:
normal_return:
#endif
#endif
/* Return SOCKET_TIMED_OUT on timeout, SOCKET_OPERATION_OK otherwise
/* Return SOCKET_TIMED_OUT on timeout, SOCKET_OPERATION_OK otherwise
(when we are able to write or when there's something to read) */
(when we are able to write or when there's something to read) */
return
rc
==
0
?
SOCKET_HAS_TIMED_OUT
:
SOCKET_OPERATION_OK
;
return
rc
==
0
?
SOCKET_HAS_TIMED_OUT
:
SOCKET_OPERATION_OK
;
}
}
static
PyObject
*
PySSL_SSLwrite
(
PySSLObject
*
self
,
PyObject
*
args
)
static
PyObject
*
PySSL_SSLwrite
(
PySSLObject
*
self
,
PyObject
*
args
)
{
{
Py_buffer
buf
;
Py_buffer
buf
;
int
len
;
int
len
;
int
sockstate
;
int
sockstate
;
int
err
;
int
err
;
int
nonblocking
;
int
nonblocking
;
if
(
!
PyArg_ParseTuple
(
args
,
"s*:write"
,
&
buf
))
if
(
!
PyArg_ParseTuple
(
args
,
"s*:write"
,
&
buf
))
return
NULL
;
return
NULL
;
/* just in case the blocking state of the socket has been changed */
/* just in case the blocking state of the socket has been changed */
nonblocking
=
(
self
->
Socket
->
sock_timeout
>=
0
.
0
);
nonblocking
=
(
self
->
Socket
->
sock_timeout
>=
0
.
0
);
BIO_set_nbio
(
SSL_get_rbio
(
self
->
ssl
),
nonblocking
);
BIO_set_nbio
(
SSL_get_rbio
(
self
->
ssl
),
nonblocking
);
BIO_set_nbio
(
SSL_get_wbio
(
self
->
ssl
),
nonblocking
);
BIO_set_nbio
(
SSL_get_wbio
(
self
->
ssl
),
nonblocking
);
sockstate
=
check_socket_and_wait_for_timeout
(
self
->
Socket
,
1
);
sockstate
=
check_socket_and_wait_for_timeout
(
self
->
Socket
,
1
);
if
(
sockstate
==
SOCKET_HAS_TIMED_OUT
)
{
if
(
sockstate
==
SOCKET_HAS_TIMED_OUT
)
{
PyErr_SetString
(
PySSLErrorObject
,
PyErr_SetString
(
PySSLErrorObject
,
"The write operation timed out"
);
"The write operation timed out"
);
goto
error
;
goto
error
;
}
else
if
(
sockstate
==
SOCKET_HAS_BEEN_CLOSED
)
{
}
else
if
(
sockstate
==
SOCKET_HAS_BEEN_CLOSED
)
{
PyErr_SetString
(
PySSLErrorObject
,
PyErr_SetString
(
PySSLErrorObject
,
"Underlying socket has been closed."
);
"Underlying socket has been closed."
);
goto
error
;
goto
error
;
}
else
if
(
sockstate
==
SOCKET_TOO_LARGE_FOR_SELECT
)
{
}
else
if
(
sockstate
==
SOCKET_TOO_LARGE_FOR_SELECT
)
{
PyErr_SetString
(
PySSLErrorObject
,
PyErr_SetString
(
PySSLErrorObject
,
"Underlying socket too large for select()."
);
"Underlying socket too large for select()."
);
goto
error
;
goto
error
;
}
}
do
{
do
{
PySSL_BEGIN_ALLOW_THREADS
PySSL_BEGIN_ALLOW_THREADS
len
=
SSL_write
(
self
->
ssl
,
buf
.
buf
,
buf
.
len
);
len
=
SSL_write
(
self
->
ssl
,
buf
.
buf
,
buf
.
len
);
err
=
SSL_get_error
(
self
->
ssl
,
len
);
err
=
SSL_get_error
(
self
->
ssl
,
len
);
PySSL_END_ALLOW_THREADS
PySSL_END_ALLOW_THREADS
if
(
PyErr_CheckSignals
())
{
if
(
PyErr_CheckSignals
())
{
goto
error
;
goto
error
;
}
}
if
(
err
==
SSL_ERROR_WANT_READ
)
{
if
(
err
==
SSL_ERROR_WANT_READ
)
{
sockstate
=
sockstate
=
check_socket_and_wait_for_timeout
(
self
->
Socket
,
0
);
check_socket_and_wait_for_timeout
(
self
->
Socket
,
0
);
}
else
if
(
err
==
SSL_ERROR_WANT_WRITE
)
{
}
else
if
(
err
==
SSL_ERROR_WANT_WRITE
)
{
sockstate
=
sockstate
=
check_socket_and_wait_for_timeout
(
self
->
Socket
,
1
);
check_socket_and_wait_for_timeout
(
self
->
Socket
,
1
);
}
else
{
}
else
{
sockstate
=
SOCKET_OPERATION_OK
;
sockstate
=
SOCKET_OPERATION_OK
;
}
}
if
(
sockstate
==
SOCKET_HAS_TIMED_OUT
)
{
if
(
sockstate
==
SOCKET_HAS_TIMED_OUT
)
{
PyErr_SetString
(
PySSLErrorObject
,
PyErr_SetString
(
PySSLErrorObject
,
"The write operation timed out"
);
"The write operation timed out"
);
goto
error
;
goto
error
;
}
else
if
(
sockstate
==
SOCKET_HAS_BEEN_CLOSED
)
{
}
else
if
(
sockstate
==
SOCKET_HAS_BEEN_CLOSED
)
{
PyErr_SetString
(
PySSLErrorObject
,
PyErr_SetString
(
PySSLErrorObject
,
"Underlying socket has been closed."
);
"Underlying socket has been closed."
);
goto
error
;
goto
error
;
}
else
if
(
sockstate
==
SOCKET_IS_NONBLOCKING
)
{
}
else
if
(
sockstate
==
SOCKET_IS_NONBLOCKING
)
{
break
;
break
;
}
}
}
while
(
err
==
SSL_ERROR_WANT_READ
||
err
==
SSL_ERROR_WANT_WRITE
);
}
while
(
err
==
SSL_ERROR_WANT_READ
||
err
==
SSL_ERROR_WANT_WRITE
);
PyBuffer_Release
(
&
buf
);
PyBuffer_Release
(
&
buf
);
if
(
len
>
0
)
if
(
len
>
0
)
return
PyInt_FromLong
(
len
);
return
PyInt_FromLong
(
len
);
else
else
return
PySSL_SetError
(
self
,
len
,
__FILE__
,
__LINE__
);
return
PySSL_SetError
(
self
,
len
,
__FILE__
,
__LINE__
);
error:
error:
PyBuffer_Release
(
&
buf
);
PyBuffer_Release
(
&
buf
);
return
NULL
;
return
NULL
;
}
}
PyDoc_STRVAR
(
PySSL_SSLwrite_doc
,
PyDoc_STRVAR
(
PySSL_SSLwrite_doc
,
...
@@ -1245,15 +1245,15 @@ of bytes written.");
...
@@ -1245,15 +1245,15 @@ of bytes written.");
static
PyObject
*
PySSL_SSLpending
(
PySSLObject
*
self
)
static
PyObject
*
PySSL_SSLpending
(
PySSLObject
*
self
)
{
{
int
count
=
0
;
int
count
=
0
;
PySSL_BEGIN_ALLOW_THREADS
PySSL_BEGIN_ALLOW_THREADS
count
=
SSL_pending
(
self
->
ssl
);
count
=
SSL_pending
(
self
->
ssl
);
PySSL_END_ALLOW_THREADS
PySSL_END_ALLOW_THREADS
if
(
count
<
0
)
if
(
count
<
0
)
return
PySSL_SetError
(
self
,
count
,
__FILE__
,
__LINE__
);
return
PySSL_SetError
(
self
,
count
,
__FILE__
,
__LINE__
);
else
else
return
PyInt_FromLong
(
count
);
return
PyInt_FromLong
(
count
);
}
}
PyDoc_STRVAR
(
PySSL_SSLpending_doc
,
PyDoc_STRVAR
(
PySSL_SSLpending_doc
,
...
@@ -1264,96 +1264,96 @@ pending on the connection.\n");
...
@@ -1264,96 +1264,96 @@ pending on the connection.\n");
static
PyObject
*
PySSL_SSLread
(
PySSLObject
*
self
,
PyObject
*
args
)
static
PyObject
*
PySSL_SSLread
(
PySSLObject
*
self
,
PyObject
*
args
)
{
{
PyObject
*
buf
;
PyObject
*
buf
;
int
count
=
0
;
int
count
=
0
;
int
len
=
1024
;
int
len
=
1024
;
int
sockstate
;
int
sockstate
;
int
err
;
int
err
;
int
nonblocking
;
int
nonblocking
;
if
(
!
PyArg_ParseTuple
(
args
,
"|i:read"
,
&
len
))
if
(
!
PyArg_ParseTuple
(
args
,
"|i:read"
,
&
len
))
return
NULL
;
return
NULL
;
if
(
!
(
buf
=
PyString_FromStringAndSize
((
char
*
)
0
,
len
)))
if
(
!
(
buf
=
PyString_FromStringAndSize
((
char
*
)
0
,
len
)))
return
NULL
;
return
NULL
;
/* just in case the blocking state of the socket has been changed */
/* just in case the blocking state of the socket has been changed */
nonblocking
=
(
self
->
Socket
->
sock_timeout
>=
0
.
0
);
nonblocking
=
(
self
->
Socket
->
sock_timeout
>=
0
.
0
);
BIO_set_nbio
(
SSL_get_rbio
(
self
->
ssl
),
nonblocking
);
BIO_set_nbio
(
SSL_get_rbio
(
self
->
ssl
),
nonblocking
);
BIO_set_nbio
(
SSL_get_wbio
(
self
->
ssl
),
nonblocking
);
BIO_set_nbio
(
SSL_get_wbio
(
self
->
ssl
),
nonblocking
);
/* first check if there are bytes ready to be read */
/* first check if there are bytes ready to be read */
PySSL_BEGIN_ALLOW_THREADS
PySSL_BEGIN_ALLOW_THREADS
count
=
SSL_pending
(
self
->
ssl
);
count
=
SSL_pending
(
self
->
ssl
);
PySSL_END_ALLOW_THREADS
PySSL_END_ALLOW_THREADS
if
(
!
count
)
{
if
(
!
count
)
{
sockstate
=
check_socket_and_wait_for_timeout
(
self
->
Socket
,
0
);
sockstate
=
check_socket_and_wait_for_timeout
(
self
->
Socket
,
0
);
if
(
sockstate
==
SOCKET_HAS_TIMED_OUT
)
{
if
(
sockstate
==
SOCKET_HAS_TIMED_OUT
)
{
PyErr_SetString
(
PySSLErrorObject
,
PyErr_SetString
(
PySSLErrorObject
,
"The read operation timed out"
);
"The read operation timed out"
);
Py_DECREF
(
buf
);
Py_DECREF
(
buf
);
return
NULL
;
return
NULL
;
}
else
if
(
sockstate
==
SOCKET_TOO_LARGE_FOR_SELECT
)
{
}
else
if
(
sockstate
==
SOCKET_TOO_LARGE_FOR_SELECT
)
{
PyErr_SetString
(
PySSLErrorObject
,
PyErr_SetString
(
PySSLErrorObject
,
"Underlying socket too large for select()."
);
"Underlying socket too large for select()."
);
Py_DECREF
(
buf
);
Py_DECREF
(
buf
);
return
NULL
;
return
NULL
;
}
else
if
(
sockstate
==
SOCKET_HAS_BEEN_CLOSED
)
{
}
else
if
(
sockstate
==
SOCKET_HAS_BEEN_CLOSED
)
{
if
(
SSL_get_shutdown
(
self
->
ssl
)
!=
if
(
SSL_get_shutdown
(
self
->
ssl
)
!=
SSL_RECEIVED_SHUTDOWN
)
SSL_RECEIVED_SHUTDOWN
)
{
{
Py_DECREF
(
buf
);
Py_DECREF
(
buf
);
PyErr_SetString
(
PySSLErrorObject
,
PyErr_SetString
(
PySSLErrorObject
,
"Socket closed without SSL shutdown handshake"
);
"Socket closed without SSL shutdown handshake"
);
return
NULL
;
return
NULL
;
}
else
{
}
else
{
/* should contain a zero-length string */
/* should contain a zero-length string */
_PyString_Resize
(
&
buf
,
0
);
_PyString_Resize
(
&
buf
,
0
);
return
buf
;
return
buf
;
}
}
}
}
}
}
do
{
do
{
PySSL_BEGIN_ALLOW_THREADS
PySSL_BEGIN_ALLOW_THREADS
count
=
SSL_read
(
self
->
ssl
,
PyString_AsString
(
buf
),
len
);
count
=
SSL_read
(
self
->
ssl
,
PyString_AsString
(
buf
),
len
);
err
=
SSL_get_error
(
self
->
ssl
,
count
);
err
=
SSL_get_error
(
self
->
ssl
,
count
);
PySSL_END_ALLOW_THREADS
PySSL_END_ALLOW_THREADS
if
(
PyErr_CheckSignals
())
{
if
(
PyErr_CheckSignals
())
{
Py_DECREF
(
buf
);
Py_DECREF
(
buf
);
return
NULL
;
return
NULL
;
}
}
if
(
err
==
SSL_ERROR_WANT_READ
)
{
if
(
err
==
SSL_ERROR_WANT_READ
)
{
sockstate
=
sockstate
=
check_socket_and_wait_for_timeout
(
self
->
Socket
,
0
);
check_socket_and_wait_for_timeout
(
self
->
Socket
,
0
);
}
else
if
(
err
==
SSL_ERROR_WANT_WRITE
)
{
}
else
if
(
err
==
SSL_ERROR_WANT_WRITE
)
{
sockstate
=
sockstate
=
check_socket_and_wait_for_timeout
(
self
->
Socket
,
1
);
check_socket_and_wait_for_timeout
(
self
->
Socket
,
1
);
}
else
if
((
err
==
SSL_ERROR_ZERO_RETURN
)
&&
}
else
if
((
err
==
SSL_ERROR_ZERO_RETURN
)
&&
(
SSL_get_shutdown
(
self
->
ssl
)
==
(
SSL_get_shutdown
(
self
->
ssl
)
==
SSL_RECEIVED_SHUTDOWN
))
SSL_RECEIVED_SHUTDOWN
))
{
{
_PyString_Resize
(
&
buf
,
0
);
_PyString_Resize
(
&
buf
,
0
);
return
buf
;
return
buf
;
}
else
{
}
else
{
sockstate
=
SOCKET_OPERATION_OK
;
sockstate
=
SOCKET_OPERATION_OK
;
}
}
if
(
sockstate
==
SOCKET_HAS_TIMED_OUT
)
{
if
(
sockstate
==
SOCKET_HAS_TIMED_OUT
)
{
PyErr_SetString
(
PySSLErrorObject
,
PyErr_SetString
(
PySSLErrorObject
,
"The read operation timed out"
);
"The read operation timed out"
);
Py_DECREF
(
buf
);
Py_DECREF
(
buf
);
return
NULL
;
return
NULL
;
}
else
if
(
sockstate
==
SOCKET_IS_NONBLOCKING
)
{
}
else
if
(
sockstate
==
SOCKET_IS_NONBLOCKING
)
{
break
;
break
;
}
}
}
while
(
err
==
SSL_ERROR_WANT_READ
||
err
==
SSL_ERROR_WANT_WRITE
);
}
while
(
err
==
SSL_ERROR_WANT_READ
||
err
==
SSL_ERROR_WANT_WRITE
);
if
(
count
<=
0
)
{
if
(
count
<=
0
)
{
Py_DECREF
(
buf
);
Py_DECREF
(
buf
);
return
PySSL_SetError
(
self
,
count
,
__FILE__
,
__LINE__
);
return
PySSL_SetError
(
self
,
count
,
__FILE__
,
__LINE__
);
}
}
if
(
count
!=
len
)
if
(
count
!=
len
)
_PyString_Resize
(
&
buf
,
count
);
_PyString_Resize
(
&
buf
,
count
);
return
buf
;
return
buf
;
}
}
PyDoc_STRVAR
(
PySSL_SSLread_doc
,
PyDoc_STRVAR
(
PySSL_SSLread_doc
,
...
@@ -1363,82 +1363,82 @@ Read up to len bytes from the SSL socket.");
...
@@ -1363,82 +1363,82 @@ Read up to len bytes from the SSL socket.");
static
PyObject
*
PySSL_SSLshutdown
(
PySSLObject
*
self
)
static
PyObject
*
PySSL_SSLshutdown
(
PySSLObject
*
self
)
{
{
int
err
,
ssl_err
,
sockstate
,
nonblocking
;
int
err
,
ssl_err
,
sockstate
,
nonblocking
;
int
zeros
=
0
;
int
zeros
=
0
;
/* Guard against closed socket */
/* Guard against closed socket */
if
(
self
->
Socket
->
sock_fd
<
0
)
{
if
(
self
->
Socket
->
sock_fd
<
0
)
{
PyErr_SetString
(
PySSLErrorObject
,
PyErr_SetString
(
PySSLErrorObject
,
"Underlying socket has been closed."
);
"Underlying socket has been closed."
);
return
NULL
;
return
NULL
;
}
}
/* Just in case the blocking state of the socket has been changed */
/* Just in case the blocking state of the socket has been changed */
nonblocking
=
(
self
->
Socket
->
sock_timeout
>=
0
.
0
);
nonblocking
=
(
self
->
Socket
->
sock_timeout
>=
0
.
0
);
BIO_set_nbio
(
SSL_get_rbio
(
self
->
ssl
),
nonblocking
);
BIO_set_nbio
(
SSL_get_rbio
(
self
->
ssl
),
nonblocking
);
BIO_set_nbio
(
SSL_get_wbio
(
self
->
ssl
),
nonblocking
);
BIO_set_nbio
(
SSL_get_wbio
(
self
->
ssl
),
nonblocking
);
while
(
1
)
{
while
(
1
)
{
PySSL_BEGIN_ALLOW_THREADS
PySSL_BEGIN_ALLOW_THREADS
/* Disable read-ahead so that unwrap can work correctly.
/* Disable read-ahead so that unwrap can work correctly.
* Otherwise OpenSSL might read in too much data,
* Otherwise OpenSSL might read in too much data,
* eating clear text data that happens to be
* eating clear text data that happens to be
* transmitted after the SSL shutdown.
* transmitted after the SSL shutdown.
* Should be safe to call repeatedly everytime this
* Should be safe to call repeatedly everytime this
* function is used and the shutdown_seen_zero != 0
* function is used and the shutdown_seen_zero != 0
* condition is met.
* condition is met.
*/
*/
if
(
self
->
shutdown_seen_zero
)
if
(
self
->
shutdown_seen_zero
)
SSL_set_read_ahead
(
self
->
ssl
,
0
);
SSL_set_read_ahead
(
self
->
ssl
,
0
);
err
=
SSL_shutdown
(
self
->
ssl
);
err
=
SSL_shutdown
(
self
->
ssl
);
PySSL_END_ALLOW_THREADS
PySSL_END_ALLOW_THREADS
/* If err == 1, a secure shutdown with SSL_shutdown() is complete */
/* If err == 1, a secure shutdown with SSL_shutdown() is complete */
if
(
err
>
0
)
if
(
err
>
0
)
break
;
break
;
if
(
err
==
0
)
{
if
(
err
==
0
)
{
/* Don't loop endlessly; instead preserve legacy
/* Don't loop endlessly; instead preserve legacy
behaviour of trying SSL_shutdown() only twice.
behaviour of trying SSL_shutdown() only twice.
This looks necessary for OpenSSL < 0.9.8m */
This looks necessary for OpenSSL < 0.9.8m */
if
(
++
zeros
>
1
)
if
(
++
zeros
>
1
)
break
;
break
;
/* Shutdown was sent, now try receiving */
/* Shutdown was sent, now try receiving */
self
->
shutdown_seen_zero
=
1
;
self
->
shutdown_seen_zero
=
1
;
continue
;
continue
;
}
}
/* Possibly retry shutdown until timeout or failure */
/* Possibly retry shutdown until timeout or failure */
ssl_err
=
SSL_get_error
(
self
->
ssl
,
err
);
ssl_err
=
SSL_get_error
(
self
->
ssl
,
err
);
if
(
ssl_err
==
SSL_ERROR_WANT_READ
)
if
(
ssl_err
==
SSL_ERROR_WANT_READ
)
sockstate
=
check_socket_and_wait_for_timeout
(
self
->
Socket
,
0
);
sockstate
=
check_socket_and_wait_for_timeout
(
self
->
Socket
,
0
);
else
if
(
ssl_err
==
SSL_ERROR_WANT_WRITE
)
else
if
(
ssl_err
==
SSL_ERROR_WANT_WRITE
)
sockstate
=
check_socket_and_wait_for_timeout
(
self
->
Socket
,
1
);
sockstate
=
check_socket_and_wait_for_timeout
(
self
->
Socket
,
1
);
else
else
break
;
break
;
if
(
sockstate
==
SOCKET_HAS_TIMED_OUT
)
{
if
(
sockstate
==
SOCKET_HAS_TIMED_OUT
)
{
if
(
ssl_err
==
SSL_ERROR_WANT_READ
)
if
(
ssl_err
==
SSL_ERROR_WANT_READ
)
PyErr_SetString
(
PySSLErrorObject
,
PyErr_SetString
(
PySSLErrorObject
,
"The read operation timed out"
);
"The read operation timed out"
);
else
else
PyErr_SetString
(
PySSLErrorObject
,
PyErr_SetString
(
PySSLErrorObject
,
"The write operation timed out"
);
"The write operation timed out"
);
return
NULL
;
return
NULL
;
}
}
else
if
(
sockstate
==
SOCKET_TOO_LARGE_FOR_SELECT
)
{
else
if
(
sockstate
==
SOCKET_TOO_LARGE_FOR_SELECT
)
{
PyErr_SetString
(
PySSLErrorObject
,
PyErr_SetString
(
PySSLErrorObject
,
"Underlying socket too large for select()."
);
"Underlying socket too large for select()."
);
return
NULL
;
return
NULL
;
}
}
else
if
(
sockstate
!=
SOCKET_OPERATION_OK
)
else
if
(
sockstate
!=
SOCKET_OPERATION_OK
)
/* Retain the SSL error code */
/* Retain the SSL error code */
break
;
break
;
}
}
if
(
err
<
0
)
if
(
err
<
0
)
return
PySSL_SetError
(
self
,
err
,
__FILE__
,
__LINE__
);
return
PySSL_SetError
(
self
,
err
,
__FILE__
,
__LINE__
);
else
{
else
{
Py_INCREF
(
self
->
Socket
);
Py_INCREF
(
self
->
Socket
);
return
(
PyObject
*
)
(
self
->
Socket
);
return
(
PyObject
*
)
(
self
->
Socket
);
}
}
}
}
PyDoc_STRVAR
(
PySSL_SSLshutdown_doc
,
PyDoc_STRVAR
(
PySSL_SSLshutdown_doc
,
...
@@ -1448,44 +1448,44 @@ Does the SSL shutdown handshake with the remote end, and returns\n\
...
@@ -1448,44 +1448,44 @@ Does the SSL shutdown handshake with the remote end, and returns\n\
the underlying socket object."
);
the underlying socket object."
);
static
PyMethodDef
PySSLMethods
[]
=
{
static
PyMethodDef
PySSLMethods
[]
=
{
{
"do_handshake"
,
(
PyCFunction
)
PySSL_SSLdo_handshake
,
METH_NOARGS
},
{
"do_handshake"
,
(
PyCFunction
)
PySSL_SSLdo_handshake
,
METH_NOARGS
},
{
"write"
,
(
PyCFunction
)
PySSL_SSLwrite
,
METH_VARARGS
,
{
"write"
,
(
PyCFunction
)
PySSL_SSLwrite
,
METH_VARARGS
,
PySSL_SSLwrite_doc
},
PySSL_SSLwrite_doc
},
{
"read"
,
(
PyCFunction
)
PySSL_SSLread
,
METH_VARARGS
,
{
"read"
,
(
PyCFunction
)
PySSL_SSLread
,
METH_VARARGS
,
PySSL_SSLread_doc
},
PySSL_SSLread_doc
},
{
"pending"
,
(
PyCFunction
)
PySSL_SSLpending
,
METH_NOARGS
,
{
"pending"
,
(
PyCFunction
)
PySSL_SSLpending
,
METH_NOARGS
,
PySSL_SSLpending_doc
},
PySSL_SSLpending_doc
},
{
"server"
,
(
PyCFunction
)
PySSL_server
,
METH_NOARGS
},
{
"server"
,
(
PyCFunction
)
PySSL_server
,
METH_NOARGS
},
{
"issuer"
,
(
PyCFunction
)
PySSL_issuer
,
METH_NOARGS
},
{
"issuer"
,
(
PyCFunction
)
PySSL_issuer
,
METH_NOARGS
},
{
"peer_certificate"
,
(
PyCFunction
)
PySSL_peercert
,
METH_VARARGS
,
{
"peer_certificate"
,
(
PyCFunction
)
PySSL_peercert
,
METH_VARARGS
,
PySSL_peercert_doc
},
PySSL_peercert_doc
},
{
"cipher"
,
(
PyCFunction
)
PySSL_cipher
,
METH_NOARGS
},
{
"cipher"
,
(
PyCFunction
)
PySSL_cipher
,
METH_NOARGS
},
{
"shutdown"
,
(
PyCFunction
)
PySSL_SSLshutdown
,
METH_NOARGS
,
{
"shutdown"
,
(
PyCFunction
)
PySSL_SSLshutdown
,
METH_NOARGS
,
PySSL_SSLshutdown_doc
},
PySSL_SSLshutdown_doc
},
{
NULL
,
NULL
}
{
NULL
,
NULL
}
};
};
static
PyObject
*
PySSL_getattr
(
PySSLObject
*
self
,
char
*
name
)
static
PyObject
*
PySSL_getattr
(
PySSLObject
*
self
,
char
*
name
)
{
{
return
Py_FindMethod
(
PySSLMethods
,
(
PyObject
*
)
self
,
name
);
return
Py_FindMethod
(
PySSLMethods
,
(
PyObject
*
)
self
,
name
);
}
}
static
PyTypeObject
PySSL_Type
=
{
static
PyTypeObject
PySSL_Type
=
{
PyVarObject_HEAD_INIT
(
NULL
,
0
)
PyVarObject_HEAD_INIT
(
NULL
,
0
)
"ssl.SSLContext"
,
/*tp_name*/
"ssl.SSLContext"
,
/*tp_name*/
sizeof
(
PySSLObject
),
/*tp_basicsize*/
sizeof
(
PySSLObject
),
/*tp_basicsize*/
0
,
/*tp_itemsize*/
0
,
/*tp_itemsize*/
/* methods */
/* methods */
(
destructor
)
PySSL_dealloc
,
/*tp_dealloc*/
(
destructor
)
PySSL_dealloc
,
/*tp_dealloc*/
0
,
/*tp_print*/
0
,
/*tp_print*/
(
getattrfunc
)
PySSL_getattr
,
/*tp_getattr*/
(
getattrfunc
)
PySSL_getattr
,
/*tp_getattr*/
0
,
/*tp_setattr*/
0
,
/*tp_setattr*/
0
,
/*tp_compare*/
0
,
/*tp_compare*/
0
,
/*tp_repr*/
0
,
/*tp_repr*/
0
,
/*tp_as_number*/
0
,
/*tp_as_number*/
0
,
/*tp_as_sequence*/
0
,
/*tp_as_sequence*/
0
,
/*tp_as_mapping*/
0
,
/*tp_as_mapping*/
0
,
/*tp_hash*/
0
,
/*tp_hash*/
};
};
#ifdef HAVE_OPENSSL_RAND
#ifdef HAVE_OPENSSL_RAND
...
@@ -1499,7 +1499,7 @@ PySSL_RAND_add(PyObject *self, PyObject *args)
...
@@ -1499,7 +1499,7 @@ PySSL_RAND_add(PyObject *self, PyObject *args)
double
entropy
;
double
entropy
;
if
(
!
PyArg_ParseTuple
(
args
,
"s#d:RAND_add"
,
&
buf
,
&
len
,
&
entropy
))
if
(
!
PyArg_ParseTuple
(
args
,
"s#d:RAND_add"
,
&
buf
,
&
len
,
&
entropy
))
return
NULL
;
return
NULL
;
RAND_add
(
buf
,
len
,
entropy
);
RAND_add
(
buf
,
len
,
entropy
);
Py_INCREF
(
Py_None
);
Py_INCREF
(
Py_None
);
return
Py_None
;
return
Py_None
;
...
@@ -1530,15 +1530,15 @@ PySSL_RAND_egd(PyObject *self, PyObject *arg)
...
@@ -1530,15 +1530,15 @@ PySSL_RAND_egd(PyObject *self, PyObject *arg)
int
bytes
;
int
bytes
;
if
(
!
PyString_Check
(
arg
))
if
(
!
PyString_Check
(
arg
))
return
PyErr_Format
(
PyExc_TypeError
,
return
PyErr_Format
(
PyExc_TypeError
,
"RAND_egd() expected string, found %s"
,
"RAND_egd() expected string, found %s"
,
Py_TYPE
(
arg
)
->
tp_name
);
Py_TYPE
(
arg
)
->
tp_name
);
bytes
=
RAND_egd
(
PyString_AS_STRING
(
arg
));
bytes
=
RAND_egd
(
PyString_AS_STRING
(
arg
));
if
(
bytes
==
-
1
)
{
if
(
bytes
==
-
1
)
{
PyErr_SetString
(
PySSLErrorObject
,
PyErr_SetString
(
PySSLErrorObject
,
"EGD connection failed or EGD did not return "
"EGD connection failed or EGD did not return "
"enough data to seed the PRNG"
);
"enough data to seed the PRNG"
);
return
NULL
;
return
NULL
;
}
}
return
PyInt_FromLong
(
bytes
);
return
PyInt_FromLong
(
bytes
);
}
}
...
@@ -1555,19 +1555,19 @@ fails or if it does provide enough data to seed PRNG.");
...
@@ -1555,19 +1555,19 @@ fails or if it does provide enough data to seed PRNG.");
/* List of functions exported by this module. */
/* List of functions exported by this module. */
static
PyMethodDef
PySSL_methods
[]
=
{
static
PyMethodDef
PySSL_methods
[]
=
{
{
"sslwrap"
,
PySSL_sslwrap
,
{
"sslwrap"
,
PySSL_sslwrap
,
METH_VARARGS
,
ssl_doc
},
METH_VARARGS
,
ssl_doc
},
{
"_test_decode_cert"
,
PySSL_test_decode_certificate
,
{
"_test_decode_cert"
,
PySSL_test_decode_certificate
,
METH_VARARGS
},
METH_VARARGS
},
#ifdef HAVE_OPENSSL_RAND
#ifdef HAVE_OPENSSL_RAND
{
"RAND_add"
,
PySSL_RAND_add
,
METH_VARARGS
,
{
"RAND_add"
,
PySSL_RAND_add
,
METH_VARARGS
,
PySSL_RAND_add_doc
},
PySSL_RAND_add_doc
},
{
"RAND_egd"
,
PySSL_RAND_egd
,
METH_O
,
{
"RAND_egd"
,
PySSL_RAND_egd
,
METH_O
,
PySSL_RAND_egd_doc
},
PySSL_RAND_egd_doc
},
{
"RAND_status"
,
(
PyCFunction
)
PySSL_RAND_status
,
METH_NOARGS
,
{
"RAND_status"
,
(
PyCFunction
)
PySSL_RAND_status
,
METH_NOARGS
,
PySSL_RAND_status_doc
},
PySSL_RAND_status_doc
},
#endif
#endif
{
NULL
,
NULL
}
/* Sentinel */
{
NULL
,
NULL
}
/* Sentinel */
};
};
...
@@ -1579,64 +1579,64 @@ static PyMethodDef PySSL_methods[] = {
...
@@ -1579,64 +1579,64 @@ static PyMethodDef PySSL_methods[] = {
static
PyThread_type_lock
*
_ssl_locks
=
NULL
;
static
PyThread_type_lock
*
_ssl_locks
=
NULL
;
static
unsigned
long
_ssl_thread_id_function
(
void
)
{
static
unsigned
long
_ssl_thread_id_function
(
void
)
{
return
PyThread_get_thread_ident
();
return
PyThread_get_thread_ident
();
}
}
static
void
_ssl_thread_locking_function
(
int
mode
,
int
n
,
const
char
*
file
,
int
line
)
{
static
void
_ssl_thread_locking_function
(
int
mode
,
int
n
,
const
char
*
file
,
int
line
)
{
/* this function is needed to perform locking on shared data
/* this function is needed to perform locking on shared data
structures. (Note that OpenSSL uses a number of global data
structures. (Note that OpenSSL uses a number of global data
structures that will be implicitly shared whenever multiple threads
structures that will be implicitly shared whenever multiple threads
use OpenSSL.) Multi-threaded applications will crash at random if
use OpenSSL.) Multi-threaded applications will crash at random if
it is not set.
it is not set.
locking_function() must be able to handle up to CRYPTO_num_locks()
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
different mutex locks. It sets the n-th lock if mode & CRYPTO_LOCK, and
releases it otherwise.
releases it otherwise.
file and line are the file number of the function setting the
file and line are the file number of the function setting the
lock. They can be useful for debugging.
lock. They can be useful for debugging.
*/
*/
if
((
_ssl_locks
==
NULL
)
||
if
((
_ssl_locks
==
NULL
)
||
(
n
<
0
)
||
((
unsigned
)
n
>=
_ssl_locks_count
))
(
n
<
0
)
||
((
unsigned
)
n
>=
_ssl_locks_count
))
return
;
return
;
if
(
mode
&
CRYPTO_LOCK
)
{
if
(
mode
&
CRYPTO_LOCK
)
{
PyThread_acquire_lock
(
_ssl_locks
[
n
],
1
);
PyThread_acquire_lock
(
_ssl_locks
[
n
],
1
);
}
else
{
}
else
{
PyThread_release_lock
(
_ssl_locks
[
n
]);
PyThread_release_lock
(
_ssl_locks
[
n
]);
}
}
}
}
static
int
_setup_ssl_threads
(
void
)
{
static
int
_setup_ssl_threads
(
void
)
{
unsigned
int
i
;
unsigned
int
i
;
if
(
_ssl_locks
==
NULL
)
{
if
(
_ssl_locks
==
NULL
)
{
_ssl_locks_count
=
CRYPTO_num_locks
();
_ssl_locks_count
=
CRYPTO_num_locks
();
_ssl_locks
=
(
PyThread_type_lock
*
)
_ssl_locks
=
(
PyThread_type_lock
*
)
malloc
(
sizeof
(
PyThread_type_lock
)
*
_ssl_locks_count
);
malloc
(
sizeof
(
PyThread_type_lock
)
*
_ssl_locks_count
);
if
(
_ssl_locks
==
NULL
)
if
(
_ssl_locks
==
NULL
)
return
0
;
return
0
;
memset
(
_ssl_locks
,
0
,
sizeof
(
PyThread_type_lock
)
*
_ssl_locks_count
);
memset
(
_ssl_locks
,
0
,
sizeof
(
PyThread_type_lock
)
*
_ssl_locks_count
);
for
(
i
=
0
;
i
<
_ssl_locks_count
;
i
++
)
{
for
(
i
=
0
;
i
<
_ssl_locks_count
;
i
++
)
{
_ssl_locks
[
i
]
=
PyThread_allocate_lock
();
_ssl_locks
[
i
]
=
PyThread_allocate_lock
();
if
(
_ssl_locks
[
i
]
==
NULL
)
{
if
(
_ssl_locks
[
i
]
==
NULL
)
{
unsigned
int
j
;
unsigned
int
j
;
for
(
j
=
0
;
j
<
i
;
j
++
)
{
for
(
j
=
0
;
j
<
i
;
j
++
)
{
PyThread_free_lock
(
_ssl_locks
[
j
]);
PyThread_free_lock
(
_ssl_locks
[
j
]);
}
}
free
(
_ssl_locks
);
free
(
_ssl_locks
);
return
0
;
return
0
;
}
}
}
}
CRYPTO_set_locking_callback
(
_ssl_thread_locking_function
);
CRYPTO_set_locking_callback
(
_ssl_thread_locking_function
);
CRYPTO_set_id_callback
(
_ssl_thread_id_function
);
CRYPTO_set_id_callback
(
_ssl_thread_id_function
);
}
}
return
1
;
return
1
;
}
}
#endif
/* def HAVE_THREAD */
#endif
/* def HAVE_THREAD */
PyDoc_STRVAR
(
module_doc
,
PyDoc_STRVAR
(
module_doc
,
"Implementation module for SSL socket operations. See the socket module
\n
\
"Implementation module for SSL socket operations. See the socket module
\n
\
...
@@ -1645,103 +1645,103 @@ for documentation.");
...
@@ -1645,103 +1645,103 @@ for documentation.");
PyMODINIT_FUNC
PyMODINIT_FUNC
init_ssl
(
void
)
init_ssl
(
void
)
{
{
PyObject
*
m
,
*
d
,
*
r
;
PyObject
*
m
,
*
d
,
*
r
;
unsigned
long
libver
;
unsigned
long
libver
;
unsigned
int
major
,
minor
,
fix
,
patch
,
status
;
unsigned
int
major
,
minor
,
fix
,
patch
,
status
;
Py_TYPE
(
&
PySSL_Type
)
=
&
PyType_Type
;
Py_TYPE
(
&
PySSL_Type
)
=
&
PyType_Type
;
m
=
Py_InitModule3
(
"_ssl"
,
PySSL_methods
,
module_doc
);
m
=
Py_InitModule3
(
"_ssl"
,
PySSL_methods
,
module_doc
);
if
(
m
==
NULL
)
if
(
m
==
NULL
)
return
;
return
;
d
=
PyModule_GetDict
(
m
);
d
=
PyModule_GetDict
(
m
);
/* Load _socket module and its C API */
/* Load _socket module and its C API */
if
(
PySocketModule_ImportModuleAndAPI
())
if
(
PySocketModule_ImportModuleAndAPI
())
return
;
return
;
/* Init OpenSSL */
/* Init OpenSSL */
SSL_load_error_strings
();
SSL_load_error_strings
();
SSL_library_init
();
SSL_library_init
();
#ifdef WITH_THREAD
#ifdef WITH_THREAD
/* note that this will start threading if not already started */
/* note that this will start threading if not already started */
if
(
!
_setup_ssl_threads
())
{
if
(
!
_setup_ssl_threads
())
{
return
;
return
;
}
}
#endif
#endif
OpenSSL_add_all_algorithms
();
OpenSSL_add_all_algorithms
();
/* Add symbols to module dict */
/* Add symbols to module dict */
PySSLErrorObject
=
PyErr_NewException
(
"ssl.SSLError"
,
PySSLErrorObject
=
PyErr_NewException
(
"ssl.SSLError"
,
PySocketModule
.
error
,
PySocketModule
.
error
,
NULL
);
NULL
);
if
(
PySSLErrorObject
==
NULL
)
if
(
PySSLErrorObject
==
NULL
)
return
;
return
;
if
(
PyDict_SetItemString
(
d
,
"SSLError"
,
PySSLErrorObject
)
!=
0
)
if
(
PyDict_SetItemString
(
d
,
"SSLError"
,
PySSLErrorObject
)
!=
0
)
return
;
return
;
if
(
PyDict_SetItemString
(
d
,
"SSLType"
,
if
(
PyDict_SetItemString
(
d
,
"SSLType"
,
(
PyObject
*
)
&
PySSL_Type
)
!=
0
)
(
PyObject
*
)
&
PySSL_Type
)
!=
0
)
return
;
return
;
PyModule_AddIntConstant
(
m
,
"SSL_ERROR_ZERO_RETURN"
,
PyModule_AddIntConstant
(
m
,
"SSL_ERROR_ZERO_RETURN"
,
PY_SSL_ERROR_ZERO_RETURN
);
PY_SSL_ERROR_ZERO_RETURN
);
PyModule_AddIntConstant
(
m
,
"SSL_ERROR_WANT_READ"
,
PyModule_AddIntConstant
(
m
,
"SSL_ERROR_WANT_READ"
,
PY_SSL_ERROR_WANT_READ
);
PY_SSL_ERROR_WANT_READ
);
PyModule_AddIntConstant
(
m
,
"SSL_ERROR_WANT_WRITE"
,
PyModule_AddIntConstant
(
m
,
"SSL_ERROR_WANT_WRITE"
,
PY_SSL_ERROR_WANT_WRITE
);
PY_SSL_ERROR_WANT_WRITE
);
PyModule_AddIntConstant
(
m
,
"SSL_ERROR_WANT_X509_LOOKUP"
,
PyModule_AddIntConstant
(
m
,
"SSL_ERROR_WANT_X509_LOOKUP"
,
PY_SSL_ERROR_WANT_X509_LOOKUP
);
PY_SSL_ERROR_WANT_X509_LOOKUP
);
PyModule_AddIntConstant
(
m
,
"SSL_ERROR_SYSCALL"
,
PyModule_AddIntConstant
(
m
,
"SSL_ERROR_SYSCALL"
,
PY_SSL_ERROR_SYSCALL
);
PY_SSL_ERROR_SYSCALL
);
PyModule_AddIntConstant
(
m
,
"SSL_ERROR_SSL"
,
PyModule_AddIntConstant
(
m
,
"SSL_ERROR_SSL"
,
PY_SSL_ERROR_SSL
);
PY_SSL_ERROR_SSL
);
PyModule_AddIntConstant
(
m
,
"SSL_ERROR_WANT_CONNECT"
,
PyModule_AddIntConstant
(
m
,
"SSL_ERROR_WANT_CONNECT"
,
PY_SSL_ERROR_WANT_CONNECT
);
PY_SSL_ERROR_WANT_CONNECT
);
/* non ssl.h errorcodes */
/* non ssl.h errorcodes */
PyModule_AddIntConstant
(
m
,
"SSL_ERROR_EOF"
,
PyModule_AddIntConstant
(
m
,
"SSL_ERROR_EOF"
,
PY_SSL_ERROR_EOF
);
PY_SSL_ERROR_EOF
);
PyModule_AddIntConstant
(
m
,
"SSL_ERROR_INVALID_ERROR_CODE"
,
PyModule_AddIntConstant
(
m
,
"SSL_ERROR_INVALID_ERROR_CODE"
,
PY_SSL_ERROR_INVALID_ERROR_CODE
);
PY_SSL_ERROR_INVALID_ERROR_CODE
);
/* cert requirements */
/* cert requirements */
PyModule_AddIntConstant
(
m
,
"CERT_NONE"
,
PyModule_AddIntConstant
(
m
,
"CERT_NONE"
,
PY_SSL_CERT_NONE
);
PY_SSL_CERT_NONE
);
PyModule_AddIntConstant
(
m
,
"CERT_OPTIONAL"
,
PyModule_AddIntConstant
(
m
,
"CERT_OPTIONAL"
,
PY_SSL_CERT_OPTIONAL
);
PY_SSL_CERT_OPTIONAL
);
PyModule_AddIntConstant
(
m
,
"CERT_REQUIRED"
,
PyModule_AddIntConstant
(
m
,
"CERT_REQUIRED"
,
PY_SSL_CERT_REQUIRED
);
PY_SSL_CERT_REQUIRED
);
/* protocol versions */
/* protocol versions */
PyModule_AddIntConstant
(
m
,
"PROTOCOL_SSLv2"
,
PyModule_AddIntConstant
(
m
,
"PROTOCOL_SSLv2"
,
PY_SSL_VERSION_SSL2
);
PY_SSL_VERSION_SSL2
);
PyModule_AddIntConstant
(
m
,
"PROTOCOL_SSLv3"
,
PyModule_AddIntConstant
(
m
,
"PROTOCOL_SSLv3"
,
PY_SSL_VERSION_SSL3
);
PY_SSL_VERSION_SSL3
);
PyModule_AddIntConstant
(
m
,
"PROTOCOL_SSLv23"
,
PyModule_AddIntConstant
(
m
,
"PROTOCOL_SSLv23"
,
PY_SSL_VERSION_SSL23
);
PY_SSL_VERSION_SSL23
);
PyModule_AddIntConstant
(
m
,
"PROTOCOL_TLSv1"
,
PyModule_AddIntConstant
(
m
,
"PROTOCOL_TLSv1"
,
PY_SSL_VERSION_TLS1
);
PY_SSL_VERSION_TLS1
);
/* OpenSSL version */
/* OpenSSL version */
/* SSLeay() gives us the version of the library linked against,
/* SSLeay() gives us the version of the library linked against,
which could be different from the headers version.
which could be different from the headers version.
*/
*/
libver
=
SSLeay
();
libver
=
SSLeay
();
r
=
PyLong_FromUnsignedLong
(
libver
);
r
=
PyLong_FromUnsignedLong
(
libver
);
if
(
r
==
NULL
)
if
(
r
==
NULL
)
return
;
return
;
if
(
PyModule_AddObject
(
m
,
"OPENSSL_VERSION_NUMBER"
,
r
))
if
(
PyModule_AddObject
(
m
,
"OPENSSL_VERSION_NUMBER"
,
r
))
return
;
return
;
status
=
libver
&
0xF
;
status
=
libver
&
0xF
;
libver
>>=
4
;
libver
>>=
4
;
patch
=
libver
&
0xFF
;
patch
=
libver
&
0xFF
;
libver
>>=
8
;
libver
>>=
8
;
fix
=
libver
&
0xFF
;
fix
=
libver
&
0xFF
;
libver
>>=
8
;
libver
>>=
8
;
minor
=
libver
&
0xFF
;
minor
=
libver
&
0xFF
;
libver
>>=
8
;
libver
>>=
8
;
major
=
libver
&
0xFF
;
major
=
libver
&
0xFF
;
r
=
Py_BuildValue
(
"IIIII"
,
major
,
minor
,
fix
,
patch
,
status
);
r
=
Py_BuildValue
(
"IIIII"
,
major
,
minor
,
fix
,
patch
,
status
);
if
(
r
==
NULL
||
PyModule_AddObject
(
m
,
"OPENSSL_VERSION_INFO"
,
r
))
if
(
r
==
NULL
||
PyModule_AddObject
(
m
,
"OPENSSL_VERSION_INFO"
,
r
))
return
;
return
;
r
=
PyString_FromString
(
SSLeay_version
(
SSLEAY_VERSION
));
r
=
PyString_FromString
(
SSLeay_version
(
SSLEAY_VERSION
));
if
(
r
==
NULL
||
PyModule_AddObject
(
m
,
"OPENSSL_VERSION"
,
r
))
if
(
r
==
NULL
||
PyModule_AddObject
(
m
,
"OPENSSL_VERSION"
,
r
))
return
;
return
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment