summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2016-03-13 09:11:16 -0400
committerPaul Kehrer <paul.l.kehrer@gmail.com>2016-03-13 09:11:16 -0400
commit84c194aa64048880fba30152910947f8f4054902 (patch)
tree2fbf7eee1f84abc40e02526a727cab3d07049683
parent9c756eacc062c843d96256eb6dec6022a8a4c684 (diff)
parent8b7e455b8603248dccb115ee4cd381ebc6434f20 (diff)
downloadpyopenssl-84c194aa64048880fba30152910947f8f4054902.tar.gz
Merge pull request #440 from hynek/examples
Polish up examples (somewhat)
-rw-r--r--doc/index.rst2
-rw-r--r--examples/README48
-rw-r--r--examples/README.rst56
-rw-r--r--examples/SecureXMLRPCServer.py43
-rw-r--r--examples/certgen.py7
-rw-r--r--examples/mk_simple_certs.py48
-rw-r--r--examples/proxy.py11
-rw-r--r--examples/simple/client.py13
-rw-r--r--examples/simple/server.py34
-rw-r--r--examples/sni/client.py9
-rw-r--r--examples/sni/server.py11
-rw-r--r--tox.ini2
12 files changed, 182 insertions, 102 deletions
diff --git a/doc/index.rst b/doc/index.rst
index 56d84ea..d4c5e2e 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -20,6 +20,8 @@ Contents:
api
internals
+There are also `examples in the pyOpenSSL repository <https://github.com/pyca/pyopenssl/tree/master/examples>`_ that may help you getting started.
+
Meta
----
diff --git a/examples/README b/examples/README
deleted file mode 100644
index ecf95e5..0000000
--- a/examples/README
+++ /dev/null
@@ -1,48 +0,0 @@
-I've finally gotten around to writing some examples :-)
-
-They aren't many, but at least it's something. If you write any, feel free to
-send them to me and I will add themn.
-
-
-certgen.py - Certificate generation module
-==========================================
-
-Example module with three functions:
- createKeyPair - Create a public/private key pair
- createCertRequest - Create a certificate request
- createCertificate - Create a certificate given a cert request
-In fact, I created the certificates and keys in the 'simple' directory with
-the script mk_simple_certs.py
-
-
-simple - Simple client/server example
-=====================================
-
-Start the server with
- python server.py PORT
-and start clients with
- python client.py HOST PORT
-
-The server is a simple echo server, anything a client sends, it sends back.
-
-
-proxy.py - Example of an SSL-enabled proxy
-==========================================
-
-The proxy example demonstrate how to use set_connect_state to start
-talking SSL over an already connected socket.
-
-Usage: python proxy.py server[:port] proxy[:port]
-
-Contributed by Mihai Ibanescu
-
-
-SecureXMLRPCServer.py - SSL-enabled version of SimpleXMLRPCServer
-=================================================================
-
-This acts exactly like SimpleXMLRPCServer from the standard python library,
-but uses secure connections. The technique and classes should work for any
-SocketServer style server. However, the code has not been extensively tested.
-
-Contributed by Michal Wallace
-
diff --git a/examples/README.rst b/examples/README.rst
new file mode 100644
index 0000000..1e9116b
--- /dev/null
+++ b/examples/README.rst
@@ -0,0 +1,56 @@
+========
+Examples
+========
+
+
+certgen.py -- Certificate generation module
+===========================================
+
+Example module with three functions:
+
+createKeyPair
+ Create a public/private key pair.
+
+createCertRequest
+ Create a certificate request.
+
+createCertificate
+ Create a certificate given a cert request.
+
+In fact, I created the certificates and keys in the 'simple' directory with the script ``mk_simple_certs.py``.
+
+
+simple -- Simple client/server example
+======================================
+
+Start the server with::
+
+ python server.py PORT
+
+and start clients with::
+
+ python client.py HOST PORT
+
+The server is a simple echo server, anything a client sends, it sends back.
+
+
+proxy.py -- Example of an SSL-enabled proxy
+===========================================
+
+The proxy example demonstrate how to use set_connect_state to start talking SSL over an already connected socket.
+
+Usage::
+
+ python proxy.py server[:port] proxy[:port]
+
+Contributed by Mihai Ibanescu
+
+
+SecureXMLRPCServer.py -- SSL-enabled version of SimpleXMLRPCServer
+==================================================================
+
+Acts exactly like `SimpleXMLRPCServer <https://docs.python.org/3/library/xmlrpc.server.html>`_ from the Python standard library, but uses secure connections.
+The technique and classes should work for any SocketServer style server.
+However, the code has not been extensively tested.
+
+Contributed by Michal Wallace
diff --git a/examples/SecureXMLRPCServer.py b/examples/SecureXMLRPCServer.py
index 757b49c..56bfaea 100644
--- a/examples/SecureXMLRPCServer.py
+++ b/examples/SecureXMLRPCServer.py
@@ -14,11 +14,15 @@ been extensively tested.
This code is in the public domain.
It is provided AS-IS WITH NO WARRANTY WHATSOEVER.
"""
-import SocketServer
-import os, socket
+
import SimpleXMLRPCServer
+import SocketServer
+import os
+import socket
+
from OpenSSL import SSL
+
class SSLWrapper:
"""
This whole class exists just to filter out a parameter
@@ -30,10 +34,13 @@ class SSLWrapper:
so I'm making a proxy instead of subclassing.
"""
self.__dict__["conn"] = conn
- def __getattr__(self,name):
+
+ def __getattr__(self, name):
return getattr(self.__dict__["conn"], name)
- def __setattr__(self,name, value):
+
+ def __setattr__(self, name, value):
setattr(self.__dict__["conn"], name, value)
+
def shutdown(self, how=1):
"""
SimpleXMLRpcServer.doPOST calls shutdown(1),
@@ -41,6 +48,7 @@ class SSLWrapper:
an argument. So we just discard the argument.
"""
self.__dict__["conn"].shutdown()
+
def accept(self):
"""
This is the other part of the shutdown() workaround.
@@ -51,42 +59,48 @@ class SSLWrapper:
return (SSLWrapper(c), a)
-
class SecureTCPServer(SocketServer.TCPServer):
"""
Just like TCPServer, but use a socket.
This really ought to let you specify the key and certificate files.
"""
def __init__(self, server_address, RequestHandlerClass):
- SocketServer.BaseServer.__init__(self, server_address, RequestHandlerClass)
+ SocketServer.BaseServer.__init__(
+ self, server_address, RequestHandlerClass
+ )
- ## Same as normal, but make it secure:
+ # Same as normal, but make it secure:
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.set_options(SSL.OP_NO_SSLv2)
dir = os.curdir
- ctx.use_privatekey_file (os.path.join(dir, 'server.pkey'))
+ ctx.use_privatekey_file(os.path.join(dir, 'server.pkey'))
ctx.use_certificate_file(os.path.join(dir, 'server.cert'))
- self.socket = SSLWrapper(SSL.Connection(ctx, socket.socket(self.address_family,
- self.socket_type)))
+ self.socket = SSLWrapper(
+ SSL.Connection(
+ ctx, socket.socket(self.address_family, self.socket_type)
+ )
+ )
self.server_bind()
self.server_activate()
-class SecureXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
+class SecureXMLRPCRequestHandler(
+ SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
def setup(self):
"""
We need to use socket._fileobject Because SSL.Connection
doesn't have a 'dup'. Not exactly sure WHY this is, but
this is backed up by comments in socket.py and SSL/connection.c
"""
- self.connection = self.request # for doPOST
+ self.connection = self.request # for doPOST
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
-
-class SecureXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer, SecureTCPServer):
+
+class SecureXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer,
+ SecureTCPServer):
def __init__(self, addr,
requestHandler=SecureXMLRPCRequestHandler,
logRequests=1):
@@ -99,4 +113,3 @@ class SecureXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer, SecureTCPServer)
self.logRequests = logRequests
self.instance = None
SecureTCPServer.__init__(self, addr, requestHandler)
-
diff --git a/examples/certgen.py b/examples/certgen.py
index da0624f..7b70e98 100644
--- a/examples/certgen.py
+++ b/examples/certgen.py
@@ -13,6 +13,7 @@ from OpenSSL import crypto
TYPE_RSA = crypto.TYPE_RSA
TYPE_DSA = crypto.TYPE_DSA
+
def createKeyPair(type, bits):
"""
Create a public/private key pair.
@@ -25,6 +26,7 @@ def createKeyPair(type, bits):
pkey.generate_key(type, bits)
return pkey
+
def createCertRequest(pkey, digest="sha256", **name):
"""
Create a certificate request.
@@ -52,7 +54,9 @@ def createCertRequest(pkey, digest="sha256", **name):
req.sign(pkey, digest)
return req
-def createCertificate(req, issuerCertKey, serial, validityPeriod, digest="sha256"):
+
+def createCertificate(req, issuerCertKey, serial, validityPeriod,
+ digest="sha256"):
"""
Generate a certificate given a certificate request.
@@ -78,4 +82,3 @@ def createCertificate(req, issuerCertKey, serial, validityPeriod, digest="sha256
cert.set_pubkey(req.get_pubkey())
cert.sign(issuerKey, digest)
return cert
-
diff --git a/examples/mk_simple_certs.py b/examples/mk_simple_certs.py
index 7129f13..f0416cd 100644
--- a/examples/mk_simple_certs.py
+++ b/examples/mk_simple_certs.py
@@ -2,27 +2,49 @@
Create certificates and private keys for the 'simple' example.
"""
+from __future__ import print_function
+
from OpenSSL import crypto
-from certgen import * # yes yes, I know, I'm lazy
-cakey = createKeyPair(TYPE_RSA, 2048)
+from certgen import (
+ createKeyPair,
+ createCertRequest,
+ createCertificate,
+)
+
+cakey = createKeyPair(crypto.TYPE_RSA, 2048)
careq = createCertRequest(cakey, CN='Certificate Authority')
-cacert = createCertificate(careq, (careq, cakey), 0, (0, 60*60*24*365*5)) # five years
+# CA certificate is valid for five years.
+cacert = createCertificate(careq, (careq, cakey), 0, (0, 60*60*24*365*5))
print('Creating Certificate Authority private key in "simple/CA.pkey"')
with open('simple/CA.pkey', 'w') as capkey:
- capkey.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, cakey).decode('utf-8'))
+ capkey.write(
+ crypto.dump_privatekey(crypto.FILETYPE_PEM, cakey).decode('utf-8')
+ )
+
print('Creating Certificate Authority certificate in "simple/CA.cert"')
with open('simple/CA.cert', 'w') as ca:
- ca.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cacert).decode('utf-8'))
+ ca.write(
+ crypto.dump_certificate(crypto.FILETYPE_PEM, cacert).decode('utf-8')
+ )
-for (fname, cname) in [('client', 'Simple Client'), ('server', 'Simple Server')]:
- pkey = createKeyPair(TYPE_RSA, 2048)
+for (fname, cname) in [('client', 'Simple Client'),
+ ('server', 'Simple Server')]:
+ pkey = createKeyPair(crypto.TYPE_RSA, 2048)
req = createCertRequest(pkey, CN=cname)
- cert = createCertificate(req, (cacert, cakey), 1, (0, 60*60*24*365*5)) # five years
- print('Creating Certificate %s private key in "simple/%s.pkey"' % (fname, fname))
+ # Certificates are valid for five years.
+ cert = createCertificate(req, (cacert, cakey), 1, (0, 60*60*24*365*5))
+
+ print('Creating Certificate %s private key in "simple/%s.pkey"'
+ % (fname, fname))
with open('simple/%s.pkey' % (fname,), 'w') as leafpkey:
- leafpkey.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey).decode('utf-8'))
- print('Creating Certificate %s certificate in "simple/%s.cert"' % (fname, fname))
- with open('simple/%s.cert' % (fname,), 'w') as leafcert:
- leafcert.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode('utf-8'))
+ leafpkey.write(
+ crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey).decode('utf-8')
+ )
+ print('Creating Certificate %s certificate in "simple/%s.cert"'
+ % (fname, fname))
+ with open('simple/%s.cert' % (fname,), 'w') as leafcert:
+ leafcert.write(
+ crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode('utf-8')
+ )
diff --git a/examples/proxy.py b/examples/proxy.py
index b1c4253..3be26f9 100644
--- a/examples/proxy.py
+++ b/examples/proxy.py
@@ -8,15 +8,20 @@
#
# $Id: proxy.py,v 1.2 2004/07/22 12:01:25 martin Exp $
-import sys, socket, string
+import sys
+import socket
+import string
+
from OpenSSL import SSL
+
def usage(exit_code=0):
print "Usage: %s server[:port] proxy[:port]" % sys.argv[0]
print " Connects SSL to the specified server (port 443 by default)"
print " using the specified proxy (port 8080 by default)"
sys.exit(exit_code)
+
def main():
# Command-line processing
if len(sys.argv) != 3:
@@ -26,12 +31,13 @@ def main():
run(split_host(server, 443), split_host(proxy, 8080))
+
def split_host(hostname, default_port=80):
a = string.split(hostname, ':', 1)
if len(a) == 1:
a.append(default_port)
return a[0], int(a[1])
-
+
# Connects to the server, through the proxy
def run(server, proxy):
@@ -66,5 +72,6 @@ def run(server, proxy):
print buff,
+
if __name__ == '__main__':
main()
diff --git a/examples/simple/client.py b/examples/simple/client.py
index dff2d03..5662122 100644
--- a/examples/simple/client.py
+++ b/examples/simple/client.py
@@ -8,8 +8,12 @@
Simple SSL client, using blocking I/O
"""
+import os
+import socket
+import sys
+
from OpenSSL import SSL, crypto
-import sys, os, select, socket
+
def verify_cb(conn, cert, errnum, depth, ok):
certsubject = crypto.X509Name(cert.get_subject())
@@ -17,20 +21,23 @@ def verify_cb(conn, cert, errnum, depth, ok):
print('Got certificate: ' + commonname)
return ok
+
if len(sys.argv) < 3:
print('Usage: python client.py HOST PORT')
sys.exit(1)
+
dir = os.path.dirname(sys.argv[0])
if dir == '':
dir = os.curdir
+
# Initialize context
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.set_options(SSL.OP_NO_SSLv2)
ctx.set_options(SSL.OP_NO_SSLv3)
-ctx.set_verify(SSL.VERIFY_PEER, verify_cb) # Demand a certificate
-ctx.use_privatekey_file (os.path.join(dir, 'client.pkey'))
+ctx.set_verify(SSL.VERIFY_PEER, verify_cb) # Demand a certificate
+ctx.use_privatekey_file(os.path.join(dir, 'client.pkey'))
ctx.use_certificate_file(os.path.join(dir, 'client.cert'))
ctx.load_verify_locations(os.path.join(dir, 'CA.cert'))
diff --git a/examples/simple/server.py b/examples/simple/server.py
index bc001ed..19f6d21 100644
--- a/examples/simple/server.py
+++ b/examples/simple/server.py
@@ -8,16 +8,23 @@
Simple echo server, using nonblocking I/O
"""
+from __future__ import print_function
+
+import os
+import select
+import socket
+import sys
+
from OpenSSL import SSL, crypto
-import sys, os, select, socket
def verify_cb(conn, cert, errnum, depth, ok):
certsubject = crypto.X509Name(cert.get_subject())
commonname = certsubject.commonName
- print(('Got certificate: ' + commonname))
+ print('Got certificate: ' + commonname)
return ok
+
if len(sys.argv) < 2:
print('Usage: python server.py PORT')
sys.exit(1)
@@ -30,20 +37,23 @@ if dir == '':
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.set_options(SSL.OP_NO_SSLv2)
ctx.set_options(SSL.OP_NO_SSLv3)
-ctx.set_verify(SSL.VERIFY_PEER|SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb) # Demand a certificate
-ctx.use_privatekey_file (os.path.join(dir, 'server.pkey'))
+ctx.set_verify(
+ SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb
+) # Demand a certificate
+ctx.use_privatekey_file(os.path.join(dir, 'server.pkey'))
ctx.use_certificate_file(os.path.join(dir, 'server.cert'))
ctx.load_verify_locations(os.path.join(dir, 'CA.cert'))
# Set up server
server = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
server.bind(('', int(sys.argv[1])))
-server.listen(3)
+server.listen(3)
server.setblocking(0)
clients = {}
writers = {}
+
def dropClient(cli, errors=None):
if errors:
print('Client %s left unexpectedly:' % (clients[cli],))
@@ -59,20 +69,24 @@ def dropClient(cli, errors=None):
while 1:
try:
- r, w, _ = select.select([server] + list(clients.keys()), list(writers.keys()), [])
+ r, w, _ = select.select(
+ [server] + list(clients.keys()), list(writers.keys()), []
+ )
except:
break
for cli in r:
if cli == server:
- cli,addr = server.accept()
+ cli, addr = server.accept()
print('Connection from %s' % (addr,))
clients[cli] = addr
else:
try:
ret = cli.recv(1024).decode('utf-8')
- except (SSL.WantReadError, SSL.WantWriteError, SSL.WantX509LookupError):
+ except (SSL.WantReadError,
+ SSL.WantWriteError,
+ SSL.WantX509LookupError):
pass
except SSL.ZeroReturnError:
dropClient(cli)
@@ -86,7 +100,9 @@ while 1:
for cli in w:
try:
ret = cli.send(writers[cli])
- except (SSL.WantReadError, SSL.WantWriteError, SSL.WantX509LookupError):
+ except (SSL.WantReadError,
+ SSL.WantWriteError,
+ SSL.WantX509LookupError):
pass
except SSL.ZeroReturnError:
dropClient(cli)
diff --git a/examples/sni/client.py b/examples/sni/client.py
index 5b93671..428525b 100644
--- a/examples/sni/client.py
+++ b/examples/sni/client.py
@@ -1,15 +1,12 @@
# Copyright (C) Jean-Paul Calderone
# See LICENSE for details.
-if __name__ == '__main__':
- import client
- raise SystemExit(client.main())
-
from sys import argv, stdout
from socket import socket
from OpenSSL.SSL import TLSv1_METHOD, Context, Connection
+
def main():
"""
Connect to an SNI-enabled server and request a specific hostname, specified
@@ -33,3 +30,7 @@ def main():
print 'Server subject is', client_ssl.get_peer_certificate().get_subject()
client_ssl.close()
+
+if __name__ == '__main__':
+ import client
+ raise SystemExit(client.main())
diff --git a/examples/sni/server.py b/examples/sni/server.py
index 8738416..e0c159a 100644
--- a/examples/sni/server.py
+++ b/examples/sni/server.py
@@ -1,16 +1,13 @@
# Copyright (C) Jean-Paul Calderone
# See LICENSE for details.
-if __name__ == '__main__':
- import server
- raise SystemExit(server.main())
-
from sys import stdout
from socket import SOL_SOCKET, SO_REUSEADDR, socket
from OpenSSL.crypto import FILETYPE_PEM, load_privatekey, load_certificate
from OpenSSL.SSL import TLSv1_METHOD, Context, Connection
+
def load(domain):
crt = open(domain + ".crt")
key = open(domain + ".key")
@@ -49,7 +46,7 @@ def main():
certificates = {
"example.invalid": load("example.invalid"),
"another.invalid": load("another.invalid"),
- }
+}
def pick_certificate(connection):
@@ -62,3 +59,7 @@ def pick_certificate(connection):
new_context.use_privatekey(key)
new_context.use_certificate(cert)
connection.set_context(new_context)
+
+
+if __name__ == '__main__':
+ raise SystemExit(main())
diff --git a/tox.ini b/tox.ini
index 2d41636..a76d1a3 100644
--- a/tox.ini
+++ b/tox.ini
@@ -38,7 +38,7 @@ deps =
flake8
skip_install = true
commands =
- flake8 src tests setup.py
+ flake8 src tests examples setup.py
[testenv:pypi-readme]
deps =