def sasl_gssapi(connection, controls): """ Performs a bind using the Kerberos v5 ("GSSAPI") SASL mechanism from RFC 4752. Does not support any security layers, only authentication! """ NO_SECURITY_LAYER = 1 INTEGRITY_PROTECTION = 2 CONFIDENTIALITY_PROTECTION = 4 authz_id = b'' krb5mech = gssapi.OID.mech_from_string() target_name = gssapi.Name('ldap@' + connection.server.host, gssapi.C_NT_HOSTBASED_SERVICE) ctx_kwargs = { 'mech_type': krb5mech, 'req_flags': (gssapi.C_INTEG_FLAG,) } if ( isinstance(connection.sasl_credentials, (list, tuple)) and len(connection.sasl_credentials) == 2 ): # connection.sasl_credentials can be a 2-tuple. The first element can be a # gssapi.Credential to use as the initiator credential. The second can be an authorization ID. # Either can be None if the default credential, or no authorization ID is to be used. if isinstance(connection.sasl_credentials[0], gssapi.Credential): ctx_kwargs['cred'] = connection.sasl_credentials if connection.sasl_credentials[1] is not None: authz_id = connection.sasl_credentials[1].encode('utf-8') ctx = gssapi.InitContext(target_name, **ctx_kwargs) in_token = None try: while not ctx.established: # Client calls init_sec_context... out_token = ctx.step(in_token) if out_token is None: out_token = b'' # and sends the server the result result = send_sasl_negotiation(connection, controls, out_token) in_token = result['saslCreds'] # once the Context is established, decode the server's token unwrapped_token = ctx.unwrap(in_token, conf_req=False) if len(unwrapped_token) != 4: raise ValueError("Incorrect response from server.") server_security_layers = ord(unwrapped_token[0]) if server_security_layers in (0, NO_SECURITY_LAYER): if unwrapped_token[1:] != b'\x00\x00\x00': raise ValueError("Server max buffer size must be 0 if no security layer.") if not (server_security_layers & NO_SECURITY_LAYER): raise ValueError("Server requires a security layer, but we don't support any.") client_security_layers = bytearray([NO_SECURITY_LAYER, 0, 0, 0]) out_token = ctx.wrap(bytes(client_security_layers) + authz_id, conf_req=False) return send_sasl_negotiation(connection, controls, out_token) except (gssapi.GSSException, ValueError) as exc: abort_sasl_negotiation(connection, controls) raise
def sasl_gssapi(connection, controls): print('MONKEY!') print(connection) print(controls) target_name = None authz_id = b"" raw_creds = None creds = None if connection.sasl_credentials: if len(connection.sasl_credentials ) >= 1 and connection.sasl_credentials[0]: if connection.sasl_credentials[0] is True: hostname = socket.gethostbyaddr( connection.socket.getpeername()[0])[0] target_name = 'ldap@' + hostname else: target_name = 'ldap@' + connection.sasl_credentials[0] if len(connection.sasl_credentials ) >= 2 and connection.sasl_credentials[1]: authz_id = connection.sasl_credentials[1].encode("utf-8") if len(connection.sasl_credentials ) >= 3 and connection.sasl_credentials[2]: raw_creds = connection.sasl_credentials[2] if target_name is None: target_name = 'ldap@' + connection.server.host print('target_name : %s' % target_name) print('authz_id : %s' % authz_id) print('raw_creds : %s' % raw_creds) target = 'ldap/WIN2019AD.test.corp' #target = target_name ksspi = KerberosSSPI(target) in_token = None res = None #while True: #result = send_sasl_negotiation(connection, controls, '') while res != SSPIResult.OK: res, out_token = ksspi.init_ctx(in_token) print(out_token) result = send_sasl_negotiation(connection, controls, out_token) in_token = result['saslCreds'] print(in_token)
def sasl_gssapi(connection, controls): """ Performs a bind using the Kerberos v5 ("GSSAPI") SASL mechanism from RFC 4752. Does not support any security layers, only authentication! sasl_credentials can be empty or a 1-element tuple with the requested target_name or the True value to request the target_name from DNS """ if connection.sasl_credentials and len(connection.sasl_credentials) == 1 \ and connection.sasl_credentials[0]: if connection.sasl_credentials[0] is True: hostname = \ socket.gethostbyaddr(connection.socket.getpeername()[0])[0] target_name = 'ldap@' + hostname else: target_name = connection.sasl_credentials[0] else: target_name = 'ldap@' + connection.server.host gssflags = (kerberos.GSS_C_MUTUAL_FLAG | kerberos.GSS_C_SEQUENCE_FLAG | kerberos.GSS_C_INTEG_FLAG | kerberos.GSS_C_CONF_FLAG) _, ctx = kerberos.authGSSClientInit(target_name, gssflags=gssflags) try: in_token = b'' while True: status = kerberos.authGSSClientStep( ctx, base64.b64encode(in_token).decode('ascii')) out_token = kerberos.authGSSClientResponse(ctx) or '' result = send_sasl_negotiation(connection, controls, base64.b64decode(out_token)) in_token = result['saslCreds'] or b'' if status == kerberos.AUTH_GSS_COMPLETE: break kerberos.authGSSClientUnwrap( ctx, base64.b64encode(in_token).decode('ascii')) unwrapped_token = base64.b64decode( kerberos.authGSSClientResponse(ctx) or '') if len(unwrapped_token) != 4: raise LDAPCommunicationError('Incorrect response from server') server_security_layers = unwrapped_token[0] if not isinstance(server_security_layers, int): server_security_layers = ord(server_security_layers) if not server_security_layers & NO_SECURITY_LAYER: raise LDAPCommunicationError( 'Server requires a security layer, but this is not implemented' ) client_security_layers = bytearray([NO_SECURITY_LAYER, 0, 0, 0]) kerberos.authGSSClientWrap( ctx, base64.b64encode(client_security_layers).decode('ascii')) out_token = kerberos.authGSSClientResponse(ctx) or '' return send_sasl_negotiation(connection, controls, base64.b64decode(out_token)) except (kerberos.GSSError, LDAPCommunicationError): abort_sasl_negotiation(connection, controls) raise
def sasl_gssapi(connection, controls): """ Performs a bind using the Kerberos v5 ("GSSAPI") SASL mechanism from RFC 4752. Does not support any security layers, only authentication! sasl_credentials can be empty or a tuple with one or two elements. The first element determines which service principal to request a ticket for and can be one of the following: - None or False, to use the hostname from the Server object - True to perform a reverse DNS lookup to retrieve the canonical hostname for the hosts IP address - A string containing the hostname The optional second element is what authorization ID to request. - If omitted or None, the authentication ID is used as the authorization ID - If a string, the authorization ID to use. Should start with "dn:" or "user:"******""" # pylint: disable=too-many-branches target_name = None authz_id = b'' if connection.sasl_credentials: if (len(connection.sasl_credentials) >= 1 and connection.sasl_credentials[0]): if connection.sasl_credentials[0] is True: hostname = \ socket.gethostbyaddr(connection.socket.getpeername()[0])[0] target_name = 'ldap@' + hostname else: target_name = 'ldap@' + connection.sasl_credentials[0] if (len(connection.sasl_credentials) >= 2 and connection.sasl_credentials[1]): authz_id = connection.sasl_credentials[1].encode("utf-8") if target_name is None: target_name = 'ldap@' + connection.server.host gssflags = (kerberos.GSS_C_MUTUAL_FLAG | kerberos.GSS_C_SEQUENCE_FLAG | kerberos.GSS_C_INTEG_FLAG | kerberos.GSS_C_CONF_FLAG) channel_bindings = get_channel_bindings(connection.socket) _, ctx = kerberos.authGSSClientInit(target_name, gssflags=gssflags) in_token = b'' try: while True: if channel_bindings: status = kerberos.authGSSClientStep( ctx, base64.b64encode(in_token).decode('ascii'), channel_bindings=channel_bindings) else: status = kerberos.authGSSClientStep( ctx, base64.b64encode(in_token).decode('ascii')) out_token = kerberos.authGSSClientResponse(ctx) or '' result = send_sasl_negotiation(connection, controls, base64.b64decode(out_token)) in_token = result['saslCreds'] or b'' if status == kerberos.AUTH_GSS_COMPLETE: break kerberos.authGSSClientUnwrap( ctx, base64.b64encode(in_token).decode('ascii')) unwrapped_token = base64.b64decode( kerberos.authGSSClientResponse(ctx) or '') if len(unwrapped_token) != 4: raise LDAPCommunicationError('Incorrect response from server') server_security_layers = unwrapped_token[0] if not isinstance(server_security_layers, int): server_security_layers = ord(server_security_layers) if server_security_layers in (0, NO_SECURITY_LAYER): if unwrapped_token.message[1:] != '\x00\x00\x00': raise LDAPCommunicationError( 'Server max buffer size must be 0 if no security layer') if not server_security_layers & NO_SECURITY_LAYER: raise LDAPCommunicationError( 'Server requires a security layer, but this is not implemented' ) client_security_layers = bytearray([NO_SECURITY_LAYER, 0, 0, 0]) kerberos.authGSSClientWrap( ctx, base64.b64encode(bytes(client_security_layers) + authz_id).decode('ascii')) out_token = kerberos.authGSSClientResponse(ctx) or '' return send_sasl_negotiation(connection, controls, base64.b64decode(out_token)) except (kerberos.GSSError, LDAPCommunicationError): abort_sasl_negotiation(connection, controls) raise