From c0bea2aeb36d4a6b7ed8240d3ed479b2c5c34a16 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 11 Sep 2004 23:09:26 +0000 Subject: r2286: Fixes towards krb5 logins into Samba's CIFS server. These fixes aim particularly at allowing PAC-less logins, as I don't yet generate a PAC in the lorikeet-heimdal KDC. This is for the benifit of a Kerbeors-enabled domain join, which seems to be progressing quite well! Andrew Bartlett (This used to be commit f5a381094dd5bcbd795a134bc4b8b89901b5e3eb) --- source4/libcli/auth/clikrb5.c | 15 ++-- source4/libcli/auth/gensec_krb5.c | 164 ++++++++++++++++++---------------- source4/libcli/auth/kerberos.h | 4 +- source4/libcli/auth/kerberos_verify.c | 19 +++- 4 files changed, 113 insertions(+), 89 deletions(-) (limited to 'source4/libcli/auth') diff --git a/source4/libcli/auth/clikrb5.c b/source4/libcli/auth/clikrb5.c index f6f8520b3c..78492d2352 100644 --- a/source4/libcli/auth/clikrb5.c +++ b/source4/libcli/auth/clikrb5.c @@ -150,18 +150,23 @@ } #endif - void get_auth_data_from_tkt(TALLOC_CTX *mem_ctx, - DATA_BLOB *auth_data, krb5_ticket *tkt) + DATA_BLOB get_auth_data_from_tkt(TALLOC_CTX *mem_ctx, + krb5_ticket *tkt) { + DATA_BLOB auth_data = data_blob(NULL, 0); #if defined(HAVE_KRB5_TKT_ENC_PART2) - if (tkt && tkt->enc_part2) - *auth_data = data_blob(tkt->enc_part2->authorization_data[0]->contents, + if (tkt && tkt->enc_part2 + && tkt->enc_part2->authorization_data + && tkt->enc_part2->authorization_data[0] + && tkt->enc_part2->authorization_data[0]->length) + auth_data = data_blob(tkt->enc_part2->authorization_data[0]->contents, tkt->enc_part2->authorization_data[0]->length); #else if (tkt && tkt->ticket.authorization_data && tkt->ticket.authorization_data->len) - *auth_data = data_blob(tkt->ticket.authorization_data->val->ad_data.data, + auth_data = data_blob(tkt->ticket.authorization_data->val->ad_data.data, tkt->ticket.authorization_data->val->ad_data.length); #endif + return auth_data; } krb5_const_principal get_principal_from_tkt(krb5_ticket *tkt) diff --git a/source4/libcli/auth/gensec_krb5.c b/source4/libcli/auth/gensec_krb5.c index 569fd81206..4a97d51c40 100644 --- a/source4/libcli/auth/gensec_krb5.c +++ b/source4/libcli/auth/gensec_krb5.c @@ -38,13 +38,14 @@ enum GENSEC_KRB5_STATE { struct gensec_krb5_state { TALLOC_CTX *mem_ctx; DATA_BLOB session_key; - struct PAC_LOGON_INFO logon_info; + struct PAC_LOGON_INFO *logon_info; enum GENSEC_KRB5_STATE state_position; krb5_context krb5_context; krb5_auth_context krb5_auth_context; krb5_ccache krb5_ccache; krb5_data ticket; krb5_keyblock krb5_keyblock; + char *peer_principal; }; #ifdef KRB5_DO_VERIFY_PAC @@ -56,6 +57,7 @@ static NTSTATUS gensec_krb5_pac_checksum(DATA_BLOB pac_data, krb5_error_code ret; krb5_crypto crypto; Checksum cksum; + int i; cksum.cksumtype = (CKSUMTYPE)sig->type; cksum.checksum.length = sizeof(sig->signature); @@ -70,21 +72,19 @@ static NTSTATUS gensec_krb5_pac_checksum(DATA_BLOB pac_data, DEBUG(0,("krb5_crypto_init() failed\n")); return NT_STATUS_FOOBAR; } -{ -int i; -for (i=0; i < 40; i++) { - keyusage = i; - ret = krb5_verify_checksum(gensec_krb5_state->krb5_context, - crypto, - keyusage, - pac_data.data, - pac_data.length, - &cksum); - if (!ret) { - DEBUG(0,("PAC Verified: keyusage: %d\n", keyusage)); - break; + for (i=0; i < 40; i++) { + keyusage = i; + ret = krb5_verify_checksum(gensec_krb5_state->krb5_context, + crypto, + keyusage, + pac_data.data, + pac_data.length, + &cksum); + if (!ret) { + DEBUG(0,("PAC Verified: keyusage: %d\n", keyusage)); + break; + } } -}} krb5_crypto_destroy(gensec_krb5_state->krb5_context, crypto); if (ret) { @@ -99,7 +99,7 @@ for (i=0; i < 40; i++) { #endif static NTSTATUS gensec_krb5_decode_pac(TALLOC_CTX *mem_ctx, - struct PAC_LOGON_INFO *logon_info_out, + struct PAC_LOGON_INFO **logon_info_out, DATA_BLOB blob, struct gensec_krb5_state *gensec_krb5_state) { @@ -220,7 +220,7 @@ static NTSTATUS gensec_krb5_decode_pac(TALLOC_CTX *mem_ctx, } #endif DEBUG(0,("account_name: %s [%s]\n",logon_info->account_name.string, logon_info->full_name.string)); - *logon_info_out = *logon_info; + *logon_info_out = logon_info; return status; } @@ -542,16 +542,22 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security, TALL return nt_status; } - /* decode and verify the pac */ - nt_status = gensec_krb5_decode_pac(gensec_krb5_state->mem_ctx, &gensec_krb5_state->logon_info, pac, - gensec_krb5_state); + if (pac.data) { + /* decode and verify the pac */ + nt_status = gensec_krb5_decode_pac(gensec_krb5_state->mem_ctx, &gensec_krb5_state->logon_info, pac, + gensec_krb5_state); + } else { + /* NULL PAC, we might need to figure this information out the hard way */ + gensec_krb5_state->logon_info = NULL; + } if (NT_STATUS_IS_OK(nt_status)) { gensec_krb5_state->state_position = GENSEC_KRB5_DONE; /* wrap that up in a nice GSS-API wrapping */ *out = gensec_gssapi_gen_krb5_wrap(out_mem_ctx, &unwrapped_out, TOK_ID_KRB_AP_REP); + + gensec_krb5_state->peer_principal = talloc_steal(gensec_krb5_state->mem_ctx, principal); } - SAFE_FREE(principal); return nt_status; } case GENSEC_KRB5_DONE: @@ -597,88 +603,88 @@ static NTSTATUS gensec_krb5_session_key(struct gensec_security *gensec_security, return NT_STATUS_NO_USER_SESSION_KEY; } } -/* -struct gensec_krb5_state { - TALLOC_CTX *mem_ctx; - DATA_BLOB session_key; - struct PAC_LOGON_INFO logon_info; - enum GENSEC_KRB5_STATE state_position; - krb5_context krb5_context; - krb5_auth_context krb5_auth_context; - krb5_ccache krb5_ccache; - krb5_data ticket; - krb5_keyblock krb5_keyblock; -}; -struct auth_session_info -{ - TALLOC_CTX *mem_ctx; - int refcount; - - NT_USER_TOKEN *nt_user_token; - - struct auth_serversupplied_info *server_info; - - DATA_BLOB session_key; - - const char *workstation; -}; -*/ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security, struct auth_session_info **session_info_out) { + NTSTATUS nt_status; struct gensec_krb5_state *gensec_krb5_state = gensec_security->private_data; TALLOC_CTX *mem_ctx; + struct auth_serversupplied_info *server_info = NULL; struct auth_session_info *session_info = NULL; - struct PAC_LOGON_INFO *logon_info = &gensec_krb5_state->logon_info; + struct PAC_LOGON_INFO *logon_info = gensec_krb5_state->logon_info; struct nt_user_token *ptoken; struct dom_sid *sid; + char *p; + char *principal; *session_info_out = NULL; - mem_ctx = talloc_init("krb5: session_info"); - - session_info = talloc_p(mem_ctx, struct auth_session_info); - if (!session_info) { - return NT_STATUS_NO_MEMORY; - } - - session_info->mem_ctx = mem_ctx; - session_info->refcount = 1; - session_info->server_info = NULL; - - ptoken = talloc_p(session_info->mem_ctx, struct nt_user_token); - if (!ptoken) { - return NT_STATUS_NO_MEMORY; + nt_status = make_server_info(&server_info, gensec_krb5_state->peer_principal); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; } - ptoken->num_sids = 0; + server_info->guest = False; - ptoken->user_sids = talloc_array_p(mem_ctx, struct dom_sid*, logon_info->groups_count + 2); - if (!ptoken->user_sids) { + principal = talloc_strdup(server_info->mem_ctx, gensec_krb5_state->peer_principal); + p = strchr(principal, '@'); + if (p) { + *p = '\0'; + } + server_info->account_name = principal; + server_info->domain = talloc_strdup(server_info->mem_ctx, p++); + if (!server_info->domain) { + free_server_info(&server_info); return NT_STATUS_NO_MEMORY; } + nt_status = make_session_info(server_info, &session_info); + if (!NT_STATUS_IS_OK(nt_status)) { + free_server_info(&server_info); + return nt_status; + } - sid = dom_sid_dup(session_info->mem_ctx, logon_info->dom_sid); - ptoken->user_sids[0] = dom_sid_add_rid(session_info->mem_ctx, sid, logon_info->user_rid); - ptoken->num_sids++; - sid = dom_sid_dup(session_info->mem_ctx, logon_info->dom_sid); - ptoken->user_sids[1] = dom_sid_add_rid(session_info->mem_ctx, sid, logon_info->group_rid); - ptoken->num_sids++; + /* IF we have the PAC - otherwise (TODO) we need to get this + * data from elsewere - local ldb, or lookup of some + * kind... */ - for (;ptoken->num_sids < logon_info->groups_count; ptoken->num_sids++) { + if (logon_info) { + ptoken = talloc_p(session_info->mem_ctx, struct nt_user_token); + if (!ptoken) { + return NT_STATUS_NO_MEMORY; + } + + ptoken->num_sids = 0; + + ptoken->user_sids = talloc_array_p(mem_ctx, struct dom_sid*, logon_info->groups_count + 2); + if (!ptoken->user_sids) { + return NT_STATUS_NO_MEMORY; + } + + + sid = dom_sid_dup(session_info->mem_ctx, logon_info->dom_sid); + ptoken->user_sids[0] = dom_sid_add_rid(session_info->mem_ctx, sid, logon_info->user_rid); + ptoken->num_sids++; sid = dom_sid_dup(session_info->mem_ctx, logon_info->dom_sid); - ptoken->user_sids[ptoken->num_sids] = dom_sid_add_rid(session_info->mem_ctx, sid, logon_info->groups[ptoken->num_sids - 2].rid); + ptoken->user_sids[1] = dom_sid_add_rid(session_info->mem_ctx, sid, logon_info->group_rid); + ptoken->num_sids++; + + for (;ptoken->num_sids < logon_info->groups_count; ptoken->num_sids++) { + sid = dom_sid_dup(session_info->mem_ctx, logon_info->dom_sid); + ptoken->user_sids[ptoken->num_sids] = dom_sid_add_rid(session_info->mem_ctx, sid, logon_info->groups[ptoken->num_sids - 2].rid); + } + + debug_nt_user_token(DBGC_AUTH, 0, ptoken); + + session_info->nt_user_token = ptoken; + } else { + session_info->nt_user_token = NULL; } - - debug_nt_user_token(DBGC_AUTH, 0, ptoken); - - session_info->nt_user_token = ptoken; session_info->session_key = data_blob_talloc(session_info->mem_ctx, - gensec_krb5_state->session_key.data, - gensec_krb5_state->session_key.length); + gensec_krb5_state->session_key.data, + gensec_krb5_state->session_key.length); session_info->workstation = NULL; diff --git a/source4/libcli/auth/kerberos.h b/source4/libcli/auth/kerberos.h index e35079a4ee..9d6a5e81ae 100644 --- a/source4/libcli/auth/kerberos.h +++ b/source4/libcli/auth/kerberos.h @@ -65,8 +65,8 @@ krb5_error_code ads_krb5_mk_req(krb5_context context, const char *principal, krb5_ccache ccache, krb5_data *outbuf); -void get_auth_data_from_tkt(TALLOC_CTX *mem_ctx, - DATA_BLOB *auth_data, krb5_ticket *tkt); +DATA_BLOB get_auth_data_from_tkt(TALLOC_CTX *mem_ctx, + krb5_ticket *tkt); NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx, krb5_context context, krb5_auth_context auth_context, diff --git a/source4/libcli/auth/kerberos_verify.c b/source4/libcli/auth/kerberos_verify.c index 88bf391cfa..843189c884 100644 --- a/source4/libcli/auth/kerberos_verify.c +++ b/source4/libcli/auth/kerberos_verify.c @@ -32,6 +32,9 @@ static DATA_BLOB unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data) DATA_BLOB pac_contents = data_blob(NULL, 0); ASN1_DATA data; int data_type; + if (!auth_data->length) { + return data_blob(NULL, 0); + } asn1_load(&data, *auth_data); asn1_start_tag(&data, ASN1_SEQUENCE(0)); @@ -95,7 +98,7 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut goto out; } /* Look for a CIFS ticket */ - if (!StrnCaseCmp(princ_name, "cifs/", 5)) { + if (!StrnCaseCmp(princ_name, "cifs/", 5) || (!StrnCaseCmp(princ_name, "host/", 5))) { #ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK krb5_auth_con_setuseruserkey(context, auth_context, &kt_entry.keyblock); #else @@ -254,6 +257,8 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au char *myname; BOOL auth_ok = False; + char *malloc_principal; + ZERO_STRUCT(packet); ZERO_STRUCTP(auth_data); ZERO_STRUCTP(ap_rep); @@ -329,7 +334,7 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au file_save("/tmp/ticket.dat", ticket->data, ticket->length); #endif - get_auth_data_from_tkt(mem_ctx, auth_data, tkt); + *auth_data = get_auth_data_from_tkt(mem_ctx, tkt); *auth_data = unwrap_pac(mem_ctx, auth_data); @@ -342,13 +347,21 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au #endif if ((ret = krb5_unparse_name(context, get_principal_from_tkt(tkt), - principal))) { + &malloc_principal))) { DEBUG(3,("ads_verify_ticket: krb5_unparse_name failed (%s)\n", error_message(ret))); sret = NT_STATUS_LOGON_FAILURE; goto out; } + *principal = talloc_strdup(mem_ctx, malloc_principal); + SAFE_FREE(malloc_principal); + if (!principal) { + DEBUG(3,("ads_verify_ticket: talloc_strdup() failed\n")); + sret = NT_STATUS_NO_MEMORY; + goto out; + } + sret = NT_STATUS_OK; out: -- cgit