From 897bc2556fed43b76f6d1b14470c3e806df15af8 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Mon, 18 Feb 2008 20:50:23 -0500 Subject: initial source import --- examples/README | 48 +++++++++++++++++++ examples/SecureXMLRPCServer.py | 102 +++++++++++++++++++++++++++++++++++++++++ examples/certgen.py | 80 ++++++++++++++++++++++++++++++++ examples/mk_simple_certs.py | 17 +++++++ examples/proxy.py | 70 ++++++++++++++++++++++++++++ examples/simple/CA.cert | 12 +++++ examples/simple/CA.pkey | 15 ++++++ examples/simple/client.cert | 11 +++++ examples/simple/client.pkey | 15 ++++++ examples/simple/client.py | 53 +++++++++++++++++++++ examples/simple/server.cert | 11 +++++ examples/simple/server.pkey | 15 ++++++ examples/simple/server.py | 101 ++++++++++++++++++++++++++++++++++++++++ 13 files changed, 550 insertions(+) create mode 100644 examples/README create mode 100644 examples/SecureXMLRPCServer.py create mode 100644 examples/certgen.py create mode 100644 examples/mk_simple_certs.py create mode 100644 examples/proxy.py create mode 100644 examples/simple/CA.cert create mode 100644 examples/simple/CA.pkey create mode 100644 examples/simple/client.cert create mode 100644 examples/simple/client.pkey create mode 100644 examples/simple/client.py create mode 100644 examples/simple/server.cert create mode 100644 examples/simple/server.pkey create mode 100644 examples/simple/server.py (limited to 'examples') diff --git a/examples/README b/examples/README new file mode 100644 index 0000000..ecf95e5 --- /dev/null +++ b/examples/README @@ -0,0 +1,48 @@ +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/SecureXMLRPCServer.py b/examples/SecureXMLRPCServer.py new file mode 100644 index 0000000..757b49c --- /dev/null +++ b/examples/SecureXMLRPCServer.py @@ -0,0 +1,102 @@ +""" +SecureXMLRPCServer module using pyOpenSSL 0.5 +Written 0907.2002 +by Michal Wallace +http://www.sabren.net/ + +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. + +This code is in the public domain. +It is provided AS-IS WITH NO WARRANTY WHATSOEVER. +""" +import SocketServer +import os, socket +import SimpleXMLRPCServer +from OpenSSL import SSL + +class SSLWrapper: + """ + This whole class exists just to filter out a parameter + passed in to the shutdown() method in SimpleXMLRPC.doPOST() + """ + def __init__(self, conn): + """ + Connection is not yet a new-style class, + so I'm making a proxy instead of subclassing. + """ + self.__dict__["conn"] = conn + def __getattr__(self,name): + return getattr(self.__dict__["conn"], name) + def __setattr__(self,name, value): + setattr(self.__dict__["conn"], name, value) + def shutdown(self, how=1): + """ + SimpleXMLRpcServer.doPOST calls shutdown(1), + and Connection.shutdown() doesn't take + an argument. So we just discard the argument. + """ + self.__dict__["conn"].shutdown() + def accept(self): + """ + This is the other part of the shutdown() workaround. + Since servers create new sockets, we have to infect + them with our magic. :) + """ + c, a = self.__dict__["conn"].accept() + 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) + + ## 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_certificate_file(os.path.join(dir, 'server.cert')) + + self.socket = SSLWrapper(SSL.Connection(ctx, socket.socket(self.address_family, + self.socket_type))) + self.server_bind() + self.server_activate() + + +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.rfile = socket._fileobject(self.request, "rb", self.rbufsize) + self.wfile = socket._fileobject(self.request, "wb", self.wbufsize) + + +class SecureXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer, SecureTCPServer): + def __init__(self, addr, + requestHandler=SecureXMLRPCRequestHandler, + logRequests=1): + """ + This is the exact same code as SimpleXMLRPCServer.__init__ + except it calls SecureTCPServer.__init__ instead of plain + old TCPServer.__init__ + """ + self.funcs = {} + self.logRequests = logRequests + self.instance = None + SecureTCPServer.__init__(self, addr, requestHandler) + diff --git a/examples/certgen.py b/examples/certgen.py new file mode 100644 index 0000000..e37d0c7 --- /dev/null +++ b/examples/certgen.py @@ -0,0 +1,80 @@ +# +# certgen.py +# +# Copyright (C) Martin Sjögren and AB Strakt 2001, All rights reserved +# +# $Id: certgen.py,v 1.2 2004/07/22 12:01:25 martin Exp $ +# +""" +Certificate generation module. +""" + +from OpenSSL import crypto + +TYPE_RSA = crypto.TYPE_RSA +TYPE_DSA = crypto.TYPE_DSA + +def createKeyPair(type, bits): + """ + Create a public/private key pair. + + Arguments: type - Key type, must be one of TYPE_RSA and TYPE_DSA + bits - Number of bits to use in the key + Returns: The public/private key pair in a PKey object + """ + pkey = crypto.PKey() + pkey.generate_key(type, bits) + return pkey + +def createCertRequest(pkey, digest="md5", **name): + """ + Create a certificate request. + + Arguments: pkey - The key to associate with the request + digest - Digestion method to use for signing, default is md5 + **name - The name of the subject of the request, possible + arguments are: + C - Country name + ST - State or province name + L - Locality name + O - Organization name + OU - Organizational unit name + CN - Common name + emailAddress - E-mail address + Returns: The certificate request in an X509Req object + """ + req = crypto.X509Req() + subj = req.get_subject() + + for (key,value) in name.items(): + setattr(subj, key, value) + + req.set_pubkey(pkey) + req.sign(pkey, digest) + return req + +def createCertificate(req, (issuerCert, issuerKey), serial, (notBefore, notAfter), digest="md5"): + """ + Generate a certificate given a certificate request. + + Arguments: req - Certificate reqeust to use + issuerCert - The certificate of the issuer + issuerKey - The private key of the issuer + serial - Serial number for the certificate + notBefore - Timestamp (relative to now) when the certificate + starts being valid + notAfter - Timestamp (relative to now) when the certificate + stops being valid + digest - Digest method to use for signing, default is md5 + Returns: The signed certificate in an X509 object + """ + cert = crypto.X509() + cert.set_serial_number(serial) + cert.gmtime_adj_notBefore(notBefore) + cert.gmtime_adj_notAfter(notAfter) + cert.set_issuer(issuerCert.get_subject()) + cert.set_subject(req.get_subject()) + 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 new file mode 100644 index 0000000..9dfdd2e --- /dev/null +++ b/examples/mk_simple_certs.py @@ -0,0 +1,17 @@ +""" +Create certificates and private keys for the 'simple' example. +""" + +from OpenSSL import crypto +from certgen import * # yes yes, I know, I'm lazy +cakey = createKeyPair(TYPE_RSA, 1024) +careq = createCertRequest(cakey, CN='Certificate Authority') +cacert = createCertificate(careq, (careq, cakey), 0, (0, 60*60*24*365*5)) # five years +open('simple/CA.pkey', 'w').write(crypto.dump_privatekey(crypto.FILETYPE_PEM, cakey)) +open('simple/CA.cert', 'w').write(crypto.dump_certificate(crypto.FILETYPE_PEM, cacert)) +for (fname, cname) in [('client', 'Simple Client'), ('server', 'Simple Server')]: + pkey = createKeyPair(TYPE_RSA, 1024) + req = createCertRequest(pkey, CN=cname) + cert = createCertificate(req, (cacert, cakey), 1, (0, 60*60*24*365*5)) # five years + open('simple/%s.pkey' % (fname,), 'w').write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey)) + open('simple/%s.cert' % (fname,), 'w').write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) diff --git a/examples/proxy.py b/examples/proxy.py new file mode 100644 index 0000000..b094864 --- /dev/null +++ b/examples/proxy.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# +# This script demostrates how one can use pyOpenSSL to speak SSL over an HTTP +# proxy +# The challenge here is to start talking SSL over an already connected socket +# +# Author: Mihai Ibanescu +# +# $Id: proxy.py,v 1.2 2004/07/22 12:01:25 martin Exp $ + +import sys, socket, 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: + usage(-1) + + server, proxy = sys.argv[1:3] + + 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): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + s.connect(proxy) + except socket.error, e: + print "Unable to connect to %s:%s %s" % (proxy[0], proxy[1], str(e)) + sys.exit(-1) + + # Use the CONNECT method to get a connection to the actual server + s.send("CONNECT %s:%s HTTP/1.0\n\n" % (server[0], server[1])) + print "Proxy response: %s" % string.strip(s.recv(1024)) + + ctx = SSL.Context(SSL.SSLv23_METHOD) + conn = SSL.Connection(ctx, s) + + # Go to client mode + conn.set_connect_state() + + # start using HTTP + + conn.send("HEAD / HTTP/1.0\n\n") + print "Sever response:" + print "-" * 40 + while 1: + try: + buff = conn.recv(4096) + except SSL.ZeroReturnError: + # we're done + break + + print buff, + +if __name__ == '__main__': + main() diff --git a/examples/simple/CA.cert b/examples/simple/CA.cert new file mode 100644 index 0000000..1e6162d --- /dev/null +++ b/examples/simple/CA.cert @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBrzCCARgCAQAwDQYJKoZIhvcNAQEEBQAwIDEeMBwGA1UEAxMVQ2VydGlmaWNh +dGUgQXV0aG9yaXR5MB4XDTAyMDgxNTEyMjQzN1oXDTA3MDgxNDEyMjQzN1owIDEe +MBwGA1UEAxMVQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQC9PNfAFlRkjw4SPLm8VV4/UFVkFJRKzpFgyi0UxN1W5HqSxMtH +ivYPiUhhtfdGlLlzcMTeE+bcDxYjdrKh1bH3OmJN60fdpCiu2YMGucrNbLvuD8+f +E1uoqYhheKTW0p2V+MkGMb/cbTmKk1rHr5dWHVXOrXTus/U8fmt/1wckNwIDAQAB +MA0GCSqGSIb3DQEBBAUAA4GBAFt0RHXJbFPWHVnx9/vyCQlI3VluEBJquUlJFsqd +VctFvzQyPypYRXYqxjD8JTxO0DmDyvlPNEu4nv6RVyca8FKDF0x8ro5G/hkCkVrN +6AvC1ZIccHb3LzlfSv8bNB0iPkQPvnH4ZxDE+KJcOe80S7ttSRdDnjxm4NZFmUsI +NtBS +-----END CERTIFICATE----- diff --git a/examples/simple/CA.pkey b/examples/simple/CA.pkey new file mode 100644 index 0000000..6747a99 --- /dev/null +++ b/examples/simple/CA.pkey @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQC9PNfAFlRkjw4SPLm8VV4/UFVkFJRKzpFgyi0UxN1W5HqSxMtH +ivYPiUhhtfdGlLlzcMTeE+bcDxYjdrKh1bH3OmJN60fdpCiu2YMGucrNbLvuD8+f +E1uoqYhheKTW0p2V+MkGMb/cbTmKk1rHr5dWHVXOrXTus/U8fmt/1wckNwIDAQAB +AoGBAIwZ54GHBqQMZVaLLteIPGaTiyS1N7TKikcmZ4ng1h3mufi/SeCFuPZ3pOby +WUggA8y7yITCJ0D0ymcnEclO9JnUP8XF8q7YBNVjjSQKr7xa4k+R1yzkqOwLnGFI +X5OWQpHnGDzVZX14CGQMk8p1jIl6jz9LrNJ/spB4VrTkB9+BAkEA+jt3CjU3x4Dl +DOxDfwNjwq2mw43SdyF03vdobLHvQhxoLbuglmSSe3V9mteD3h9NwgosK7QkApwr +gJ2EHAWJvwJBAMGZeCxfO5B9ghVYNd8JupDdIkIiJh28wJPx8bgoncBsB/b7JEd5 +aUbfCwuMzy/FHLTRWCkiQ02qMSPBVcp404kCQGRw7g1Y4zTfVhFj3IvlDmwcS+3+ +xVYwRbshz/ahTYpZ4K9KuuDjKbEIrgwzKalFI28ZqjU4r6OkkAmmMFsXFf0CQHVO +JnDMa20Lf2yrfEjevjrUotNrmajfG9kI+qvZgGx9iP3wAnWEbXPR5gFjmo6ZYuF1 +D3QtHJbMjuXZWcBLIfECQQDP6ywjwMAAB2285GwyI8Aqvo9U05QtGby6O/UQ2XoM +XsrjM42qlPI+S+s72o47wkRhRayhnE5MJMpKJGgbTN8f +-----END RSA PRIVATE KEY----- diff --git a/examples/simple/client.cert b/examples/simple/client.cert new file mode 100644 index 0000000..97ee35e --- /dev/null +++ b/examples/simple/client.cert @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBpzCCARACAQEwDQYJKoZIhvcNAQEEBQAwIDEeMBwGA1UEAxMVQ2VydGlmaWNh +dGUgQXV0aG9yaXR5MB4XDTAyMDgxNTEyMjQzN1oXDTA3MDgxNDEyMjQzN1owGDEW +MBQGA1UEAxMNU2ltcGxlIENsaWVudDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC +gYEAynARaDhd5I/BhLGlcqOqOoEsOEF4KH9+5SfwQX1zBaaI8bVTq8GB1/J5UFXt +3ugLAb4QHtUVBrks9wi+IGENS1IeUgZZMsETQqXgzdK3SXt7IPnggo4GUl3dWIJG +UYsOjea37ejV1TbtD5MrEWNSF4F9OP1H8oWUFJOFR/7sdHECAwEAATANBgkqhkiG +9w0BAQQFAAOBgQAzvsH7fD0GKKZo2uL/5gBc/ZE1hSx/KfRIZ78CZGsgHI8oi3Y+ +Km91PX2H4xx/2dv/ZaAPslDjvvyVTl6KQoN+HMmhcjY8XAs1lVqckcNbhVEw2kgc +Admy5yPZmuIC0nTC1jzZo1dDD4PNrFcRho6fHDk2aaxpS+DnzAO2/cTCTg== +-----END CERTIFICATE----- diff --git a/examples/simple/client.pkey b/examples/simple/client.pkey new file mode 100644 index 0000000..a4ffec1 --- /dev/null +++ b/examples/simple/client.pkey @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDKcBFoOF3kj8GEsaVyo6o6gSw4QXgof37lJ/BBfXMFpojxtVOr +wYHX8nlQVe3e6AsBvhAe1RUGuSz3CL4gYQ1LUh5SBlkywRNCpeDN0rdJe3sg+eCC +jgZSXd1YgkZRiw6N5rft6NXVNu0PkysRY1IXgX04/UfyhZQUk4VH/ux0cQIDAQAB +AoGBAIwv314U6rCE/LYvbytcO14YZc7vR46D/BQk/DPd8/FNyjfYIgEnGAu7VldT +qk5a0oR6Yh933/+v7HuGCmPR0anCdBX+0fuZakMetvM1PN0Nvv8PqEXfILW/ikT6 +rCcFWXff4og41HVmLcap6wo4KeCGLyXEynZWCXNRnedGnHQhAkEA+1tOa03oc9HJ +RbBC87teSLCVVa8CiXWhpttXAbBPBRpzrBCdIiv9cpVQ1iRRbmKUgPRNX1MQI5Lw +6mzQNkRPnwJBAM4tazLZJD3KIqNTUuQgxhcPmzerQ5jylhbPcHB4N5U/nS1feWpm +QQf4AWQp4TJUOqoqW+nbdfEwyOUPqc2Zge8CQQDupnJ+Tyo1TSnckM4AvBV4zq/6 ++n9eI+GnmvmxEMT2A3dwFxYaK8on0L0/lJv8QnzdMxeDOkpIfGthKI9H9vPhAkAJ +8CiFp+/WRqMKyl5pfqbtv6PUuB2nBrJzYQZjdXgAarOR11NL7Kff0XWHtXkUavj0 +8NvDVv/FY3ubhvjBX0/jAkEAtjbwbIcRVjMQ9FuZk6SdJBSMfsX7iTDhgA7Hgn3U +YsHo3E094lIi/66gnApVUOqr+brdglP6uAG2qP+ZgqWPiw== +-----END RSA PRIVATE KEY----- diff --git a/examples/simple/client.py b/examples/simple/client.py new file mode 100644 index 0000000..6358b20 --- /dev/null +++ b/examples/simple/client.py @@ -0,0 +1,53 @@ +# +# client.py +# +# Copyright (C) 2001 Martin Sjögren and AB Strakt, All rights reserved +# +# $Id: client.py,v 1.7 2002/08/15 12:20:46 martin Exp $ +# +""" +Simple SSL client, using blocking I/O +""" + +from OpenSSL import SSL +import sys, os, select, socket + +def verify_cb(conn, cert, errnum, depth, ok): + # This obviously has to be updated + print 'Got certificate: %s' % cert.get_subject() + return ok + +if len(sys.argv) < 3: + print 'Usage: python[2] 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_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')) + +# Set up client +sock = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM)) +sock.connect((sys.argv[1], int(sys.argv[2]))) + +while 1: + line = sys.stdin.readline() + if line == '': + break + try: + sock.send(line) + sys.stdout.write(sock.recv(1024)) + sys.stdout.flush() + except SSL.Error: + print 'Connection died unexpectedly' + break + + +sock.shutdown() +sock.close() diff --git a/examples/simple/server.cert b/examples/simple/server.cert new file mode 100644 index 0000000..adc84e8 --- /dev/null +++ b/examples/simple/server.cert @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBpzCCARACAQEwDQYJKoZIhvcNAQEEBQAwIDEeMBwGA1UEAxMVQ2VydGlmaWNh +dGUgQXV0aG9yaXR5MB4XDTAyMDgxNTEyMjQzOFoXDTA3MDgxNDEyMjQzOFowGDEW +MBQGA1UEAxMNU2ltcGxlIFNlcnZlcjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC +gYEA6IUeEF7IA5onMYj1nxbNRshtEMtJoNKmVhkhv+izihSmFBZp2X+s5ijCVtx4 +RlSbUh9HN3yQJnL0lpiv6MuivXiYElMcla8x3nryBG5ZNE6dpZI9NqGCuMzyiuhH +2AhyJPQ2xDOAly5T/jnILNUmPbPBmpUX5hYjAaTyXM9hUIkCAwEAATANBgkqhkiG +9w0BAQQFAAOBgQAo6u+V9CU9tLJI6iD3X+oxC6Z5XCL7iz5ROf+G8Jbke21uWbWS +JHvmk1jENrfHZ8z1vm5XN25TWNDXPmNb1c4n3Rn9CcoVnmG+IThAaqQZuwSryj2B +TmvyzKqNqLbdofF1O5hyqgDUFG09323Hny4+TwaUq2yMaj63jpLyUkZc/Q== +-----END CERTIFICATE----- diff --git a/examples/simple/server.pkey b/examples/simple/server.pkey new file mode 100644 index 0000000..dbcfafb --- /dev/null +++ b/examples/simple/server.pkey @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDohR4QXsgDmicxiPWfFs1GyG0Qy0mg0qZWGSG/6LOKFKYUFmnZ +f6zmKMJW3HhGVJtSH0c3fJAmcvSWmK/oy6K9eJgSUxyVrzHeevIEblk0Tp2lkj02 +oYK4zPKK6EfYCHIk9DbEM4CXLlP+Ocgs1SY9s8GalRfmFiMBpPJcz2FQiQIDAQAB +AoGAMnyk+Hz8BPw1wmWwn2h+Df564Aij5g2XHF68m0TVpwewv+/V7+nvCtKSz/Vz +ECJSz1QHTJ75Vb/kJ8bjezKsFPncBRUBBPNlbvOD02DhDQAmzdJPul6gQ2TvtuLu +07KtfjnQcH4/2gqMknW7GB3SroCDZbw72QRuridFvfJlTlkCQQD6TOy7a5WZOn+Q +luYLyWzOaB7uzLfoHY3tWLd1hJBLbY+WvuXFzfjgLteM7vxHpitz+xjiFw6ktK6o +mhmt/QGTAkEA7dCLgaI2lqk3GqndEWsU33PYJlgNWAVjMnGRMmYwEnxYf7WkPGYC +07qhlBoZ1SiiHOmMCD+IY6frChdU8C8m8wJBAIk6gZQj4OoYi3XfdZLCxVfI+CSe +srmc8oJNYJAatO3VzKKuWNWBHtDyfZU0NbamoS4+XZ8fWxTsRtIDYs7kZucCQQCH +h1MJ5M0hXXw26NlAxPrXQajMaV/pauCWbdxmkZAR6OVymqzncudnjLPquFlCfm6s +9XhFdxeeW6L6VEOmweh7AkEAsvcEcce8CAauroQ4ST5dw9dQlxuohHY37lEtWuFL +A7/k1kCtLitZKvAWDfaz34NQUtgr5/lOQ6h+jGfIafpHpQ== +-----END RSA PRIVATE KEY----- diff --git a/examples/simple/server.py b/examples/simple/server.py new file mode 100644 index 0000000..a592ec3 --- /dev/null +++ b/examples/simple/server.py @@ -0,0 +1,101 @@ +# +# server.py +# +# Copyright (C) 2001 Martin Sjögren and AB Strakt, All rights reserved +# +# $Id: server.py,v 1.2 2002/07/25 08:26:34 martin Exp $ +# +""" +Simple echo server, using nonblocking I/O +""" + +from OpenSSL import SSL +import sys, os, select, socket + + +def verify_cb(conn, cert, errnum, depth, ok): + # This obviously has to be updated + print 'Got certificate: %s' % cert.get_subject() + return ok + +if len(sys.argv) < 2: + print 'Usage: python[2] server.py 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_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.setblocking(0) + +clients = {} +writers = {} + +def dropClient(cli, errors=None): + if errors: + print 'Client %s left unexpectedly:' % (clients[cli],) + print ' ', errors + else: + print 'Client %s left politely' % (clients[cli],) + del clients[cli] + if writers.has_key(cli): + del writers[cli] + if not errors: + cli.shutdown() + cli.close() + +while 1: + try: + r,w,_ = select.select([server]+clients.keys(), writers.keys(), []) + except: + break + + for cli in r: + if cli == server: + cli,addr = server.accept() + print 'Connection from %s' % (addr,) + clients[cli] = addr + + else: + try: + ret = cli.recv(1024) + except (SSL.WantReadError, SSL.WantWriteError, SSL.WantX509LookupError): + pass + except SSL.ZeroReturnError: + dropClient(cli) + except SSL.Error, errors: + dropClient(cli, errors) + else: + if not writers.has_key(cli): + writers[cli] = '' + writers[cli] = writers[cli] + ret + + for cli in w: + try: + ret = cli.send(writers[cli]) + except (SSL.WantReadError, SSL.WantWriteError, SSL.WantX509LookupError): + pass + except SSL.ZeroReturnError: + dropClient(cli) + except SSL.Error, errors: + dropClient(cli, errors) + else: + writers[cli] = writers[cli][ret:] + if writers[cli] == '': + del writers[cli] + +for cli in clients.keys(): + cli.close() +server.close() -- cgit v1.2.1