Advertisement
Biggie

Example TCP-Echo-Server (SSL) ... just hacked together :)

Aug 25th, 2012
1,182
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.77 KB | None | 0 0
  1. #!/usr/bin/env python
  2.  
  3. # Copyright (C) 2012  Biggie
  4. #
  5. # This program is free software; you can redistribute it and/or
  6. # modify it under the terms of the GNU General Public License
  7. # as published by the Free Software Foundation; either version 2
  8. # of the License, or (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  18.  
  19.  
  20. import socket
  21. import SocketServer
  22. import threading
  23.  
  24. from OpenSSL import SSL
  25.  
  26.  
  27.  
  28. class MyRequestHandler(SocketServer.StreamRequestHandler):
  29.     """The MyRequestHandler-class is used to handle a client in
  30.    its own thread"""
  31.  
  32.     def setup(self):
  33.         """setup is called to set up the new client connection."""
  34.         # ----
  35.         # Instead of using SocketServer.StreamRequestHandler.setup(self):
  36.         #   self.connection = self.request
  37.         #   self.rfile = self.connection.makefile('rb', self.rbufsize)
  38.         #   self.wfile = self.connection.makefile('wb', self.wbufsize)
  39.         # Use the following (because of ssl-usage):
  40.         # ----
  41.         if self.server.use_ssl:
  42.             self.connection = self.request
  43.             self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
  44.             self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
  45.         else:
  46.             SocketServer.StreamRequestHandler.setup(self)
  47.  
  48.         # The connection-lock is used to prevent closing the connection
  49.         # while data is written
  50.         self.connection_lock = threading.Lock()
  51.         self.write_lock = threading.Lock()
  52.         self.connected = True
  53.  
  54.     def finish(self):
  55.         """finish is called if the connection to the client is closed."""
  56.         with self.connection_lock:
  57.             SocketServer.StreamRequestHandler.finish(self)
  58.             self.connected = False
  59.  
  60.     def readline(self):
  61.         """Read a new line from the client.socket.
  62.  
  63.        Returns an empty string if an error occurred or the socket was
  64.        closed.
  65.        """
  66.         line = ""
  67.         if self.connected and not self.rfile.closed:
  68.             try:
  69.                 line = self.rfile.readline()
  70.             except socket.error, e:
  71.                 print 'error occurred while reading:', e
  72.             except SSL.SysCallError, e:
  73.                 pass
  74.             except SSL.Error, e:
  75.                 pass  # maybe client does not use ssl
  76.         return line
  77.  
  78.     def write(self, data):
  79.         """Write data to the client-socket.
  80.  
  81.        data -- the data to send
  82.        """
  83.         with self.connection_lock:
  84.             if self.connected:
  85.                 # only 1 write at a time
  86.                 with self.write_lock:
  87.                     if not self.wfile.closed:
  88.                         try:
  89.                             self.wfile.write(data)
  90.                         except socket.error, e:
  91.                             print 'error occurred while writing:', e
  92.  
  93.     def handle(self):
  94.         """handle is called to handle the new client."""
  95.         while True:
  96.             # self.rfile is a file-like object created by the handler
  97.             request = self.readline().strip()
  98.  
  99.             if request == '':
  100.                 return
  101.  
  102.             # act like an echo server
  103.             self.write(request + '\n')
  104.  
  105.  
  106.  
  107. class MyThreadedTCPServer(SocketServer.ThreadingMixIn,
  108.                                 SocketServer.TCPServer):
  109.     """The MyThreadedTCPServer is the TCP-server and handles each client in its
  110.    own thread."""
  111.  
  112.     def __init__(self, certfile, server_address, RequestHandlerClass,
  113.                     bind_and_activate=True):
  114.         """Initialize the MyThreadedTCPServer.
  115.        
  116.        certfile        -- The cert-file which should be used for SSL
  117.                           sockets. If None, no SSL-sockets will be used.
  118.        server_address, RequestHandlerClass, bind_and_activate
  119.                        -- see SocketServer.TCPServer.__init__
  120.        """
  121.         self.daemon_threads = True  # kill threads when server stops
  122.         self.client_lock = threading.Lock()
  123.  
  124.         # if cert-file is present then use ssl
  125.         if certfile is None:
  126.             self.use_ssl = False
  127.             SocketServer.TCPServer.__init__(self, server_address,
  128.                                         RequestHandlerClass, bind_and_activate)
  129.         else:
  130.             self.use_ssl = True
  131.             # Code taken from SocketServer.TCPServer.__init__
  132.             # and added ssl-support:
  133.             SocketServer.BaseServer.__init__(self, server_address,
  134.                                                 RequestHandlerClass)
  135.             ctx = SSL.Context(SSL.SSLv23_METHOD)
  136.             # cert.pem-file containing the server private key and certificate
  137.             cert = certfile
  138.             ctx.use_privatekey_file(cert)
  139.             ctx.use_certificate_file(cert)
  140.             self.socket = SSL.Connection(ctx, socket.socket(self.address_family,
  141.                                                             self.socket_type))
  142.             if bind_and_activate:
  143.                 self.server_bind()
  144.                 self.server_activate()
  145.  
  146.     def shutdown_request(self,request):
  147.         request.shutdown()
  148.  
  149.  
  150.  
  151. class MyTCPServer:
  152.     """The MyTCPServer ecapsulates the TCP-server and can be used to start and
  153.    stop the server."""
  154.  
  155.     def __init__(self, host, port, certfile=None):
  156.         """Initialize the MyTCPServer.
  157.  
  158.        host        -- The host-address of the server.
  159.        port        -- The port to bind the server to.
  160.        certfile -- The cert-file to use when using SSL-sockets.
  161.        """
  162.         self.host = host
  163.         self.port = port
  164.  
  165.         self.server = MyThreadedTCPServer(certfile, (self.host, self.port),
  166.                                                 MyRequestHandler)
  167.  
  168.     def start(self):
  169.         """Start the server."""
  170.         # Start a thread with the server -- that thread will then start one
  171.         # more thread for each request
  172.         server_thread = threading.Thread(target=self.server.serve_forever)
  173.         # Exit the server thread when the main thread terminates
  174.         server_thread.daemon = False
  175.         server_thread.start()
  176.  
  177.     def stop(self):
  178.         """Stop the server."""
  179.         self.server.shutdown()
  180.  
  181.  
  182.  
  183. if __name__ == "__main__":
  184.     # EXAMPLE-Code
  185.  
  186.     server = MyTCPServer('localhost', 9999, '/home/biggie/foruse.cer')
  187.     server.start()
  188.  
  189.     import time
  190.     time.sleep(30)
  191.  
  192.     server.stop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement