[Python] How I can generate correct SPNEGO token from existing kerberos token using pyspnego?

Discussão em 'Python' iniciado por Stack, Julho 5, 2025.

  1. Stack

    Stack Membro Participativo

    I am trying to solve the problem of accessing a service (HTTP) using the kerberos constrained delegation mechanism. It seems that I am forming the kerberos ticket correctly, but at the same time looking at its ASN.1 format, I do not find support for the SPNEGO mechanism. and the server cannot recognize this ticket, when it is transmitted in the Authorization:Negotiate header. I tried using the pyspnego library, but apparently I'm not an expert in it.

    import gssapi
    from gssapi import RequirementFlag, MechType
    import os
    import base64
    import requests
    import argparse
    import gssapi.raw as gssapi_raw
    import spnego

    # parse argument
    parser = argparse.ArgumentParser()
    parser.add_argument('client_user', help='Client user principal')
    args = parser.parse_args()

    #Settings

    realm = "REGION.INTRA.NET"
    keytab = "/etc/httpd/conf.d/t_hrkrbtest.keytab"
    server_principal = 'HOST/t_hrkrbtest.' + realm.lower() + '@' + realm
    client_user = args.client_user # Use receive arg
    target_service = 'HTTP/sap3.' + realm.lower() + '@' + realm

    #Set keytab

    os.environ["KRB5_KTNAME"] = keytab

    # === Exist keytab ===

    if not os.path.exists(keytab):
    raise FileNotFoundError(f"Keytab not found: {keytab}")

    #print(">>> Check principals in keytab:")
    kt = gssapi_raw.acquire_cred_from({
    'keytab': keytab.encode('utf-8')
    }, usage='accept')
    #print("Principal:", kt[0])


    try:
    server_name = gssapi.Name(server_principal, name_type=gssapi.NameType.kerberos_principal)
    creds = gssapi.Credentials(name=server_name, usage="initiate")

    except Exception as e:
    print(f"Error getting TGT from keytab: {e}")
    exit(1)

    #print(">>> S4U2Self")

    try:
    user_name = gssapi.Name(client_user, name_type=gssapi.NameType.kerberos_principal)
    creds = gssapi.Credentials(usage='initiate')
    impersonated_creds = creds.impersonate(user_name)
    # print(f"Success S4U2Self {client_user}")

    except Exception as e:
    print(f"Error S4U2Self: {e}")

    try:
    target_name = gssapi.Name(target_service, name_type=gssapi.NameType.kerberos_principal)

    # ctx = gssapi.SecurityContext(name=target_name, creds=impersonated_creds, mech=MechType.kerberos, flags=RequirementFlag.delegate_to_peer |
    # RequirementFlag.identify |
    # RequirementFlag.mutual_authentication, usage="initiate")
    ctx = gssapi.SecurityContext(name=target_name, creds=impersonated_creds, mech=MechType.kerberos, usage="initiate")
    token = ctx.step()
    ctx1 = spnego.client(hostname="sap3.intra.net", service="HTTP", protocol="negotiate")
    out_token = ctx1.step(token)

    b64_ticket = base64.b64encode(out_token).decode('utf-8')
    print(b64_ticket)

    except Exception as e:
    print(f"Error S4U2Proxy: {e}")
    exit(1)


    How can I add the SPNEGO mechanism to the token in the current ticket?

    Continue reading...

Compartilhe esta Página