Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
gajim
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
pg mr
gajim
Commits
1e006745
Commit
1e006745
authored
16 years ago
by
steve-e
Browse files
Options
Downloads
Patches
Plain Diff
Coding standards and documentation improvements in tls_nb.py
parent
5c02a907
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/common/xmpp/tls_nb.py
+97
-77
97 additions, 77 deletions
src/common/xmpp/tls_nb.py
with
97 additions
and
77 deletions
src/common/xmpp/tls_nb.py
+
97
−
77
View file @
1e006745
...
...
@@ -17,11 +17,9 @@
import
socket
from
client
import
PlugIn
from
protocol
import
*
import
sys
import
os
import
errno
import
time
import
traceback
...
...
@@ -48,25 +46,27 @@
print
>>
sys
.
stderr
,
"
PyOpenSSL not found, falling back to Python builtin SSL objects (insecure).
"
print
>>
sys
.
stderr
,
"
=
"
*
79
def
torf
(
cond
,
tv
,
fv
):
if
cond
:
return
tv
return
fv
def
gattr
(
obj
,
attr
,
default
=
None
):
try
:
return
getattr
(
obj
,
attr
)
except
:
except
AttributeError
:
return
default
class
SSLWrapper
:
'''
Abstract SSLWrapper base class
'''
class
Error
(
IOError
):
def
__init__
(
self
,
sock
=
None
,
exc
=
None
,
errno
=
None
,
strerror
=
None
,
peer
=
None
):
'''
Generic SSL Error Wrapper
'''
def
__init__
(
self
,
sock
=
None
,
exc
=
None
,
errno
=
None
,
strerror
=
None
,
peer
=
None
):
self
.
parent
=
IOError
errno
=
errno
or
gattr
(
exc
,
'
errno
'
)
strerror
=
strerror
or
gattr
(
exc
,
'
strerror
'
)
or
gattr
(
exc
,
'
args
'
)
if
not
isinstance
(
strerror
,
basestring
):
strerror
=
repr
(
strerror
)
if
not
isinstance
(
strerror
,
basestring
):
strerror
=
repr
(
strerror
)
self
.
sock
=
sock
self
.
exc
=
exc
...
...
@@ -97,17 +97,22 @@ def __init__(self, sock=None, exc=None, errno=None, strerror=None, peer=None):
if
len
(
ppeer
)
==
2
and
isinstance
(
ppeer
[
0
],
basestring
)
\
and
isinstance
(
ppeer
[
1
],
int
):
self
.
peer
=
ppeer
except
:
pass
except
:
pass
def
__str__
(
self
):
s
=
str
(
self
.
__class__
)
if
self
.
peer
:
s
+=
"
for %s:%d
"
%
self
.
peer
if
self
.
errno
is
not
None
:
s
+=
"
: [Errno: %d]
"
%
self
.
errno
if
self
.
strerror
:
s
+=
"
(%s)
"
%
self
.
strerror
if
self
.
peer
:
s
+=
"
for %s:%d
"
%
self
.
peer
if
self
.
errno
is
not
None
:
s
+=
"
: [Errno: %d]
"
%
self
.
errno
if
self
.
strerror
:
s
+=
"
(%s)
"
%
self
.
strerror
if
self
.
exc_name
:
s
+=
"
, Caused by %s
"
%
self
.
exc_name
if
self
.
exc_str
:
if
self
.
strerror
:
s
+=
"
(%s)
"
%
self
.
exc_str
if
self
.
strerror
:
s
+=
"
(%s)
"
%
self
.
exc_str
else
:
s
+=
"
(%s)
"
%
str
(
self
.
exc_args
)
return
s
...
...
@@ -117,18 +122,21 @@ def __init__(self, sslobj, sock=None):
log
.
debug
(
"
%s.__init__ called with %s
"
,
self
.
__class__
,
sslobj
)
def
recv
(
self
,
data
,
flags
=
None
):
'''
Receive wrapper for SSL object
'''
Receive wrapper for SSL object
We can return None out of this function to signal that no data is
available right now. Better than an exception, which differs
depending on which SSL lib we
'
re using. Unfortunately returning
''
can indicate that the socket has been closed, so to be sure, we avoid
this by returning None.
'''
this by returning None.
'''
raise
NotImplementedError
raise
NotImplementedException
()
def
send
(
self
,
data
,
flags
=
None
,
now
=
False
):
'''
Send wrapper for SSL object
'''
raise
NotImplementedError
def
send
(
self
,
data
,
flags
=
None
,
now
=
False
):
raise
NotImplementedException
()
class
PyOpenSSLWrapper
(
SSLWrapper
):
'''
Wrapper class for PyOpenSSL
'
s recv() and send() methods
'''
...
...
@@ -138,21 +146,24 @@ def __init__(self, *args):
self
.
parent
.
__init__
(
self
,
*
args
)
def
is_numtoolarge
(
self
,
e
):
'''
Magic methods don
'
t need documentation
'''
t
=
(
'
asn1 encoding routines
'
,
'
a2d_ASN1_OBJECT
'
,
'
first num too large
'
)
return
isinstance
(
e
.
args
,
(
list
,
tuple
))
and
len
(
e
.
args
)
==
1
and
\
isinstance
(
e
.
args
[
0
],
(
list
,
tuple
))
and
len
(
e
.
args
[
0
])
==
2
and
\
e
.
args
[
0
][
0
]
==
e
.
args
[
0
][
1
]
==
t
return
(
isinstance
(
e
.
args
,
(
list
,
tuple
))
and
len
(
e
.
args
)
==
1
and
isinstance
(
e
.
args
[
0
],
(
list
,
tuple
))
and
len
(
e
.
args
[
0
])
==
2
and
e
.
args
[
0
][
0
]
==
e
.
args
[
0
][
1
]
==
t
)
def
recv
(
self
,
bufsize
,
flags
=
None
):
retval
=
None
try
:
if
flags
is
None
:
retval
=
self
.
sslobj
.
recv
(
bufsize
)
else
:
retval
=
self
.
sslobj
.
recv
(
bufsize
,
flags
)
if
flags
is
None
:
retval
=
self
.
sslobj
.
recv
(
bufsize
)
else
:
retval
=
self
.
sslobj
.
recv
(
bufsize
,
flags
)
except
(
OpenSSL
.
SSL
.
WantReadError
,
OpenSSL
.
SSL
.
WantWriteError
),
e
:
log
.
debug
(
"
Recv: Want-error:
"
+
repr
(
e
))
except
OpenSSL
.
SSL
.
SysCallError
,
e
:
log
.
debug
(
"
Recv: Got OpenSSL.SSL.SysCallError:
"
+
repr
(
e
),
exc_info
=
True
)
#traceback.print_exc(
)
log
.
debug
(
"
Recv: Got OpenSSL.SSL.SysCallError:
"
+
repr
(
e
),
exc_info
=
True
)
raise
SSLWrapper
.
Error
(
self
.
sock
or
self
.
sslobj
,
e
)
except
OpenSSL
.
SSL
.
Error
,
e
:
if
self
.
is_numtoolarge
(
e
):
...
...
@@ -160,22 +171,21 @@ def recv(self, bufsize, flags=None):
log
.
warning
(
"
Recv: OpenSSL: asn1enc: first num too large (ignored)
"
)
else
:
log
.
debug
(
"
Recv: Caught OpenSSL.SSL.Error:
"
,
exc_info
=
True
)
#traceback.print_exc()
#print "Current Stack:"
#traceback.print_stack()
raise
SSLWrapper
.
Error
(
self
.
sock
or
self
.
sslobj
,
e
)
return
retval
def
send
(
self
,
data
,
flags
=
None
,
now
=
False
):
def
send
(
self
,
data
,
flags
=
None
,
now
=
False
):
try
:
if
flags
is
None
:
return
self
.
sslobj
.
send
(
data
)
else
:
return
self
.
sslobj
.
send
(
data
,
flags
)
if
flags
is
None
:
return
self
.
sslobj
.
send
(
data
)
else
:
return
self
.
sslobj
.
send
(
data
,
flags
)
except
(
OpenSSL
.
SSL
.
WantReadError
,
OpenSSL
.
SSL
.
WantWriteError
),
e
:
#log.debug("Send: " + repr(e))
time
.
sleep
(
0.1
)
# prevent 100% CPU usage
except
OpenSSL
.
SSL
.
SysCallError
,
e
:
log
.
error
(
"
Send: Got OpenSSL.SSL.SysCallError:
"
+
repr
(
e
),
exc_info
=
True
)
#traceback.print_exc(
)
log
.
error
(
"
Send: Got OpenSSL.SSL.SysCallError:
"
+
repr
(
e
),
exc_info
=
True
)
raise
SSLWrapper
.
Error
(
self
.
sock
or
self
.
sslobj
,
e
)
except
OpenSSL
.
SSL
.
Error
,
e
:
if
self
.
is_numtoolarge
(
e
):
...
...
@@ -183,12 +193,10 @@ def send(self, data, flags=None, now = False):
log
.
warning
(
"
Send: OpenSSL: asn1enc: first num too large (ignored)
"
)
else
:
log
.
error
(
"
Send: Caught OpenSSL.SSL.Error:
"
,
exc_info
=
True
)
#traceback.print_exc()
#print "Current Stack:"
#traceback.print_stack()
raise
SSLWrapper
.
Error
(
self
.
sock
or
self
.
sslobj
,
e
)
return
0
class
StdlibSSLWrapper
(
SSLWrapper
):
'''
Wrapper class for Python socket.ssl read() and write() methods
'''
...
...
@@ -218,7 +226,12 @@ def send(self, data, flags=None, now = False):
class
NonBlockingTLS
(
PlugIn
):
'''
TLS connection used to encrypts already estabilished tcp connection.
'''
'''
TLS connection used to encrypts already estabilished tcp connection.
Can be plugged into NonBlockingTCP and will make use of StdlibSSLWrapper or
PyOpenSSLWrapper.
'''
def
__init__
(
self
,
cacerts
,
mycerts
):
'''
...
...
@@ -238,7 +251,8 @@ def __init__(self, cacerts, mycerts):
def
PlugIn
(
self
,
owner
):
'''
start using encryption immediately
Use to PlugIn TLS into transport and start establishing immediately
Returns True if TLS/SSL was established correctly, otherwise False.
'''
log
.
info
(
'
Starting TLS estabilishing
'
)
PlugIn
.
PlugIn
(
self
,
owner
)
...
...
@@ -249,14 +263,12 @@ def PlugIn(self, owner):
return
False
return
res
def
_dumpX509
(
self
,
cert
,
stream
=
sys
.
stderr
):
print
>>
stream
,
"
Digest (SHA-1):
"
,
cert
.
digest
(
"
sha1
"
)
print
>>
stream
,
"
Digest (MD5):
"
,
cert
.
digest
(
"
md5
"
)
print
>>
stream
,
"
Serial #:
"
,
cert
.
get_serial_number
()
print
>>
stream
,
"
Version:
"
,
cert
.
get_version
()
print
>>
stream
,
"
Expired:
"
,
torf
(
cert
.
has_expired
()
,
"
Yes
"
,
"
No
"
)
print
>>
stream
,
"
Expired:
"
,
(
"
Yes
"
if
cert
.
has_expired
()
else
"
No
"
)
print
>>
stream
,
"
Subject:
"
self
.
_dumpX509Name
(
cert
.
get_subject
(),
stream
)
print
>>
stream
,
"
Issuer:
"
...
...
@@ -267,23 +279,51 @@ def _dumpX509Name(self, name, stream=sys.stderr):
print
>>
stream
,
"
X509Name:
"
,
str
(
name
)
def
_dumpPKey
(
self
,
pkey
,
stream
=
sys
.
stderr
):
typedict
=
{
OpenSSL
.
crypto
.
TYPE_RSA
:
"
RSA
"
,
OpenSSL
.
crypto
.
TYPE_DSA
:
"
DSA
"
}
typedict
=
{
OpenSSL
.
crypto
.
TYPE_RSA
:
"
RSA
"
,
OpenSSL
.
crypto
.
TYPE_DSA
:
"
DSA
"
}
print
>>
stream
,
"
PKey bits:
"
,
pkey
.
bits
()
print
>>
stream
,
"
PKey type: %s (%d)
"
%
(
typedict
.
get
(
pkey
.
type
(),
"
Unknown
"
),
pkey
.
type
())
print
>>
stream
,
"
PKey type: %s (%d)
"
%
(
typedict
.
get
(
pkey
.
type
(),
"
Unknown
"
),
pkey
.
type
())
def
_startSSL
(
self
):
'''
Immediatedly switch socket to TLS mode. Used internally.
'''
log
.
debug
(
"
_startSSL called
"
)
if
USE_PYOPENSSL
:
result
=
self
.
_startSSL_pyOpenSSL
()
else
:
result
=
self
.
_startSSL_stdlib
()
if
USE_PYOPENSSL
:
result
=
self
.
_startSSL_pyOpenSSL
()
else
:
result
=
self
.
_startSSL_stdlib
()
if
result
:
log
.
debug
(
"
Synchronous handshake completed
"
)
log
.
debug
(
'
Synchronous handshake completed
'
)
return
True
else
:
return
False
def
_load_user_certs
(
self
,
cert_path
,
cert_store
):
if
not
os
.
path
.
isfile
(
cert_path
):
return
f
=
open
(
cert_path
)
lines
=
f
.
readlines
()
i
=
0
begin
=
-
1
for
line
in
lines
:
if
'
BEGIN CERTIFICATE
'
in
line
:
begin
=
i
elif
'
END CERTIFICATE
'
in
line
and
begin
>
-
1
:
cert
=
''
.
join
(
lines
[
begin
:
i
+
2
])
try
:
x509cert
=
OpenSSL
.
crypto
.
load_certificate
(
OpenSSL
.
crypto
.
FILETYPE_PEM
,
cert
)
cert_store
.
add_cert
(
x509cert
)
except
OpenSSL
.
crypto
.
Error
,
exception_obj
:
log
.
warning
(
'
Unable to load a certificate from file %s: %s
'
%
\
(
self
.
mycerts
,
exception_obj
.
args
[
0
][
0
][
2
]))
except
:
log
.
warning
(
'
Unknown error while loading certificate from file%s
'
%
self
.
mycerts
)
begin
=
-
1
i
+=
1
def
_startSSL_pyOpenSSL
(
self
):
log
.
debug
(
"
_startSSL_pyOpenSSL called
"
)
...
...
@@ -292,39 +332,18 @@ def _startSSL_pyOpenSSL(self):
#tcpsock._sslContext = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_METHOD)
tcpsock
.
_sslContext
=
OpenSSL
.
SSL
.
Context
(
OpenSSL
.
SSL
.
SSLv23_METHOD
)
tcpsock
.
ssl_errnum
=
0
tcpsock
.
_sslContext
.
set_verify
(
OpenSSL
.
SSL
.
VERIFY_PEER
,
self
.
_ssl_verify_callback
)
tcpsock
.
_sslContext
.
set_verify
(
OpenSSL
.
SSL
.
VERIFY_PEER
,
self
.
_ssl_verify_callback
)
try
:
tcpsock
.
_sslContext
.
load_verify_locations
(
self
.
cacerts
)
except
:
log
.
warning
(
'
Unable to load SSL certificates from file %s
'
%
\
os
.
path
.
abspath
(
self
.
cacerts
))
# load users certs
if
os
.
path
.
isfile
(
self
.
mycerts
):
store
=
tcpsock
.
_sslContext
.
get_cert_store
()
f
=
open
(
self
.
mycerts
)
lines
=
f
.
readlines
()
i
=
0
begin
=
-
1
for
line
in
lines
:
if
'
BEGIN CERTIFICATE
'
in
line
:
begin
=
i
elif
'
END CERTIFICATE
'
in
line
and
begin
>
-
1
:
cert
=
''
.
join
(
lines
[
begin
:
i
+
2
])
try
:
X509cert
=
OpenSSL
.
crypto
.
load_certificate
(
OpenSSL
.
crypto
.
FILETYPE_PEM
,
cert
)
store
.
add_cert
(
X509cert
)
except
OpenSSL
.
crypto
.
Error
,
exception_obj
:
log
.
warning
(
'
Unable to load a certificate from file %s: %s
'
%
\
(
self
.
mycerts
,
exception_obj
.
args
[
0
][
0
][
2
]))
except
:
log
.
warning
(
'
Unknown error while loading certificate from file %s
'
%
\
self
.
mycerts
)
begin
=
-
1
i
+=
1
tcpsock
.
_sslObj
=
OpenSSL
.
SSL
.
Connection
(
tcpsock
.
_sslContext
,
tcpsock
.
_sock
)
tcpsock
.
_sslObj
.
set_connect_state
()
# set to client mode
self
.
_load_user_certs
(
self
.
mycerts
,
tcpsock
.
_sslContext
.
get_cert_store
())
tcpsock
.
_sslObj
=
OpenSSL
.
SSL
.
Connection
(
tcpsock
.
_sslContext
,
tcpsock
.
_sock
)
tcpsock
.
_sslObj
.
set_connect_state
()
# set to client mode
wrapper
=
PyOpenSSLWrapper
(
tcpsock
.
_sslObj
)
tcpsock
.
_recv
=
wrapper
.
recv
tcpsock
.
_send
=
wrapper
.
send
...
...
@@ -340,7 +359,6 @@ def _startSSL_pyOpenSSL(self):
self
.
_owner
.
ssl_lib
=
PYOPENSSL
return
True
def
_startSSL_stdlib
(
self
):
log
.
debug
(
"
_startSSL_stdlib called
"
)
tcpsock
=
self
.
_owner
...
...
@@ -371,5 +389,7 @@ def _ssl_verify_callback(self, sslconn, cert, errnum, depth, ok):
return
True
except
:
log
.
error
(
"
Exception caught in _ssl_info_callback:
"
,
exc_info
=
True
)
traceback
.
print_exc
()
# Make sure something is printed, even if log is disabled.
# Make sure something is printed, even if log is disabled.
traceback
.
print_exc
()
# vim: se ts=3:
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment