adds full docs

This commit is contained in:
Moisés Guimarães 2017-02-05 18:51:13 -03:00
parent 00a74d0da4
commit e33d4c0172
9 changed files with 225 additions and 53 deletions

View File

@ -18,7 +18,7 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
.PHONY : all clean clean-build clean-pyc clean-test install test docs upload .PHONY : all clean clean-build clean-pyc clean-test clean-docs install test docs upload
# builds the module # builds the module
all : all :
@ -29,7 +29,7 @@ install : all
python ./setup.py install python ./setup.py install
## removes all build, test, coverage and Python artifacts ## removes all build, test, coverage and Python artifacts
clean : clean-test clean-build clean-pyc clean : clean-test clean-build clean-pyc clean-docs
## removes test and coverage artifacts ## removes test and coverage artifacts
clean-test : clean-test :
@ -47,6 +47,10 @@ clean-pyc :
find src test -name '*.pyc' -exec rm -f {} + find src test -name '*.pyc' -exec rm -f {} +
find src test -name '*.pyo' -exec rm -f {} + find src test -name '*.pyo' -exec rm -f {} +
## removes documentation file artifacts
clean-docs :
$(MAKE) -C docs clean
# runs unit tests # runs unit tests
check : test check : test
@ -54,7 +58,7 @@ test : clean-pyc
tox tox
docs : docs :
$(MAKE) -C docs singlehtml $(MAKE) -C docs html
# publishes module at pypi # publishes module at pypi
upload : test upload : test

View File

@ -6,12 +6,12 @@ resource-constrained environments primarily because of its small size, speed,
and portability. and portability.
Installation Installation
============ ------------
In order to use ``wolfssl Python``, you'll also need to install ``wolfssl C``. In order to use ``wolfssl Python``, you'll also need to install ``wolfssl C``.
Mac OSX Mac OSX
------- ~~~~~~~
Installing from ``homebrew`` and ``pip`` package managers: Installing from ``homebrew`` and ``pip`` package managers:
@ -41,7 +41,7 @@ Installing from ``source code``:
Linux Linux
----- ~~~~~
.. code-block:: shell .. code-block:: shell
@ -65,7 +65,7 @@ Linux
Testing Testing
======= -------
To run the tox tests in the source code, you'll need ``tox`` and a few other To run the tox tests in the source code, you'll need ``tox`` and a few other
requirements. The source code relies at **WOLFSSL_DIR/wrapper/python/wolfssl** requirements. The source code relies at **WOLFSSL_DIR/wrapper/python/wolfssl**

View File

@ -1,23 +1,21 @@
API API Documentation
=== =================
.. module:: wolfssl .. module:: wolfssl
wrap_socket
-----------
.. autofunction:: wrap_socket
SSL/TLS Context SSL/TLS Context
--------------- ---------------
SSLContext
~~~~~~~~~~
.. autoclass:: SSLContext .. autoclass:: SSLContext
:members: :members:
SSL/TLS Socket SSL/TLS Socket
-------------- --------------
SSLSocket
~~~~~~~~~
.. autoclass:: SSLSocket .. autoclass:: SSLSocket
:members: :members:

View File

@ -0,0 +1,95 @@
Client and Server Examples
==========================
SSL/TLS Client Example
----------------------
.. code-block:: python
import socket
import wolfssl
CA_DATA = \
"""
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
+OkuE6N36B9K
-----END CERTIFICATE-----
"""
bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
context = wolfssl.SSLContext(wolfssl.PROTOCOL_TLSv1_2)
context.verify_mode = wolfssl.CERT_REQUIRED
context.load_verify_locations(cadata=CA_DATA)
secure_socket = context.wrap_socket(bind_socket)
secure_socket.connect(("www.python.org", 443))
secure_socket.write(b"GET / HTTP/1.1\n\n")
print(secure_socket.read())
secure_socket.close()
SSL/TLS Server Example
----------------------
.. code-block:: python
import socket
import wolfssl
bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
bind_socket.bind(("", 4433))
bind_socket.listen(5)
context = wolfssl.SSLContext(wolfssl.PROTOCOL_TLSv1_2, server_side=True)
context.load_cert_chain("certs/server-cert.pem", "certs/server-key.pem")
while True:
try:
secure_socket = None
new_socket, from_addr = bind_socket.accept()
secure_socket = context.wrap_socket(new_socket)
print("Connection received from", from_addr)
print("\n", secure_socket.read(), "\n")
secure_socket.write(b"I hear you fa shizzle!")
except KeyboardInterrupt:
print()
break
finally:
if secure_socket:
secure_socket.close()
bind_socket.close()

View File

@ -1,15 +1,13 @@
.. include:: ../README.rst .. include:: ../README.rst
Summary Summary
------- =======
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 2
context usage
socket api
examples
.. automodule:: wolfssl
:members:
.. include:: ../LICENSING.rst .. include:: ../LICENSING.rst

View File

@ -1 +0,0 @@
.. include:: ../README.rst

View File

@ -1 +0,0 @@
.. include:: ../LICENSING.rst

View File

@ -1,8 +1,87 @@
Usage Basic Usage
===== ===========
SSL/TLS Client The SSL/TLS protocol works securing an underlying TCP connection, this module
-------------- adds the secure layer around the Python standard library
`socket <https://docs.python.org/3.6/library/socket.html>`_ module.
SSL/TLS Server There are three different paths to secure a socket in this module:
--------------
* Using the top level function wolfssl.wrap_socket();
* Using the method wrap_socket() from a SSLContext instance;
* Creating an SSLSocket object from the scratch.
Note 1:
It is possible to use the same SSLContext for multiple SSLSockets to save
time and resources.
Note 2:
Each path provides its own options for fine-tuning the securint parameters.
Check them out in the API documentation.
Using the top level function wolfssl.wrap_socket()
--------------------------------------------------
.. code-block:: python
>>> import socket
>>> import wolfssl
>>>
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
>>>
>>> secure_socket = wolfssl.wrap_socket(sock)
>>>
>>> secure_socket.connect(("www.python.org", 443))
>>>
>>> secure_socket.write(b"GET / HTTP/1.1\n\n")
>>>
>>> print(secure_socket.read())
b'HTTP/1.1 500 Domain Not Found\r\nServer: Varnish\r\nRetry-After: 0\r\ncontent-type: text/html\r\nCache-Control: private, no-cache\r\nconnection: keep-alive\r\nContent-Length: 179\r\nAccept-Ranges: bytes\r\nDate: Sun, 05 Feb 2017 21:26:48 GMT\r\nVia: 1.1 varnish\r\nConnection: keep-alive\r\n\r\n\n<html>\n<head>\n<title>Fastly error: unknown domain </title>\n</head>\n<body>\nFastly error: unknown domain: . Please check that this domain has been added to a service.</body></html>'
>>>
>>> secure_socket.close()
Using the method wrap_socket() from a SSLContext instance
---------------------------------------------------------
.. code-block:: python
>>> import socket
>>> import wolfssl
>>>
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
>>>
>>> context = wolfssl.SSLContext(wolfssl.PROTOCOL_TLSv1_2)
>>>
>>> secure_socket = context.wrap_socket(sock)
>>>
>>> secure_socket.connect(("www.python.org", 443))
>>>
>>> secure_socket.write(b"GET / HTTP/1.1\n\n")
>>>
>>> print(secure_socket.read())
b'HTTP/1.1 500 Domain Not Found\r\nServer: Varnish\r\nRetry-After: 0\r\ncontent-type: text/html\r\nCache-Control: private, no-cache\r\nconnection: keep-alive\r\nContent-Length: 179\r\nAccept-Ranges: bytes\r\nDate: Sun, 05 Feb 2017 21:26:48 GMT\r\nVia: 1.1 varnish\r\nConnection: keep-alive\r\n\r\n\n<html>\n<head>\n<title>Fastly error: unknown domain </title>\n</head>\n<body>\nFastly error: unknown domain: . Please check that this domain has been added to a service.</body></html>'
>>>
>>> secure_socket.close()
Creating an SSLSocket object from the scratch
---------------------------------------------
.. code-block:: python
>>> import socket
>>> import wolfssl
>>>
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
>>>
>>> secure_socket = wolfssl.SSLSocket(sock)
>>>
>>> secure_socket.connect(("www.python.org", 443))
>>>
>>> secure_socket.write(b"GET / HTTP/1.1\n\n")
>>>
>>> print(secure_socket.read())
b'HTTP/1.1 500 Domain Not Found\r\nServer: Varnish\r\nRetry-After: 0\r\ncontent-type: text/html\r\nCache-Control: private, no-cache\r\nconnection: keep-alive\r\nContent-Length: 179\r\nAccept-Ranges: bytes\r\nDate: Sun, 05 Feb 2017 21:26:48 GMT\r\nVia: 1.1 varnish\r\nConnection: keep-alive\r\n\r\n\n<html>\n<head>\n<title>Fastly error: unknown domain </title>\n</head>\n<body>\nFastly error: unknown domain: . Please check that this domain has been added to a service.</body></html>'
>>>
>>> secure_socket.close()

View File

