@ -32,7 +32,7 @@ import hmac 
				
			 
			
		
	
		
		
			
				
					 
					 
					import  hashlib  
					 
					 
					import  hashlib  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					import  shadowsocks  
					 
					 
					import  shadowsocks  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					from  shadowsocks  import  common ,  lru_cache  
					 
					 
					from  shadowsocks  import  common ,  lru_cache ,  encrypt  
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					 
					 
					from  shadowsocks . obfsplugin  import  plain  
					 
					 
					from  shadowsocks . obfsplugin  import  plain  
				
			 
			
		
	
		
		
			
				
					 
					 
					from  shadowsocks . common  import  to_bytes ,  to_str ,  ord ,  chr  
					 
					 
					from  shadowsocks . common  import  to_bytes ,  to_str ,  ord ,  chr  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					@ -48,6 +48,9 @@ def create_auth_sha1_v3(method): 
				
			 
			
		
	
		
		
			
				
					 
					 
					def  create_auth_sha1_v4 ( method ) :  
					 
					 
					def  create_auth_sha1_v4 ( method ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					    return  auth_sha1_v4 ( method )  
					 
					 
					    return  auth_sha1_v4 ( method )  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					def  create_auth_aes128 ( method ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					    return  auth_aes128 ( method )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					obfs_map  =  {  
					 
					 
					obfs_map  =  {  
				
			 
			
		
	
		
		
			
				
					 
					 
					        ' auth_sha1 ' :  ( create_auth_sha1 , ) ,  
					 
					 
					        ' auth_sha1 ' :  ( create_auth_sha1 , ) ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					        ' auth_sha1_compatible ' :  ( create_auth_sha1 , ) ,  
					 
					 
					        ' auth_sha1_compatible ' :  ( create_auth_sha1 , ) ,  
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					@ -57,6 +60,7 @@ obfs_map = { 
				
			 
			
		
	
		
		
			
				
					 
					 
					        ' auth_sha1_v3_compatible ' :  ( create_auth_sha1_v3 , ) ,  
					 
					 
					        ' auth_sha1_v3_compatible ' :  ( create_auth_sha1_v3 , ) ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					        ' auth_sha1_v4 ' :  ( create_auth_sha1_v4 , ) ,  
					 
					 
					        ' auth_sha1_v4 ' :  ( create_auth_sha1_v4 , ) ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					        ' auth_sha1_v4_compatible ' :  ( create_auth_sha1_v4 , ) ,  
					 
					 
					        ' auth_sha1_v4_compatible ' :  ( create_auth_sha1_v4 , ) ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        ' auth_aes128 ' :  ( create_auth_aes128 , ) ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					}  
					 
					 
					}  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					def  match_begin ( str1 ,  str2 ) :  
					 
					 
					def  match_begin ( str1 ,  str2 ) :  
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					@ -1048,3 +1052,257 @@ class auth_sha1_v4(verify_base): 
				
			 
			
		
	
		
		
			
				
					 
					 
					            self . decrypt_packet_num  + =  1  
					 
					 
					            self . decrypt_packet_num  + =  1  
				
			 
			
		
	
		
		
			
				
					 
					 
					        return  ( out_buf ,  sendback )  
					 
					 
					        return  ( out_buf ,  sendback )  
				
			 
			
		
	
		
		
			
				
					 
					 
					
 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					class  auth_aes128 ( verify_base ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					    def  __init__ ( self ,  method ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        super ( auth_aes128 ,  self ) . __init__ ( method )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . recv_buf  =  b ' '  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . unit_len  =  8100  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . raw_trans  =  False  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . has_sent_header  =  False  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . has_recv_header  =  False  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . client_id  =  0  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . connection_id  =  0  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . max_time_dif  =  60  *  60  *  24  # time dif (second) setting  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . salt  =  b " auth_aes128 "  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . no_compatible_method  =  ' auth_aes128 '  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . extra_wait_size  =  struct . unpack ( ' >H ' ,  os . urandom ( 2 ) ) [ 0 ]  %  1024  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . pack_id  =  0  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . recv_id  =  0  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					    def  init_data ( self ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        return  obfs_auth_v2_data ( )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					    def  set_server_info ( self ,  server_info ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . server_info  =  server_info  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        try :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            max_client  =  int ( server_info . protocol_param )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        except :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            max_client  =  64  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . server_info . data . set_max_client ( max_client )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					    def  rnd_data ( self ,  buf_size ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        if  buf_size  >  1200 :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            return  b ' \x01 '  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        if  self . pack_id  >  4 :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            rnd_data  =  os . urandom ( common . ord ( os . urandom ( 1 ) [ 0 ] )  %  32 )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        elif  buf_size  >  400 :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            rnd_data  =  os . urandom ( common . ord ( os . urandom ( 1 ) [ 0 ] )  %  128 )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        else :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            rnd_data  =  os . urandom ( struct . unpack ( ' >H ' ,  os . urandom ( 2 ) ) [ 0 ]  %  512 )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        if  len ( rnd_data )  <  128 :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            return  common . chr ( len ( rnd_data )  +  1 )  +  rnd_data  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        else :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            return  common . chr ( 255 )  +  struct . pack ( ' <H ' ,  len ( rnd_data )  +  3 )  +  rnd_data  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					    def  pack_data ( self ,  buf ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        data  =  self . rnd_data ( len ( buf ) )  +  buf  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        data_len  =  len ( data )  +  8  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        crc  =  binascii . crc32 ( struct . pack ( ' <H ' ,  data_len ) )  &  0xFFFF  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        data  =  struct . pack ( ' <H ' ,  crc )  +  data  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        data  =  struct . pack ( ' <H ' ,  data_len )  +  data  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        adler32  =  ( zlib . adler32 ( data )  &  0xFFFFFFFF )  ^  self . pack_id  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . pack_id  =  ( self . pack_id  +  1 )  &  0xFFFFFFFF  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        data  + =  struct . pack ( ' <I ' ,  adler32 )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        return  data  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					    def  pack_auth_data ( self ,  auth_data ,  buf ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        if  len ( buf )  ==  0 :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            return  b ' '  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        if  len ( buf )  >  400 :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            rnd_len  =  common . ord ( os . urandom ( 1 ) [ 0 ] )  %  512  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        else :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            rnd_len  =  struct . unpack ( ' <H ' ,  os . urandom ( 2 ) ) [ 0 ]  %  1024  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        data  =  auth_data  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        data_len  =  len ( buf )  +  rnd_len  +  16  +  10  +  4  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        data  =  data  +  struct . pack ( ' <H ' ,  data_len )  +  struct . pack ( ' <H ' ,  rnd_len )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        uid  =  ' \x00 '  *  4  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        encryptor  =  encrypt . Encryptor ( to_bytes ( base64 . b64encode ( uid  +  self . server_info . key ) )  +  self . salt ,  ' aes-128-cbc ' ,  b ' \x00 '  *  16 )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        data  =  uid  +  encryptor . encrypt ( data ) [ 16 : ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        data  + =  hmac . new ( self . server_info . iv  +  self . server_info . key ,  data ,  hashlib . sha1 ) . digest ( ) [ : 10 ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        data  + =  os . urandom ( rnd_len )  +  buf  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        crc  =  binascii . crc32 ( struct . pack ( ' <H ' ,  data_len ) )  &  0xFFFF  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        data  =  struct . pack ( ' <H ' ,  crc )  +  data  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        return  data  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					    def  auth_data ( self ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        utc_time  =  int ( time . time ( ) )  &  0xFFFFFFFF  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        if  self . server_info . data . connection_id  >  0xFF000000 :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            self . server_info . data . local_client_id  =  b ' '  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        if  not  self . server_info . data . local_client_id :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            self . server_info . data . local_client_id  =  os . urandom ( 4 )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            logging . debug ( " local_client_id  %s "  %  ( binascii . hexlify ( self . server_info . data . local_client_id ) , ) )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            self . server_info . data . connection_id  =  struct . unpack ( ' <I ' ,  os . urandom ( 4 ) ) [ 0 ]  &  0xFFFFFF  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . server_info . data . connection_id  + =  1  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        return  b ' ' . join ( [ struct . pack ( ' <I ' ,  utc_time ) ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                self . server_info . data . local_client_id ,  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                struct . pack ( ' <I ' ,  self . server_info . data . connection_id ) ] )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					    def  client_pre_encrypt ( self ,  buf ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        ret  =  b ' '  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        if  not  self . has_sent_header :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            head_size  =  self . get_head_size ( buf ,  30 )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            datalen  =  min ( len ( buf ) ,  random . randint ( 0 ,  31 )  +  head_size )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            ret  + =  self . pack_auth_data ( self . auth_data ( ) ,  buf [ : datalen ] )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            buf  =  buf [ datalen : ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            self . has_sent_header  =  True  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        while  len ( buf )  >  self . unit_len :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            ret  + =  self . pack_data ( buf [ : self . unit_len ] )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            buf  =  buf [ self . unit_len : ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        ret  + =  self . pack_data ( buf )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        return  ret  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					    def  client_post_decrypt ( self ,  buf ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        if  self . raw_trans :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            return  buf  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . recv_buf  + =  buf  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        out_buf  =  b ' '  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        while  len ( self . recv_buf )  >  4 :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            crc  =  struct . pack ( ' <H ' ,  binascii . crc32 ( self . recv_buf [ : 2 ] )  &  0xFFFF )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            if  crc  !=  self . recv_buf [ 2 : 4 ] :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                raise  Exception ( ' client_post_decrypt data uncorrect crc ' )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            length  =  struct . unpack ( ' <H ' ,  self . recv_buf [ : 2 ] ) [ 0 ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            if  length  > =  8192  or  length  <  7 :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                self . raw_trans  =  True  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                self . recv_buf  =  b ' '  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                raise  Exception ( ' client_post_decrypt data error ' )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            if  length  >  len ( self . recv_buf ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                break  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            if  struct . pack ( ' <I ' ,  ( zlib . adler32 ( self . recv_buf [ : length  -  4 ] )  &  0xFFFFFFFF )  ^  self . recv_id )  !=  self . recv_buf [ length  -  4 : length ] :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                self . raw_trans  =  True  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                self . recv_buf  =  b ' '  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                raise  Exception ( ' client_post_decrypt data uncorrect checksum ' )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            self . recv_id  =  ( self . recv_id  +  1 )  &  0xFFFFFFFF  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            pos  =  common . ord ( self . recv_buf [ 4 ] )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            if  pos  <  255 :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                pos  + =  4  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            else :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                pos  =  struct . unpack ( ' <H ' ,  self . recv_buf [ 5 : 7 ] ) [ 0 ]  +  4  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            out_buf  + =  self . recv_buf [ pos : length  -  4 ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            self . recv_buf  =  self . recv_buf [ length : ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        return  out_buf  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					    def  server_pre_encrypt ( self ,  buf ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        if  self . raw_trans :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            return  buf  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        ret  =  b ' '  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        while  len ( buf )  >  self . unit_len :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            ret  + =  self . pack_data ( buf [ : self . unit_len ] )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            buf  =  buf [ self . unit_len : ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        ret  + =  self . pack_data ( buf )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        return  ret  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					    def  server_post_decrypt ( self ,  buf ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        if  self . raw_trans :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            return  ( buf ,  False )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        self . recv_buf  + =  buf  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        out_buf  =  b ' '  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        if  not  self . has_recv_header :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            if  len ( self . recv_buf )  <  30 :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                return  ( b ' ' ,  False )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            sha1data  =  hmac . new ( self . server_info . recv_iv  +  self . server_info . key ,  self . recv_buf [ : 20 ] ,  hashlib . sha1 ) . digest ( ) [ : 10 ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            if  sha1data  !=  self . recv_buf [ 20 : 30 ] :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                logging . error ( ' auth_aes128 data uncorrect auth HMAC-SHA1 from  %s : %d , data  %s '  %  ( self . server_info . client ,  self . server_info . client_port ,  binascii . hexlify ( self . recv_buf ) ) )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                if  len ( self . recv_buf )  <  30  +  self . extra_wait_size :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                    return  ( b ' ' ,  False )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                return  self . not_match_return ( self . recv_buf )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            user_key  =  self . recv_buf [ : 4 ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            encryptor  =  encrypt . Encryptor ( to_bytes ( base64 . b64encode ( user_key  +  self . server_info . key ) )  +  self . salt ,  ' aes-128-cbc ' )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            head  =  encryptor . decrypt ( b ' \x00 '  *  16  +  self . recv_buf [ 4 : 20 ]  +  b ' \x00 ' )  # need an extra byte or recv empty  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            length  =  struct . unpack ( ' <H ' ,  head [ 12 : 14 ] ) [ 0 ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            if  len ( self . recv_buf )  <  length :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                return  ( b ' ' ,  False )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            utc_time  =  struct . unpack ( ' <I ' ,  head [ : 4 ] ) [ 0 ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            client_id  =  struct . unpack ( ' <I ' ,  head [ 4 : 8 ] ) [ 0 ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            connection_id  =  struct . unpack ( ' <I ' ,  head [ 8 : 12 ] ) [ 0 ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            rnd_len  =  struct . unpack ( ' <H ' ,  head [ 14 : 16 ] ) [ 0 ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            if  struct . pack ( ' <I ' ,  zlib . adler32 ( self . recv_buf [ : length  -  4 ] )  &  0xFFFFFFFF )  !=  self . recv_buf [ length  -  4 : length ] :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                logging . info ( ' auth_aes128: checksum error, data  %s '  %  ( binascii . hexlify ( self . recv_buf [ : length ] ) , ) )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                return  self . not_match_return ( self . recv_buf )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            time_dif  =  common . int32 ( utc_time  -  ( int ( time . time ( ) )  &  0xffffffff ) )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            if  time_dif  <  - self . max_time_dif  or  time_dif  >  self . max_time_dif :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                logging . info ( ' auth_aes128: wrong timestamp, time_dif  %d , data  %s '  %  ( time_dif ,  binascii . hexlify ( head ) , ) )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                return  self . not_match_return ( self . recv_buf )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            elif  self . server_info . data . insert ( client_id ,  connection_id ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                self . has_recv_header  =  True  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                out_buf  =  self . recv_buf [ 30  +  rnd_len : length  -  4 ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                self . client_id  =  client_id  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                self . connection_id  =  connection_id  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            else :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                logging . info ( ' auth_aes128: auth fail, data  %s '  %  ( binascii . hexlify ( out_buf ) , ) )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                return  self . not_match_return ( self . recv_buf )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            self . recv_buf  =  self . recv_buf [ length : ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            self . has_recv_header  =  True  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        sendback  =  False  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        while  len ( self . recv_buf )  >  4 :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            crc  =  struct . pack ( ' <H ' ,  binascii . crc32 ( self . recv_buf [ : 2 ] )  &  0xFFFF )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            if  crc  !=  self . recv_buf [ 2 : 4 ] :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                self . raw_trans  =  True  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                logging . info ( ' auth_aes128: wrong crc ' )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                if  self . recv_id  ==  0 :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                    logging . info ( ' auth_aes128: wrong crc ' )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                    return  ( b ' E ' ,  False )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                else :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                    raise  Exception ( ' server_post_decrype data error ' )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            length  =  struct . unpack ( ' <H ' ,  self . recv_buf [ : 2 ] ) [ 0 ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            if  length  > =  8192  or  length  <  7 :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                self . raw_trans  =  True  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                self . recv_buf  =  b ' '  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                if  self . recv_id  ==  0 :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                    logging . info ( ' auth_aes128: over size ' )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                    return  ( b ' E ' ,  False )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                else :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                    raise  Exception ( ' server_post_decrype data error ' )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            if  length  >  len ( self . recv_buf ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                break  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            if  struct . pack ( ' <I ' ,  ( zlib . adler32 ( self . recv_buf [ : length  -  4 ] )  &  0xFFFFFFFF )  ^  self . recv_id )  !=  self . recv_buf [ length  -  4 : length ] :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                logging . info ( ' auth_aes128: checksum error, data  %s '  %  ( binascii . hexlify ( self . recv_buf [ : length ] ) , ) )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                self . raw_trans  =  True  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                self . recv_buf  =  b ' '  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                if  self . recv_id  ==  0 :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                    return  ( b ' E ' ,  False )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                else :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                    raise  Exception ( ' server_post_decrype data uncorrect checksum ' )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            self . recv_id  =  ( self . recv_id  +  1 )  &  0xFFFFFFFF  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            pos  =  common . ord ( self . recv_buf [ 4 ] )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            if  pos  <  255 :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                pos  + =  4  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            else :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                pos  =  struct . unpack ( ' <H ' ,  self . recv_buf [ 5 : 7 ] ) [ 0 ]  +  4  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            out_buf  + =  self . recv_buf [ pos : length  -  4 ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            self . recv_buf  =  self . recv_buf [ length : ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            if  pos  ==  length  -  4 :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					                sendback  =  True  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        if  out_buf :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            self . server_info . data . update ( self . client_id ,  self . connection_id )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        return  ( out_buf ,  sendback )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					    def  client_udp_pre_encrypt ( self ,  buf ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        return  buf  +  struct . pack ( ' <I ' ,  zlib . adler32 ( buf )  &  0xFFFFFFFF )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					    def  client_udp_post_decrypt ( self ,  buf ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        length  =  len ( buf )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        data  =  buf [ : - 4 ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        if  struct . pack ( ' <I ' ,  zlib . adler32 ( data )  &  0xFFFFFFFF )  !=  buf [ length  -  4 : ] :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            return  b ' '  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        return  data  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					    def  server_udp_pre_encrypt ( self ,  buf ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        return  buf  +  struct . pack ( ' <I ' ,  zlib . adler32 ( buf )  &  0xFFFFFFFF )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					    def  server_udp_post_decrypt ( self ,  buf ) :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        length  =  len ( buf )  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        data  =  buf [ : - 4 ]  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        if  struct . pack ( ' <I ' ,  zlib . adler32 ( data )  &  0xFFFFFFFF )  !=  buf [ length  -  4 : ] :  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					            return  b ' '  
				
			 
			
		
	
		
		
			
				
					 
					 
					 
					 
					 
					        return  data