From dc2d2ad467927affbd1461df75f77f07ddfbc3b1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 15 Aug 2003 02:57:59 +0000 Subject: [PATCH] Add the gss-spnego kerberos server side to ntml_auth. This uses the same ads_verify_ticket routine that smbd uses, so in the current state we have to be have the host password in secrets.tdb instead of the keytab. This means we have to be an ADS member, but it's a start. Volker --- source/Makefile.in | 7 ++-- source/libsmb/spnego.c | 14 ++++++++ source/utils/ntlm_auth.c | 78 ++++++++++++++++++++++++++++++++++------ 3 files changed, 87 insertions(+), 12 deletions(-) diff --git a/source/Makefile.in b/source/Makefile.in index ebf4c1abd52..4e3daa50a21 100644 --- a/source/Makefile.in +++ b/source/Makefile.in @@ -623,8 +623,11 @@ POPT_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \ TDBBACKUP_OBJ = tdb/tdbbackup.o tdb/tdbback.o $(TDBBASE_OBJ) -NTLM_AUTH_OBJ = utils/ntlm_auth.o $(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) \ - libsmb/asn1.o libsmb/spnego.o libsmb/clikrb5.o libads/kerberos.o +NTLM_AUTH_OBJ = utils/ntlm_auth.o $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) \ + libsmb/asn1.o libsmb/spnego.o libsmb/clikrb5.o libads/kerberos.o \ + libads/kerberos_verify.o passdb/secrets.o lib/server_mutex.o \ + libads/authdata.o rpc_parse/parse_prs.o rpc_parse/parse_misc.o \ + libsmb/doserr.o ###################################################################### # now the rules... diff --git a/source/libsmb/spnego.c b/source/libsmb/spnego.c index 0b2dec7ef84..50caf7b4c0e 100644 --- a/source/libsmb/spnego.c +++ b/source/libsmb/spnego.c @@ -140,8 +140,22 @@ static BOOL write_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token) /* write mechListMIC */ if (token->mechListMIC.data) { asn1_push_tag(asn1, ASN1_CONTEXT(3)); +#if 0 + /* This is what RFC 2478 says ... */ asn1_write_OctetString(asn1, token->mechListMIC.data, token->mechListMIC.length); +#else + /* ... but unfortunately this is what Windows + sends/expects */ + asn1_push_tag(asn1, ASN1_SEQUENCE(0)); + asn1_push_tag(asn1, ASN1_CONTEXT(0)); + asn1_push_tag(asn1, ASN1_GENERAL_STRING); + asn1_write(asn1, token->mechListMIC.data, + token->mechListMIC.length); + asn1_pop_tag(asn1); + asn1_pop_tag(asn1); + asn1_pop_tag(asn1); +#endif asn1_pop_tag(asn1); } diff --git a/source/utils/ntlm_auth.c b/source/utils/ntlm_auth.c index 19d485a9367..4ac125f317f 100644 --- a/source/utils/ntlm_auth.c +++ b/source/utils/ntlm_auth.c @@ -361,27 +361,35 @@ static void manage_squid_basic_request(enum squid_mode squid_mode, static void offer_gss_spnego_mechs(void) { DATA_BLOB token; - ASN1_DATA asn1; SPNEGO_DATA spnego; ssize_t len; char *reply_base64; + pstring principal; + pstring myname_lower; + ZERO_STRUCT(spnego); + pstrcpy(myname_lower, global_myname()); + strlower_m(myname_lower); + + pstr_sprintf(principal, "%s$@%s", myname_lower, lp_realm()); + /* Server negTokenInit (mech offerings) */ spnego.type = SPNEGO_NEG_TOKEN_INIT; - spnego.negTokenInit.mechTypes = smb_xmalloc(sizeof(char *) * 2); + spnego.negTokenInit.mechTypes = smb_xmalloc(sizeof(char *) * 3); +#ifdef HAVE_KRB5 + spnego.negTokenInit.mechTypes[0] = smb_xstrdup(OID_KERBEROS5_OLD); + spnego.negTokenInit.mechTypes[1] = smb_xstrdup(OID_NTLMSSP); + spnego.negTokenInit.mechTypes[2] = NULL; +#else spnego.negTokenInit.mechTypes[0] = smb_xstrdup(OID_NTLMSSP); spnego.negTokenInit.mechTypes[1] = NULL; +#endif - ZERO_STRUCT(asn1); - asn1_push_tag(&asn1, ASN1_SEQUENCE(0)); - asn1_push_tag(&asn1, ASN1_CONTEXT(0)); - asn1_write_GeneralString(&asn1, "NONE"); - asn1_pop_tag(&asn1); - asn1_pop_tag(&asn1); - spnego.negTokenInit.mechListMIC = data_blob(asn1.data, asn1.length); - asn1_free(&asn1); + + spnego.negTokenInit.mechListMIC = data_blob(principal, + strlen(principal)); len = write_spnego_data(&token, &spnego); free_spnego_data(&spnego); @@ -507,6 +515,56 @@ static void manage_gss_spnego_request(enum squid_mode squid_mode, &response.negTokenTarg.responseToken); } +#ifdef HAVE_KRB5 + if (strcmp(request.negTokenInit.mechTypes[0], OID_KERBEROS5_OLD) == 0) { + + char *principal; + DATA_BLOB auth_data; + DATA_BLOB ap_rep; + uint8 session_key[16]; + + if ( request.negTokenInit.mechToken.data == NULL ) { + DEBUG(1, ("Client did not provide Kerberos data\n")); + x_fprintf(x_stdout, "BH\n"); + return; + } + + response.type = SPNEGO_NEG_TOKEN_TARG; + response.negTokenTarg.supportedMech = strdup(OID_KERBEROS5_OLD); + response.negTokenTarg.mechListMIC = data_blob(NULL, 0); + response.negTokenTarg.responseToken = data_blob(NULL, 0); + + status = ads_verify_ticket(lp_realm(), + &request.negTokenInit.mechToken, + &principal, &auth_data, &ap_rep, + session_key); + + /* Now in "principal" we have the name we are + authenticated as. */ + + if (NT_STATUS_IS_OK(status)) { + + domain = strchr(principal, '@'); + + if (domain == NULL) { + DEBUG(1, ("Did not get a valid principal " + "from ads_verify_ticket\n")); + x_fprintf(x_stdout, "BH\n"); + return; + } + + *domain++ = '\0'; + domain = strdup(domain); + user = strdup(principal); + + data_blob_free(&ap_rep); + data_blob_free(&auth_data); + + SAFE_FREE(principal); + } + } +#endif + } else { if ( (request.negTokenTarg.supportedMech == NULL) ||