69
69
IPROTO_FEATURE_TRANSACTIONS ,
70
70
IPROTO_FEATURE_ERROR_EXTENSION ,
71
71
IPROTO_FEATURE_WATCHERS ,
72
+ IPROTO_AUTH_TYPE ,
72
73
IPROTO_CHUNK ,
74
+ AUTH_TYPE_CHAP_SHA1 ,
75
+ AUTH_TYPE_PAP_SHA256 ,
76
+ AUTH_TYPES ,
73
77
)
74
78
from tarantool .error import (
75
79
Error ,
@@ -574,7 +578,8 @@ def __init__(self, host, port,
574
578
ssl_password = DEFAULT_SSL_PASSWORD ,
575
579
ssl_password_file = DEFAULT_SSL_PASSWORD_FILE ,
576
580
packer_factory = default_packer_factory ,
577
- unpacker_factory = default_unpacker_factory ):
581
+ unpacker_factory = default_unpacker_factory ,
582
+ auth_type = None ):
578
583
"""
579
584
:param host: Server hostname or IP address. Use ``None`` for
580
585
Unix sockets.
@@ -723,6 +728,14 @@ def __init__(self, host, port,
723
728
callable[[:obj:`~tarantool.Connection`], :obj:`~msgpack.Unpacker`],
724
729
optional
725
730
731
+ :param auth_type: Authentication method: ``"chap-sha1"`` (supported in
732
+ Tarantool CE and EE) or ``"pap-sha256"`` (supported in Tarantool EE,
733
+ ``"ssl"`` :paramref:`~tarantool.Connection.transport` must be used).
734
+ If `None`, use authentication method provided by server in IPROTO_ID
735
+ exchange. If server does not provide an authentication method, use
736
+ ``"chap-sha1"``.
737
+ :type auth_type: :obj:`None` or :obj:`str`, optional
738
+
726
739
:raise: :exc:`~tarantool.error.ConfigurationError`,
727
740
:meth:`~tarantool.Connection.connect` exceptions
728
741
@@ -778,6 +791,8 @@ def __init__(self, host, port,
778
791
}
779
792
self ._packer_factory_impl = packer_factory
780
793
self ._unpacker_factory_impl = unpacker_factory
794
+ self ._client_auth_type = auth_type
795
+ self ._server_auth_type = None
781
796
782
797
if connect_now :
783
798
self .connect ()
@@ -985,6 +1000,7 @@ def handshake(self):
985
1000
if greeting .protocol != "Binary" :
986
1001
raise NetworkError ("Unsupported protocol: " + greeting .protocol )
987
1002
self .version_id = greeting .version_id
1003
+ self ._check_features ()
988
1004
self .uuid = greeting .uuid
989
1005
self ._salt = greeting .salt
990
1006
if self .user :
@@ -1008,7 +1024,6 @@ def connect(self):
1008
1024
self .wrap_socket_ssl ()
1009
1025
self .handshake ()
1010
1026
self .load_schema ()
1011
- self ._check_features ()
1012
1027
except SslError as e :
1013
1028
raise e
1014
1029
except Exception as e :
@@ -1390,13 +1405,44 @@ def authenticate(self, user, password):
1390
1405
if not self ._socket :
1391
1406
return self ._opt_reconnect ()
1392
1407
1393
- request = RequestAuthenticate (self , self ._salt , self .user ,
1394
- self .password )
1408
+ request = RequestAuthenticate (self ,
1409
+ salt = self ._salt ,
1410
+ user = self .user ,
1411
+ password = self .password ,
1412
+ auth_type = self ._get_auth_type ())
1395
1413
auth_response = self ._send_request_wo_reconnect (request )
1396
1414
if auth_response .return_code == 0 :
1397
1415
self .flush_schema ()
1398
1416
return auth_response
1399
1417
1418
+ def _get_auth_type (self ):
1419
+ """
1420
+ Get authentication method based on client and server settings.
1421
+
1422
+ :rtype: :obj:`str`
1423
+
1424
+ :raise: :exc:`~tarantool.error.DatabaseError`
1425
+
1426
+ :meta private:
1427
+ """
1428
+
1429
+ if self ._client_auth_type is None :
1430
+ if self ._server_auth_type is None :
1431
+ auth_type = AUTH_TYPE_CHAP_SHA1
1432
+ else :
1433
+ if self ._server_auth_type not in AUTH_TYPES :
1434
+ raise ConfigurationError (f'Unknown server authentication type { self ._server_auth_type } ' )
1435
+ auth_type = self ._server_auth_type
1436
+ else :
1437
+ if self ._client_auth_type not in AUTH_TYPES :
1438
+ raise ConfigurationError (f'Unknown client authentication type { self ._client_auth_type } ' )
1439
+ auth_type = self ._client_auth_type
1440
+
1441
+ if auth_type == AUTH_TYPE_PAP_SHA256 and self .transport != SSL_TRANSPORT :
1442
+ raise ConfigurationError ('Use PAP-SHA256 only with ssl transport' )
1443
+
1444
+ return auth_type
1445
+
1400
1446
def _join_v16 (self , server_uuid ):
1401
1447
"""
1402
1448
Execute a JOIN request for Tarantool 1.6 and older.
@@ -2037,11 +2083,13 @@ def _check_features(self):
2037
2083
response = self ._send_request (request )
2038
2084
server_protocol_version = response .protocol_version
2039
2085
server_features = response .features
2086
+ server_auth_type = response .auth_type
2040
2087
except DatabaseError as exc :
2041
2088
ER_UNKNOWN_REQUEST_TYPE = 48
2042
2089
if exc .code == ER_UNKNOWN_REQUEST_TYPE :
2043
2090
server_protocol_version = None
2044
2091
server_features = []
2092
+ server_auth_type = None
2045
2093
else :
2046
2094
raise exc
2047
2095
@@ -2054,6 +2102,8 @@ def _check_features(self):
2054
2102
for val in features_list :
2055
2103
self ._features [val ] = True
2056
2104
2105
+ self ._server_auth_type = server_auth_type
2106
+
2057
2107
def _packer_factory (self ):
2058
2108
return self ._packer_factory_impl (self )
2059
2109
0 commit comments