[Spambayes-checkins] spambayes/scripts sb_server.py,1.39,1.40

Tony Meyer anadelonbrin at users.sourceforge.net
Mon Jan 3 07:51:46 CET 2005


Update of /cvsroot/spambayes/spambayes/scripts
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13766/scripts

Modified Files:
	sb_server.py 
Log Message:
Implement part of [ 753708 ] Support POP over SSL

If the use_ssl option is on (or automatic and the POP3 server port is 995) then sb_server
 will try and make a SSL/TLS connection to the server, rather than a regular connection.
 Note that the connection between sb_server and the mail client is *not* SSL/TLS -
 I think that would mean we needed to have SSL/TLS server code, which doesn't look
 easy, and isn't in the Python stdlib.  That's almost certainly a local (or at least
 controlled) connection, anyway, so that shouldn't matter.

This *mostly* works (with Python 2.4 or 2.3.5 - 2.3.4 has an outstanding bug)).

The remaining problem is that if the incoming data is larger than the buffer (4096)
 then the final chunk isn't received until a new command is send.  This screws all
 sorts of things up.  I can't figure out why that is though - select.select seems
 to ignore the remaining bit waiting (maybe select.select works differently with SSL
 sockets?).  I'll have another crack at it tomorrow, unless someone else figures it
 out overnight.

Index: sb_server.py
===================================================================
RCS file: /cvsroot/spambayes/spambayes/scripts/sb_server.py,v
retrieving revision 1.39
retrieving revision 1.40
diff -C2 -d -r1.39 -r1.40
*** sb_server.py	2 Jan 2005 04:56:40 -0000	1.39
--- sb_server.py	3 Jan 2005 06:51:42 -0000	1.40
***************
*** 91,96 ****
  
   o Slightly-wordy index page; intro paragraph for each page.
!  o In both stats and training results, report nham and nspam - warn if
!    they're very different (for some value of 'very').
   o "Links" section (on homepage?) to project homepage, mailing list,
     etc.
--- 91,95 ----
  
   o Slightly-wordy index page; intro paragraph for each page.
!  o In both stats and training results, report nham and nspam.
   o "Links" section (on homepage?) to project homepage, mailing list,
     etc.
***************
*** 102,106 ****
   o Graphs.  Of something.  Who cares what?
   o NNTP proxy.
-  o Zoe...!
  """
  
--- 101,104 ----
***************
*** 146,152 ****
      synchronously, because that would block the process."""
  
!     lineCallback = None
! 
!     def __init__(self, serverName, serverPort, lineCallback):
          Dibbler.BrighterAsyncChat.__init__(self)
          self.lineCallback = lineCallback
--- 144,148 ----
      synchronously, because that would block the process."""
  
!     def __init__(self, serverName, serverPort, lineCallback, ssl=False):
          Dibbler.BrighterAsyncChat.__init__(self)
          self.lineCallback = lineCallback
***************
*** 154,157 ****
--- 150,158 ----
          self.set_terminator('\r\n')
          self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
+         # create_socket creates a non-blocking socket.  This is fine for
+         # regular sockets, but not for ssl - if it is non-blocking then the
+         # second ssl connection will fail.
+         if ssl:
+             self.socket.setblocking(1)
          try:
              self.connect((serverName, serverPort))
***************
*** 162,165 ****
--- 163,203 ----
              self.lineCallback('')   # "The socket's been closed."
              self.close()
+         else:
+             if ssl:
+                 try:
+                     self.ssl_socket = socket.ssl(self.socket)
+                 except socket.sslerror, why:
+                     if why[0] == 1: # error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol'
+                         # Probably not SSL after all.
+                         print >>sys.stderr, "Can't use SSL"
+                     else:
+                         raise
+                 else:
+                     self.send = self.send_ssl
+                     self.recv = self.recv_ssl
+                 self.socket.setblocking(0)
+                 print self._fileno
+             
+     def send_ssl(self, data):
+         return self.ssl_socket.write(data)
+ 
+     def recv_ssl(self, buffer_size):
+         try:
+             data = self.ssl_socket.read(buffer_size)
+             if not data:
+                 # a closed connection is indicated by signaling
+                 # a read condition, and having recv() return 0.
+                 self.handle_close()
+                 return ''
+             else:
+                 return data
+         except socket.sslerror, why:
+             if why[0] == 6: # 'TLS/SSL connection has been closed'
+                 self.handle_close()
+                 return ''
+             elif why[0] == 2: # 'The operation did not complete (read)'
+                 return ''
+             else:
+                 raise
  
      def collect_incoming_data(self, data):
***************
*** 173,176 ****
--- 211,218 ----
          self.lineCallback('')
          self.close()
+         try:
+             del self.ssl_socket, self.socket
+         except AttributeError:
+             pass
  
  
***************
*** 188,192 ****
      """
  
!     def __init__(self, clientSocket, serverName, serverPort):
          Dibbler.BrighterAsyncChat.__init__(self, clientSocket)
          self.request = ''
--- 230,234 ----
      """
  
!     def __init__(self, clientSocket, serverName, serverPort, ssl=False):
          Dibbler.BrighterAsyncChat.__init__(self, clientSocket)
          self.request = ''
***************
*** 207,211 ****
  
          self.serverSocket = ServerLineReader(serverName, serverPort,
!                                              self.onServerLine)
  
      def onIncomingConnection(self, clientSocket):
--- 249,253 ----
  
          self.serverSocket = ServerLineReader(serverName, serverPort,
!                                              self.onServerLine, ssl)
  
      def onIncomingConnection(self, clientSocket):
***************
*** 345,350 ****
      """
  
!     def __init__(self, serverName, serverPort, proxyPort):
!         proxyArgs = (serverName, serverPort)
          Dibbler.Listener.__init__(self, proxyPort, BayesProxy, proxyArgs)
          print 'Listener on port %s is proxying %s:%d' % \
--- 387,392 ----
      """
  
!     def __init__(self, serverName, serverPort, proxyPort, ssl=False):
!         proxyArgs = (serverName, serverPort, ssl)
          Dibbler.Listener.__init__(self, proxyPort, BayesProxy, proxyArgs)
          print 'Listener on port %s is proxying %s:%d' % \
***************
*** 384,389 ****
      """
  
!     def __init__(self, clientSocket, serverName, serverPort):
!         POP3ProxyBase.__init__(self, clientSocket, serverName, serverPort)
          self.handlers = {'STAT': self.onStat, 'LIST': self.onList,
                           'RETR': self.onRetr, 'TOP': self.onTop,
--- 426,432 ----
      """
  
!     def __init__(self, clientSocket, serverName, serverPort, ssl=False):
!         POP3ProxyBase.__init__(self, clientSocket, serverName, serverPort,
!                                ssl)
          self.handlers = {'STAT': self.onStat, 'LIST': self.onList,
                           'RETR': self.onRetr, 'TOP': self.onTop,
***************
*** 897,901 ****
      """Create BayesProxyListeners for all the given servers."""
      for (server, serverPort), proxyPort in zip(servers, proxyPorts):
!         listener = BayesProxyListener(server, serverPort, proxyPort)
          proxyListeners.append(listener)
  
--- 940,947 ----
      """Create BayesProxyListeners for all the given servers."""
      for (server, serverPort), proxyPort in zip(servers, proxyPorts):
!         ssl = options["pop3proxy", "use_ssl"]
!         if ssl == "automatic":
!             ssl = serverPort == 995
!         listener = BayesProxyListener(server, serverPort, proxyPort, ssl)
          proxyListeners.append(listener)
  



More information about the Spambayes-checkins mailing list