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
Exemple #4
0
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