44__author__ = 'Simon Robinson'
55__copyright__ = 'Copyright (c) 2022 Simon Robinson'
66__license__ = 'Apache 2.0'
7- __version__ = '2022-08-17 ' # ISO 8601 (YYYY-MM-DD)
7+ __version__ = '2022-08-19 ' # ISO 8601 (YYYY-MM-DD)
88
99import argparse
1010import asyncore
@@ -597,6 +597,9 @@ def __init__(self, proxy_type, connection, socket_map, connection_info, server_c
597597 self .censor_next_log = False # try to avoid logging credentials
598598 self .authenticated = False
599599
600+ self .ssl_handshake_completed = not (
601+ custom_configuration ['local_certificate_path' ] and custom_configuration ['local_key_path' ])
602+
600603 def info_string (self ):
601604 if Log .get_level () == logging .DEBUG :
602605 return '%s (%s:%d; %s:%d->%s:%d%s)' % (
@@ -607,20 +610,28 @@ def info_string(self):
607610 else :
608611 return '%s (%s:%d)' % (self .proxy_type , self .local_address [0 ], self .local_address [1 ])
609612
610- def handle_connect (self ):
611- pass
612-
613- def get_data (self ):
613+ def ssl_handshake (self ):
614614 try :
615- byte_data = self .recv (RECEIVE_BUFFER_SIZE )
616- return byte_data
617- except (ssl .SSLWantReadError , ssl .SSLWantWriteError ) as e : # only relevant when using local certificates
618- Log .info (self .info_string (), 'Warning: caught client-side SSL recv error' ,
619- '(see https://github.com/simonrob/email-oauth2-proxy/issues/9):' , Log .error_string (e ))
620- return None
615+ # noinspection PyUnresolvedReferences
616+ self .socket .do_handshake ()
617+ except (ssl .SSLWantReadError , ssl .SSLWantWriteError ): # only relevant when using local certificates
618+ return
619+ else :
620+ Log .debug (self .info_string (), '[ SSL/TLS handshake complete ]' )
621+ self .ssl_handshake_completed = True
622+
623+ def readable (self ):
624+ return super ().readable () and self .ssl_handshake_completed
625+
626+ def writable (self ):
627+ return super ().writable () and self .ssl_handshake_completed
621628
622629 def handle_read (self ):
623- byte_data = self .get_data ()
630+ if not self .ssl_handshake_completed :
631+ self .ssl_handshake ()
632+ return
633+
634+ byte_data = self .recv (RECEIVE_BUFFER_SIZE )
624635 if not byte_data :
625636 return
626637
@@ -675,18 +686,11 @@ def process_data(self, byte_data, censor_server_log=False):
675686 self .close ()
676687
677688 def send (self , byte_data ):
689+ while not self .ssl_handshake_completed :
690+ self .ssl_handshake ()
691+
678692 Log .debug (self .info_string (), '<--' , byte_data )
679- try :
680- super ().send (byte_data )
681- except (ssl .SSLWantReadError , ssl .SSLWantWriteError ) as e : # only relevant when using local certificates
682- Log .info (self .info_string (), 'Warning: caught client-side SSL send error' ,
683- '(see https://github.com/simonrob/email-oauth2-proxy/issues/9):' , Log .error_string (e ))
684- while True :
685- try :
686- super ().send (byte_data )
687- break
688- except (ssl .SSLWantReadError , ssl .SSLWantWriteError ):
689- time .sleep (1 )
693+ super ().send (byte_data )
690694
691695 def log_info (self , message , message_type = 'info' ):
692696 # override to redirect error messages to our own log
@@ -1355,7 +1359,7 @@ def start(self):
13551359 self .create_socket (socket .AF_INET , socket .SOCK_STREAM )
13561360 self .set_reuse_addr ()
13571361 self .bind (self .local_address )
1358- self .listen (1 )
1362+ self .listen (5 )
13591363
13601364 def create_socket (self , socket_family = socket .AF_INET , socket_type = socket .SOCK_STREAM ):
13611365 if self .custom_configuration ['local_certificate_path' ] and self .custom_configuration ['local_key_path' ]:
@@ -1366,7 +1370,9 @@ def create_socket(self, socket_family=socket.AF_INET, socket_type=socket.SOCK_ST
13661370 ssl_context .load_cert_chain (
13671371 certfile = self .custom_configuration ['local_certificate_path' ],
13681372 keyfile = self .custom_configuration ['local_key_path' ])
1369- self .set_socket (ssl_context .wrap_socket (new_socket , server_side = True ))
1373+ # suppress_ragged_eofs=True: see test_ssl.py documentation in https://github.com/python/cpython/pull/5266
1374+ self .set_socket (ssl_context .wrap_socket (new_socket , server_side = True , suppress_ragged_eofs = True ,
1375+ do_handshake_on_connect = False ))
13701376 else :
13711377 super ().create_socket (socket_family , socket_type )
13721378
0 commit comments