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?