@@ -1328,6 +1328,61 @@ def handle_AUTHENTICATION_REQUEST(self: "Connection", data: bytes, cursor: Curso
13281328 # self._write(NULL_BYTE)
13291329 self ._flush ()
13301330
1331+ elif auth_code == 13 : # AUTH_REQ_DIGEST
1332+ offset : int = 4
1333+ algo : int = i_unpack (data , offset )[0 ]
1334+ algo_names : typing .Tuple [str ] = ("SHA256" ,)
1335+ offset += 4
1336+
1337+ salt_len : int = i_unpack (data , offset )[0 ]
1338+ offset += 4
1339+
1340+ salt = data [offset : offset + salt_len ]
1341+ offset += salt_len
1342+
1343+ server_nonce_len : int = i_unpack (data , offset )[0 ]
1344+ offset += 4
1345+
1346+ server_nonce : bytes = data [offset : offset + server_nonce_len ]
1347+ offset += server_nonce_len
1348+
1349+ ms_since_epoch : int = int ((Datetime .utcnow () - Datetime .utcfromtimestamp (0 )).total_seconds () * 1000.0 )
1350+ client_nonce : bytes = str (ms_since_epoch ).encode ("utf-8" )
1351+
1352+ _logger .debug ("handle_AUTHENTICATION_REQUEST: AUTH_REQ_DIGEST" )
1353+ _logger .debug ("Algo:{}" .format (algo ))
1354+
1355+ if self .password is None :
1356+ raise InterfaceError (
1357+ "The server requested password-based authentication, but no password was provided."
1358+ )
1359+
1360+ if algo > len (algo_names ):
1361+ raise InterfaceError (
1362+ "The server requested password-based authentication, "
1363+ "but requested algorithm {} is not supported." .format (algo )
1364+ )
1365+
1366+ from redshift_connector .utils .extensible_digest import ExtensibleDigest
1367+
1368+ digest : bytes = ExtensibleDigest .encode (
1369+ client_nonce = client_nonce ,
1370+ password = typing .cast (bytes , self .password ),
1371+ salt = salt ,
1372+ algo_name = algo_names [algo ],
1373+ server_nonce = server_nonce ,
1374+ )
1375+
1376+ _logger .debug ("Password(extensible digest)" )
1377+
1378+ self ._write (b"d" )
1379+ self ._write (i_pack (4 + 4 + len (digest ) + 4 + len (client_nonce )))
1380+ self ._write (i_pack (len (digest )))
1381+ self ._write (digest )
1382+ self ._write (i_pack (len (client_nonce )))
1383+ self ._write (client_nonce )
1384+ self ._flush ()
1385+
13311386 elif auth_code in (2 , 4 , 6 , 7 , 8 , 9 ):
13321387 raise InterfaceError ("Authentication method " + str (auth_code ) + " not supported by redshift_connector." )
13331388 else :
0 commit comments