1# -*- coding: latin-1 -*- 2# 3# Copyright (C) AB Strakt 4# Copyright (C) Jean-Paul Calderone 5# See LICENSE for details. 6 7""" 8Simple echo server, using nonblocking I/O 9""" 10 11from __future__ import print_function 12 13import os 14import select 15import socket 16import sys 17 18from OpenSSL import SSL, crypto 19 20 21def verify_cb(conn, cert, errnum, depth, ok): 22 certsubject = crypto.X509Name(cert.get_subject()) 23 commonname = certsubject.commonName 24 print('Got certificate: ' + commonname) 25 return ok 26 27 28if len(sys.argv) < 2: 29 print('Usage: python server.py PORT') 30 sys.exit(1) 31 32dir = os.path.dirname(sys.argv[0]) 33if dir == '': 34 dir = os.curdir 35 36# Initialize context 37ctx = SSL.Context(SSL.SSLv23_METHOD) 38ctx.set_options(SSL.OP_NO_SSLv2) 39ctx.set_options(SSL.OP_NO_SSLv3) 40ctx.set_verify( 41 SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb 42) # Demand a certificate 43ctx.use_privatekey_file(os.path.join(dir, 'server.pkey')) 44ctx.use_certificate_file(os.path.join(dir, 'server.cert')) 45ctx.load_verify_locations(os.path.join(dir, 'CA.cert')) 46 47# Set up server 48server = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM)) 49server.bind(('', int(sys.argv[1]))) 50server.listen(3) 51server.setblocking(0) 52 53clients = {} 54writers = {} 55 56 57def dropClient(cli, errors=None): 58 if errors: 59 print('Client %s left unexpectedly:' % (clients[cli],)) 60 print(' ', errors) 61 else: 62 print('Client %s left politely' % (clients[cli],)) 63 del clients[cli] 64 if cli in writers: 65 del writers[cli] 66 if not errors: 67 cli.shutdown() 68 cli.close() 69 70 71while 1: 72 try: 73 r, w, _ = select.select( 74 [server] + list(clients.keys()), list(writers.keys()), [] 75 ) 76 except Exception: 77 break 78 79 for cli in r: 80 if cli == server: 81 cli, addr = server.accept() 82 print('Connection from %s' % (addr,)) 83 clients[cli] = addr 84 85 else: 86 try: 87 ret = cli.recv(1024).decode('utf-8') 88 except (SSL.WantReadError, 89 SSL.WantWriteError, 90 SSL.WantX509LookupError): 91 pass 92 except SSL.ZeroReturnError: 93 dropClient(cli) 94 except SSL.Error as errors: 95 dropClient(cli, errors) 96 else: 97 if cli not in writers: 98 writers[cli] = '' 99 writers[cli] = writers[cli] + ret 100 101 for cli in w: 102 try: 103 ret = cli.send(writers[cli]) 104 except (SSL.WantReadError, 105 SSL.WantWriteError, 106 SSL.WantX509LookupError): 107 pass 108 except SSL.ZeroReturnError: 109 dropClient(cli) 110 except SSL.Error as errors: 111 dropClient(cli, errors) 112 else: 113 writers[cli] = writers[cli][ret:] 114 if writers[cli] == '': 115 del writers[cli] 116 117for cli in clients.keys(): 118 cli.close() 119server.close() 120