@ -187,6 +187,8 @@ class SSLContext(object):
The keyfile string, if present, must point to a file containing the The keyfile string, if present, must point to a file containing the
private key in. private key in.
The password parameter is not supported yet.
""" """
if password is not None: if password is not None:
@ -453,7 +455,7 @@ class SSLSocket(socket):
raise ValueError("buffer not allowed in calls to " raise ValueError("buffer not allowed in calls to "
"read() on %s" % self.__class__) "read() on %s" % self.__class__)
data = t2b("\0" * length) data = _ffi.new('byte[%d]' % length)
length = _lib.wolfSSL_read(self.native_object, data, length) length = _lib.wolfSSL_read(self.native_object, data, length)
if length < 0: if length < 0:
@ -463,7 +465,7 @@ class SSLSocket(socket):
else: else:
raise SSLError("wolfSSL_read error (%d)" % err) raise SSLError("wolfSSL_read error (%d)" % err)
return data[:length] if length > 0 else b'' return _ffi.buffer(data, length)[:] if length > 0 else b''
def recv(self, length=1024, flags=0): def recv(self, length=1024, flags=0):
@ -602,19 +604,13 @@ def wrap_socket(sock, keyfile=None, certfile=None, server_side=False,
ciphers=None): ciphers=None):
""" """
Takes an instance sock of socket.socket, and returns an instance of Takes an instance sock of socket.socket, and returns an instance of
wolfssl.SSLSocket, a subtype of socket.socket, which wraps the underlying wolfssl.SSLSocket, wraping the underlying socket in an SSL context.
socket in an SSL context. sock must be a SOCK_STREAM socket; other socket
types are unsupported.
For client-side sockets, the context construction is lazy; if the underlying The sock parameter must be a SOCK_STREAM socket; other socket types are
socket isnt connected yet, the context construction will be performed after unsupported.
connect() is called on the socket. For server-side sockets, if the socket
has no remote peer, it is assumed to be a listening socket, and the
server-side SSL wrapping is automatically performed on client connections
accepted via the accept() method. wrap_socket() may raise SSLError.
The keyfile and certfile parameters specify optional files which contain a The keyfile and certfile parameters specify optional files whith proper
certificate to be used to identify the local side of the connection. key and the certificates used to identify the local side of the connection.
The parameter server_side is a boolean which identifies whether server-side The parameter server_side is a boolean which identifies whether server-side
or client-side behavior is desired from this socket. or client-side behavior is desired from this socket.
@ -622,9 +618,10 @@ def wrap_socket(sock, keyfile=None, certfile=None, server_side=False,
The parameter cert_reqs specifies whether a certificate is required from the The parameter cert_reqs specifies whether a certificate is required from the
other side of the connection, and whether it will be validated if provided. other side of the connection, and whether it will be validated if provided.
It must be one of the three values: It must be one of the three values:
CERT_NONE (certificates ignored)
CERT_OPTIONAL (not required, but validated if provided) * CERT_NONE (certificates ignored)
CERT_REQUIRED (required and validated) * CERT_OPTIONAL (not required, but validated if provided)
* CERT_REQUIRED (required and validated)
If the value of this parameter is not CERT_NONE, then the ca_certs parameter If the value of this parameter is not CERT_NONE, then the ca_certs parameter
must point to a file of CA certificates. must point to a file of CA certificates.
@ -642,12 +639,19 @@ def wrap_socket(sock, keyfile=None, certfile=None, server_side=False,
Heres a table showing which versions in a client (down the side) can Heres a table showing which versions in a client (down the side) can
connect to which versions in a server (along the top): connect to which versions in a server (along the top):
+------------------+-------+-----+-------+---------+---------+
| client \\ server | SSLv3 | TLS | TLSv1 | TLSv1.1 | TLSv1.2 | | client \\ server | SSLv3 | TLS | TLSv1 | TLSv1.1 | TLSv1.2 |
+------------------+-------+-----+-------+---------+---------+
| SSLv3 | yes | yes | no | no | no | | SSLv3 | yes | yes | no | no | no |
+------------------+-------+-----+-------+---------+---------+
| TLS (SSLv23) | yes | yes | yes | yes | yes | | TLS (SSLv23) | yes | yes | yes | yes | yes |
+------------------+-------+-----+-------+---------+---------+
| TLSv1 | no | yes | yes | no | no | | TLSv1 | no | yes | yes | no | no |
+------------------+-------+-----+-------+---------+---------+
| TLSv1.1 | no | yes | no | yes | no | | TLSv1.1 | no | yes | no | yes | no |
+------------------+-------+-----+-------+---------+---------+
| TLSv1.2 | no | yes | no | no | yes | | TLSv1.2 | no | yes | no | no | yes |
+------------------+-------+-----+-------+---------+---------+
Note: Note:
Which connections succeed will vary depending on the versions of the ssl Which connections succeed will vary depending on the versions of the ssl
@ -663,11 +667,7 @@ def wrap_socket(sock, keyfile=None, certfile=None, server_side=False,
gives the program control over the blocking behavior of the socket I/O gives the program control over the blocking behavior of the socket I/O
involved in the handshake. involved in the handshake.
The parameter suppress_ragged_eofs specifies how the SSLSocket.recv() method The parameter suppress_ragged_eofs is not supported yet.
should signal unexpected EOF from the other end of the connection. If
specified as True (the default), it returns a normal EOF (an empty bytes
object) in response to unexpected EOF errors raised from the underlying
socket; if False, it will raise the exceptions back to the caller.
""" """
return SSLSocket(sock=sock, keyfile=keyfile, certfile=certfile, return SSLSocket(sock=sock, keyfile=keyfile, certfile=certfile,
server_side=server_side, cert_reqs=cert_reqs, server_side=server_side, cert_reqs=cert_reqs,