The Samba-Bugzilla – Attachment 1461 Details for
Bug 2804
SID missmatch with share perms set from windows
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Use Kerberos PAC to build NT Token
samba3-pac.diffv9 (text/plain), 59.55 KB, created by
Guenther Deschner
on 2005-09-28 03:53:21 UTC
(
hide
)
Description:
Use Kerberos PAC to build NT Token
Filename:
MIME Type:
Creator:
Guenther Deschner
Created:
2005-09-28 03:53:21 UTC
Size:
59.55 KB
patch
obsolete
>Index: Makefile.in >=================================================================== >--- Makefile.in (revision 10425) >+++ Makefile.in (working copy) >@@ -715,7 +715,7 @@ > libsmb/asn1.o libsmb/spnego.o libsmb/clikrb5.o libads/kerberos.o \ > libads/kerberos_verify.o $(SECRETS_OBJ) $(SERVER_MUTEX_OBJ) \ > libads/authdata.o $(RPC_PARSE_OBJ0) $(PASSDB_OBJ) $(GROUPDB_OBJ) \ >- $(SMBLDAP_OBJ) $(DOSERR_OBJ) >+ $(SMBLDAP_OBJ) $(DOSERR_OBJ) rpc_parse/parse_net.o > > ###################################################################### > # now the rules... >Index: smbd/sesssetup.c >=================================================================== >--- smbd/sesssetup.c (revision 10425) >+++ smbd/sesssetup.c (working copy) >@@ -139,6 +139,7 @@ > int length, int bufsize, > DATA_BLOB *secblob) > { >+ TALLOC_CTX *mem_ctx; > DATA_BLOB ticket; > char *client, *p, *domain; > fstring netbios_domain_name; >@@ -146,7 +147,7 @@ > fstring user; > int sess_vuid; > NTSTATUS ret; >- DATA_BLOB auth_data; >+ PAC_DATA *pac_data; > DATA_BLOB ap_rep, ap_rep_wrapped, response; > auth_serversupplied_info *server_info = NULL; > DATA_BLOB session_key = data_blob(NULL, 0); >@@ -154,18 +155,24 @@ > DATA_BLOB nullblob = data_blob(NULL, 0); > fstring real_username; > BOOL map_domainuser_to_guest = False; >+ PAC_LOGON_INFO *logon_info = NULL; >+ int i; > > ZERO_STRUCT(ticket); >- ZERO_STRUCT(auth_data); >+ ZERO_STRUCT(pac_data); > ZERO_STRUCT(ap_rep); > ZERO_STRUCT(ap_rep_wrapped); > ZERO_STRUCT(response); > >+ mem_ctx = talloc_init("reply_spnego_kerberos"); >+ if (mem_ctx == NULL) >+ return ERROR_NT(NT_STATUS_NO_MEMORY); >+ > if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) { > return ERROR_NT(NT_STATUS_LOGON_FAILURE); > } > >- ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, &session_key); >+ ret = ads_verify_ticket(mem_ctx, lp_realm(), &ticket, &client, &pac_data, &ap_rep, &session_key); > > data_blob_free(&ticket); > >@@ -174,8 +181,19 @@ > return ERROR_NT(NT_STATUS_LOGON_FAILURE); > } > >- data_blob_free(&auth_data); >+ if (pac_data) { > >+ /* get the logon_info */ >+ for (i=0; i < pac_data->num_buffers; i++) { >+ >+ if (pac_data->pac_buffer[i].type != PAC_TYPE_LOGON_INFO) >+ continue; >+ >+ logon_info = pac_data->pac_buffer[i].ctr->pac.logon_info; >+ break; >+ } >+ } >+ > DEBUG(3,("Ticket name is [%s]\n", client)); > > p = strchr_m(client, '@'); >@@ -203,7 +221,14 @@ > > domain = p+1; > >- { >+ if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) { >+ >+ unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1); >+ domain = netbios_domain_name; >+ DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain)); >+ >+ } else { >+ > /* If we have winbind running, we can (and must) shorten the > username by using the short netbios name. Otherwise we will > have inconsistent user names. With Kerberos, we get the >@@ -231,7 +256,7 @@ > wb_response.data.domain_info.name); > domain = netbios_domain_name; > >- DEBUG(10, ("Mapped to [%s]\n", domain)); >+ DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain)); > } else { > DEBUG(3, ("Could not find short name -- winbind " > "not running?\n")); >@@ -274,8 +299,21 @@ > reload_services(True); > if ( map_domainuser_to_guest ) { > make_server_info_guest(&server_info); >+ } else if (logon_info) { >+ ret = make_server_info_pac(&server_info, real_username, pw, logon_info); >+ >+ if ( !NT_STATUS_IS_OK(ret) ) { >+ DEBUG(1,("make_server_info_pac failed!\n")); >+ SAFE_FREE(client); >+ data_blob_free(&ap_rep); >+ data_blob_free(&session_key); >+ passwd_free(&pw); >+ return ERROR_NT(ret); >+ } >+ > } else { > ret = make_server_info_pw(&server_info, real_username, pw); >+ > if ( !NT_STATUS_IS_OK(ret) ) { > DEBUG(1,("make_server_info_from_pw failed!\n")); > SAFE_FREE(client); >@@ -284,15 +322,17 @@ > passwd_free(&pw); > return ERROR_NT(ret); > } >+ >+ /* make_server_info_pw does not set the domain. Without this we end up >+ * with the local netbios name in substitutions for %D. */ >+ >+ if (server_info->sam_account != NULL) { >+ pdb_set_domain(server_info->sam_account, domain, PDB_SET); >+ } > } >- passwd_free(&pw); > >- /* make_server_info_pw does not set the domain. Without this we end up >- * with the local netbios name in substitutions for %D. */ > >- if (server_info->sam_account != NULL) { >- pdb_set_domain(server_info->sam_account, domain, PDB_SET); >- } >+ passwd_free(&pw); > > /* register_vuid keeps the server info */ > /* register_vuid takes ownership of session_key, no need to free after this. >@@ -339,6 +379,7 @@ > data_blob_free(&ap_rep); > data_blob_free(&ap_rep_wrapped); > data_blob_free(&response); >+ talloc_destroy(mem_ctx); > > return -1; /* already replied */ > } >Index: auth/auth_util.c >=================================================================== >--- auth/auth_util.c (revision 10425) >+++ auth/auth_util.c (working copy) >@@ -832,6 +832,61 @@ > } > > /*************************************************************************** >+ Make (and fill) a user_info struct from a Kerberos PAC logon_info by conversion >+ to a SAM_ACCOUNT >+***************************************************************************/ >+ >+NTSTATUS make_server_info_pac(auth_serversupplied_info **server_info, >+ char *unix_username, >+ struct passwd *pwd, >+ PAC_LOGON_INFO *logon_info) >+{ >+ NTSTATUS nt_status; >+ SAM_ACCOUNT *sampass = NULL; >+ DOM_SID user_sid, group_sid; >+ fstring dom_name; >+ >+ if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(&sampass, pwd))) { >+ return nt_status; >+ } >+ if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info))) { >+ return nt_status; >+ } >+ >+ /* only copy user_sid, group_sid and domain name out of the PAC for >+ * now, we will benefit from more later - Guenther */ >+ >+ sid_copy(&user_sid, &logon_info->info3.dom_sid.sid); >+ sid_append_rid(&user_sid, logon_info->info3.user_rid); >+ pdb_set_user_sid(sampass, &user_sid, PDB_SET); >+ >+ sid_copy(&group_sid, &logon_info->info3.dom_sid.sid); >+ sid_append_rid(&group_sid, logon_info->info3.group_rid); >+ pdb_set_group_sid(sampass, &group_sid, PDB_SET); >+ >+ unistr2_to_ascii(dom_name, &logon_info->info3.uni_logon_dom, -1); >+ pdb_set_domain(sampass, dom_name, PDB_SET); >+ >+ pdb_set_logon_count(sampass, logon_info->info3.logon_count, PDB_SET); >+ >+ (*server_info)->sam_account = sampass; >+ >+ if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, unix_username, >+ sampass, pwd->pw_uid, pwd->pw_gid))) >+ { >+ return nt_status; >+ } >+ >+ (*server_info)->unix_name = smb_xstrdup(unix_username); >+ >+ (*server_info)->sam_fill_level = SAM_FILL_ALL; >+ (*server_info)->uid = pwd->pw_uid; >+ (*server_info)->gid = pwd->pw_gid; >+ return nt_status; >+} >+ >+ >+/*************************************************************************** > Make (and fill) a user_info struct from a 'struct passwd' by conversion > to a SAM_ACCOUNT > ***************************************************************************/ >Index: auth/auth_winbind.c >=================================================================== >--- auth/auth_winbind.c (revision 10425) >+++ auth/auth_winbind.c (working copy) >@@ -38,7 +38,7 @@ > } > prs_copy_data_in(&ps, (char *)info3_ndr, len); > prs_set_offset(&ps,0); >- if (!net_io_user_info3("", info3, &ps, 1, 3)) { >+ if (!net_io_user_info3("", info3, &ps, 1, 3, False)) { > DEBUG(2, ("get_info3_from_ndr: could not parse info3 struct!\n")); > return NT_STATUS_UNSUCCESSFUL; > } >Index: nsswitch/winbindd_pam.c >=================================================================== >--- nsswitch/winbindd_pam.c (revision 10425) >+++ nsswitch/winbindd_pam.c (working copy) >@@ -37,7 +37,7 @@ > if (!prs_init(&ps, 256 /* Random, non-zero number */, mem_ctx, MARSHALL)) { > return NT_STATUS_NO_MEMORY; > } >- if (!net_io_user_info3("", info3, &ps, 1, 3)) { >+ if (!net_io_user_info3("", info3, &ps, 1, 3, False)) { > prs_mem_free(&ps); > return NT_STATUS_UNSUCCESSFUL; > } >Index: lib/time.c >=================================================================== >--- lib/time.c (revision 10425) >+++ lib/time.c (working copy) >@@ -783,6 +783,15 @@ > } > > /**************************************************************************** >+ Check if two NTTIMEs are the same. >+****************************************************************************/ >+ >+BOOL nt_time_equals(NTTIME *nt1, NTTIME *nt2) >+{ >+ return (nt1->high == nt2->high && nt1->low == nt2->low); >+} >+ >+/**************************************************************************** > Return a timeval difference in usec. > ****************************************************************************/ > >Index: libsmb/clikrb5.c >=================================================================== >--- libsmb/clikrb5.c (revision 10425) >+++ libsmb/clikrb5.c (working copy) >@@ -3,6 +3,8 @@ > simple kerberos5 routines for active directory > Copyright (C) Andrew Tridgell 2001 > Copyright (C) Luke Howard 2002-2003 >+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005 >+ Copyright (C) Guenther Deschner 2005 > > This program is free software; you can redistribute it and/or modify > it under the terms of the GNU General Public License as published by >@@ -186,17 +188,70 @@ > } > #endif > >- void get_auth_data_from_tkt(DATA_BLOB *auth_data, krb5_ticket *tkt) >+ BOOL get_auth_data_from_tkt(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, krb5_ticket *tkt) > { >+ DATA_BLOB auth_data_wrapped; >+ BOOL got_auth_data_pac = False; >+ int i; >+ > #if defined(HAVE_KRB5_TKT_ENC_PART2) >- if (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); >+ if (tkt->enc_part2 && tkt->enc_part2->authorization_data && >+ tkt->enc_part2->authorization_data[0] && >+ tkt->enc_part2->authorization_data[0]->length) >+ { >+ for (i = 0; tkt->enc_part2->authorization_data[i] != NULL; i++) { >+ >+ if (tkt->enc_part2->authorization_data[i]->ad_type != >+ KRB5_AUTHDATA_IF_RELEVANT) { >+ DEBUG(10,("get_auth_data_from_tkt: ad_type is %d\n", >+ kt->enc_part2->authorization_data[i]->ad_type)); >+ continue; >+ } >+ >+ auth_data_wrapped = data_blob(tkt->enc_part2->authorization_data[i]->contents, >+ tkt->enc_part2->authorization_data[i]->length); >+ >+ /* check if it is a PAC */ >+ got_auth_data_pac = unwrap_pac(mem_ctx, &auth_data_wrapped, auth_data); >+ data_blob_free(&auth_data_wrapped); >+ >+ if (!got_auth_data_pac) { >+ continue; >+ } >+ } >+ >+ return got_auth_data_pac; >+ } >+ > #else >- if (tkt->ticket.authorization_data && tkt->ticket.authorization_data->len) >- *auth_data = data_blob(tkt->ticket.authorization_data->val->ad_data.data, >- tkt->ticket.authorization_data->val->ad_data.length); >+ if (tkt->ticket.authorization_data && >+ tkt->ticket.authorization_data->len) >+ { >+ for (i = 0; i < tkt->ticket.authorization_data->len; i++) { >+ >+ if (tkt->ticket.authorization_data->val[i].ad_type != >+ KRB5_AUTHDATA_IF_RELEVANT) { >+ DEBUG(10,("get_auth_data_from_tkt: ad_type is %d\n", >+ tkt->ticket.authorization_data->val[i].ad_type)); >+ continue; >+ } >+ >+ auth_data_wrapped = data_blob(tkt->ticket.authorization_data->val[i].ad_data.data, >+ tkt->ticket.authorization_data->val[i].ad_data.length); >+ >+ /* check if it is a PAC */ >+ got_auth_data_pac = unwrap_pac(mem_ctx, &auth_data_wrapped, auth_data); >+ data_blob_free(&auth_data_wrapped); >+ >+ if (!got_auth_data_pac) { >+ continue; >+ } >+ } >+ >+ return got_auth_data_pac; >+ } > #endif >+ return False; > } > > krb5_const_principal get_principal_from_tkt(krb5_ticket *tkt) >@@ -550,6 +605,345 @@ > #endif > } > >+void smb_krb5_checksum_from_pac_sig(krb5_checksum *cksum, >+ PAC_SIGNATURE_DATA *sig) >+{ >+#ifdef HAVE_CHECKSUM_IN_KRB5_CHECKSUM >+ cksum->cksumtype = (krb5_cksumtype)sig->type; >+ cksum->checksum.length = sig->signature.buf_len; >+ cksum->checksum.data = sig->signature.buffer; >+#else >+ cksum->checksum_type = (krb5_cksumtype)sig->type; >+ cksum->length = sig->signature.buf_len; >+ cksum->contents = sig->signature.buffer; >+#endif >+} >+ >+krb5_error_code smb_krb5_verify_checksum(krb5_context context, >+ krb5_keyblock *keyblock, >+ krb5_keyusage usage, >+ krb5_checksum *cksum, >+ uint8 *data, >+ size_t length) >+{ >+ krb5_error_code ret; >+ >+ /* verify the checksum */ >+ >+ /* welcome to the wonderful world of samba's kerberos abstraction layer: >+ * >+ * function heimdal 0.6.1rc3 heimdal 0.7 MIT krb 1.4.2 >+ * ----------------------------------------------------------------------------- >+ * krb5_c_verify_checksum - works works >+ * krb5_verify_checksum works (6 args) works (6 args) broken (7 args) >+ */ >+ >+#if defined(HAVE_KRB5_C_VERIFY_CHECKSUM) >+ { >+ krb5_boolean checksum_valid = False; >+ krb5_data input; >+ >+ input.data = (char *)data; >+ input.length = length; >+ >+ ret = krb5_c_verify_checksum(context, >+ keyblock, >+ usage, >+ &input, >+ cksum, >+ &checksum_valid); >+ if (!checksum_valid) >+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; >+ } >+ >+#elif KRB5_VERIFY_CHECKSUM_ARGS == 6 && defined(HAVE_KRB5_CRYPTO_INIT) && defined(HAVE_KRB5_CRYPTO) && defined(HAVE_KRB5_CRYPTO_DESTROY) >+ >+ /* Warning: MIT's krb5_verify_checksum cannot be used as it will use a key >+ * without enctype and it ignores any key_usage types - Guenther */ >+ >+ { >+ >+ krb5_crypto crypto; >+ ret = krb5_crypto_init(context, >+ keyblock, >+ 0, >+ &crypto); >+ if (ret) { >+ DEBUG(0,("smb_krb5_verify_checksum: krb5_crypto_init() failed: %s\n", >+ error_message(ret))); >+ return ret; >+ } >+ >+ ret = krb5_verify_checksum(context, >+ crypto, >+ usage, >+ data, >+ length, >+ cksum); >+ >+ krb5_crypto_destroy(context, crypto); >+ } >+ >+#else >+#error UNKNOWN_KRB5_VERIFY_CHECKSUM_FUNCTION >+#endif >+ >+ return ret; >+} >+ >+time_t get_authtime_from_tkt(krb5_ticket *tkt) >+{ >+#if defined(HAVE_KRB5_TKT_ENC_PART2) >+ return tkt->enc_part2->times.authtime; >+#else >+ return tkt->ticket.authtime; >+#endif >+} >+ >+static int get_kvno_from_ap_req(krb5_ap_req *ap_req) >+{ >+#ifdef HAVE_TICKET_POINTER_IN_KRB5_AP_REQ /* MIT */ >+ if (ap_req->ticket->enc_part.kvno) >+ return ap_req->ticket->enc_part.kvno; >+#else /* Heimdal */ >+ if (ap_req->ticket.enc_part.kvno) >+ return *ap_req->ticket.enc_part.kvno; >+#endif >+ return 0; >+} >+ >+static krb5_enctype get_enctype_from_ap_req(krb5_ap_req *ap_req) >+{ >+#ifdef HAVE_ETYPE_IN_ENCRYPTEDDATA /* Heimdal */ >+ return ap_req->ticket.enc_part.etype; >+#else /* MIT */ >+ return ap_req->ticket->enc_part.enctype; >+#endif >+} >+ >+static krb5_error_code >+get_key_from_keytab(krb5_context context, >+ krb5_keytab keytab, >+ krb5_const_principal server, >+ krb5_enctype enctype, >+ krb5_kvno kvno, >+ krb5_keyblock **out_key) >+{ >+ krb5_keytab_entry entry; >+ krb5_error_code ret; >+ krb5_keytab real_keytab; >+ char *name = NULL; >+ >+ if (keytab == NULL) { >+ krb5_kt_default(context, &real_keytab); >+ } else { >+ real_keytab = keytab; >+ } >+ >+ if ( DEBUGLEVEL >= 10 ) { >+ krb5_unparse_name(context, server, &name); >+ DEBUG(10,("get_key_from_keytab: will look for kvno %d, enctype %d and name: %s\n", >+ kvno, enctype, name)); >+ krb5_free_unparsed_name(context, name); >+ } >+ >+ ret = krb5_kt_get_entry(context, >+ real_keytab, >+ server, >+ kvno, >+ enctype, >+ &entry); >+ >+ if (ret) { >+ DEBUG(0,("get_key_from_keytab: failed to retrieve key: %s\n", error_message(ret))); >+ goto out; >+ } >+ >+#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */ >+ ret = krb5_copy_keyblock(context, &entry.keyblock, out_key); >+#elif defined(HAVE_KRB5_KEYTAB_ENTRY_KEY) /* MIT */ >+ ret = krb5_copy_keyblock(context, &entry.key, out_key); >+#else >+#error UNKNOWN_KRB5_KEYTAB_ENTRY_FORMAT >+#endif >+ >+ if (ret) { >+ DEBUG(0,("get_key_from_keytab: failed to copy key: %s\n", error_message(ret))); >+ goto out; >+ } >+ >+ smb_krb5_kt_free_entry(context, &entry); >+ >+out: >+ if (keytab == NULL) { >+ krb5_kt_close(context, real_keytab); >+ } >+ >+ return ret; >+} >+ >+void smb_krb5_free_ap_req(krb5_context context, >+ krb5_ap_req *ap_req) >+{ >+#ifdef HAVE_KRB5_FREE_AP_REQ /* MIT */ >+ krb5_free_ap_req(context, ap_req); >+#elif defined(HAVE_FREE_AP_REQ) /* Heimdal */ >+ free_AP_REQ(ap_req); >+#else >+#error UNKNOWN_KRB5_AP_REQ_FREE_FUNCTION >+#endif >+} >+ >+/* Prototypes */ >+#if defined(HAVE_DECODE_KRB5_AP_REQ) /* MIT */ >+krb5_error_code decode_krb5_ap_req(const krb5_data *code, krb5_ap_req **rep); >+#endif >+ >+krb5_error_code smb_krb5_get_keyinfo_from_ap_req(krb5_context context, >+ const krb5_data *inbuf, >+ krb5_kvno *kvno, >+ krb5_enctype *enctype) >+{ >+ krb5_error_code ret; >+#ifdef HAVE_KRB5_DECODE_AP_REQ /* Heimdal */ >+ { >+ krb5_ap_req ap_req; >+ >+ ret = krb5_decode_ap_req(context, inbuf, &ap_req); >+ if (ret) >+ return ret; >+ >+ *kvno = get_kvno_from_ap_req(&ap_req); >+ *enctype = get_enctype_from_ap_req(&ap_req); >+ >+ smb_krb5_free_ap_req(context, &ap_req); >+ } >+#elif defined(HAVE_DECODE_KRB5_AP_REQ) /* MIT */ >+ { >+ krb5_ap_req *ap_req = NULL; >+ >+ ret = decode_krb5_ap_req(inbuf, &ap_req); >+ if (ret) >+ return ret; >+ >+ *kvno = get_kvno_from_ap_req(ap_req); >+ *enctype = get_enctype_from_ap_req(ap_req); >+ >+ smb_krb5_free_ap_req(context, ap_req); >+ } >+#else >+#error UNKOWN_KRB5_AP_REQ_DECODING_FUNCTION >+#endif >+ return ret; >+} >+ >+krb5_error_code krb5_rd_req_return_keyblock_from_keytab(krb5_context context, >+ krb5_auth_context *auth_context, >+ const krb5_data *inbuf, >+ krb5_const_principal server, >+ krb5_keytab keytab, >+ krb5_flags *ap_req_options, >+ krb5_ticket **ticket, >+ krb5_keyblock **keyblock) >+{ >+ krb5_error_code ret; >+ krb5_ap_req *ap_req = NULL; >+ krb5_kvno kvno; >+ krb5_enctype enctype; >+ krb5_keyblock *local_keyblock; >+ >+ ret = krb5_rd_req(context, >+ auth_context, >+ inbuf, >+ server, >+ keytab, >+ ap_req_options, >+ ticket); >+ if (ret) { >+ return ret; >+ } >+ >+ ret = smb_krb5_get_keyinfo_from_ap_req(context, inbuf, &kvno, &enctype); >+ if (ret) { >+ return ret; >+ } >+ >+ ret = get_key_from_keytab(context, >+ keytab, >+ server, >+ enctype, >+ kvno, >+ &local_keyblock); >+ if (ret) { >+ DEBUG(0,("krb5_rd_req_return_keyblock_from_keytab: failed to call get_key_from_keytab\n")); >+ goto out; >+ } >+ >+out: >+ if (ap_req) { >+ smb_krb5_free_ap_req(context, ap_req); >+ } >+ >+ if (ret && local_keyblock != NULL) { >+ krb5_free_keyblock(context, local_keyblock); >+ } else { >+ *keyblock = local_keyblock; >+ } >+ >+ return ret; >+} >+ >+krb5_error_code smb_krb5_parse_name_norealm(krb5_context context, >+ const char *name, >+ krb5_principal *principal) >+{ >+#ifdef HAVE_KRB5_PARSE_NAME_NOREALM >+ return krb5_parse_name_norealm(context, name, principal); >+#endif >+ >+ /* we are cheating here because parse_name will in fact set the realm. >+ * We don't care as the only caller of smb_krb5_parse_name_norealm >+ * ignores the realm anyway when calling >+ * smb_krb5_principal_compare_any_realm later - Guenther */ >+ >+ return krb5_parse_name(context, name, principal); >+} >+ >+BOOL smb_krb5_principal_compare_any_realm(krb5_context context, >+ krb5_const_principal princ1, >+ krb5_const_principal princ2) >+{ >+#ifdef HAVE_KRB5_PRINCIPAL_COMPARE_ANY_REALM >+ >+ return krb5_principal_compare_any_realm(context, princ1, princ2); >+ >+/* krb5_princ_size is a macro in MIT */ >+#elif defined(HAVE_KRB5_PRINC_SIZE) || defined(krb5_princ_size) >+ >+ int i, len1, len2; >+ const krb5_data *p1, *p2; >+ >+ len1 = krb5_princ_size(context, princ1); >+ len2 = krb5_princ_size(context, princ2); >+ >+ if (len1 != len2) >+ return False; >+ >+ for (i = 0; i < len1; i++) { >+ >+ p1 = krb5_princ_component(context, CONST_DISCARD(krb5_principal, princ1), i); >+ p2 = krb5_princ_component(context, CONST_DISCARD(krb5_principal, princ2), i); >+ >+ if (p1->length != p2->length || memcmp(p1->data, p2->data, p1->length)) >+ return False; >+ } >+ >+ return True; >+#else >+#error NO_SUITABLE_PRINCIPAL_COMPARE_FUNCTION >+#endif >+} >+ > #else /* HAVE_KRB5 */ > /* this saves a few linking headaches */ > int cli_krb5_get_ticket(const char *principal, time_t time_offset, >Index: rpc_parse/parse_net.c >=================================================================== >--- rpc_parse/parse_net.c (revision 10425) >+++ rpc_parse/parse_net.c (working copy) >@@ -1496,7 +1497,7 @@ > ********************************************************************/ > > BOOL net_io_user_info3(const char *desc, NET_USER_INFO_3 *usr, prs_struct *ps, >- int depth, uint16 validation_level) >+ int depth, uint16 validation_level, BOOL kerb_validation_level) > { > unsigned int i; > >@@ -1595,6 +1596,18 @@ > } > } > >+ /* get kerb validation info (not really part of user_info_3) - Guenther */ >+ >+ if (kerb_validation_level) { >+ >+ if(!prs_uint32("ptr_res_group_dom_sid", ps, depth, &usr->ptr_res_group_dom_sid)) >+ return False; >+ if(!prs_uint32("res_group_count", ps, depth, &usr->res_group_count)) >+ return False; >+ if(!prs_uint32("ptr_res_groups", ps, depth, &usr->ptr_res_groups)) >+ return False; >+ } >+ > if(!smb_io_unistr2("uni_user_name", &usr->uni_user_name, usr->hdr_user_name.buffer, ps, depth)) /* username unicode string */ > return False; > if(!smb_io_unistr2("uni_full_name", &usr->uni_full_name, usr->hdr_full_name.buffer, ps, depth)) /* user's full name unicode string */ >@@ -1636,6 +1649,11 @@ > > uint32 num_other_sids = usr->num_other_sids; > >+ if (!(usr->user_flgs & LOGON_EXTRA_SIDS)) { >+ DEBUG(10,("net_io_user_info3: user_flgs attribute does not have LOGON_EXTRA_SIDS\n")); >+ /* return False; */ >+ } >+ > if (!prs_uint32("num_other_sids", ps, depth, > &num_other_sids)) > return False; >@@ -1733,11 +1751,11 @@ > return False; > > #if 1 /* W2k always needs this - even for bad passwd. JRA */ >- if(!net_io_user_info3("", r_l->user, ps, depth, r_l->switch_value)) >+ if(!net_io_user_info3("", r_l->user, ps, depth, r_l->switch_value, False)) > return False; > #else > if (r_l->switch_value != 0) { >- if(!net_io_user_info3("", r_l->user, ps, depth, r_l->switch_value)) >+ if(!net_io_user_info3("", r_l->user, ps, depth, r_l->switch_value, False)) > return False; > } > #endif >Index: include/authdata.h >=================================================================== >--- include/authdata.h (revision 10425) >+++ include/authdata.h (working copy) >@@ -23,12 +23,22 @@ > #define _AUTHDATA_H > > #include "rpc_misc.h" >+#include "rpc_netlogon.h" > > #define PAC_TYPE_LOGON_INFO 1 > #define PAC_TYPE_SERVER_CHECKSUM 6 > #define PAC_TYPE_PRIVSVR_CHECKSUM 7 > #define PAC_TYPE_LOGON_NAME 10 > >+#ifndef KRB5_AUTHDATA_WIN2K_PAC >+#define KRB5_AUTHDATA_WIN2K_PAC 128 >+#endif >+ >+#ifndef KRB5_AUTHDATA_IF_RELEVANT >+#define KRB5_AUTHDATA_IF_RELEVANT 1 >+#endif >+ >+ > typedef struct pac_logon_name { > NTTIME logon_time; > uint16 len; >@@ -37,7 +47,7 @@ > > typedef struct pac_signature_data { > uint32 type; >- uint8 *signature; >+ RPC_DATA_BLOB signature; /* this not the on-wire-format (!) */ > } PAC_SIGNATURE_DATA; > > typedef struct group_membership { >@@ -50,6 +60,8 @@ > GROUP_MEMBERSHIP *group_membership; > } GROUP_MEMBERSHIP_ARRAY; > >+#if 0 /* Unused, replaced by NET_USER_INFO_3 - Guenther */ >+ > typedef struct krb_sid_and_attrs { > uint32 sid_ptr; > uint32 attrs; >@@ -82,7 +94,7 @@ > UNIHDR hdr_dir_drive; > > uint16 logon_count; /* number of times user has logged onto domain */ >- uint16 reserved12; >+ uint16 bad_password_count; /* samba4 idl */ > > uint32 user_rid; > uint32 group_rid; >@@ -90,16 +102,16 @@ > uint32 group_membership_ptr; > uint32 user_flags; > >- uint32 reserved13[4]; >+ uint8 session_key[16]; /* samba4 idl */ > UNIHDR hdr_dom_controller; > UNIHDR hdr_dom_name; > > uint32 ptr_dom_sid; >- >- uint32 reserved16[2]; >- uint32 reserved17; /* looks like it may be acb_info */ >- uint32 reserved18[7]; > >+ uint8 lm_session_key[8]; /* samba4 idl */ >+ uint32 acct_flags; /* samba4 idl */ >+ uint32 unknown[7]; >+ > uint32 sid_count; > uint32 ptr_extra_sids; > >@@ -122,7 +134,15 @@ > GROUP_MEMBERSHIP_ARRAY res_groups; > > } PAC_LOGON_INFO; >+#endif > >+typedef struct pac_logon_info { >+ NET_USER_INFO_3 info3; >+ DOM_SID2 res_group_dom_sid; >+ GROUP_MEMBERSHIP_ARRAY res_groups; >+ >+} PAC_LOGON_INFO; >+ > typedef struct pac_info_ctr > { > union >@@ -134,18 +154,19 @@ > } pac; > } PAC_INFO_CTR; > >-typedef struct pac_info_hdr { >+typedef struct pac_buffer { > uint32 type; > uint32 size; > uint32 offset; > uint32 offsethi; > PAC_INFO_CTR *ctr; >-} PAC_INFO_HDR; >+ uint32 pad; >+} PAC_BUFFER; > > typedef struct pac_data { > uint32 num_buffers; > uint32 version; >- PAC_INFO_HDR *pac_info_hdr_ptr; >+ PAC_BUFFER *pac_buffer; > } PAC_DATA; > > >Index: include/includes.h >=================================================================== >--- include/includes.h (revision 10425) >+++ include/includes.h (working copy) >@@ -27,7 +27,8 @@ > > #ifndef __cplusplus > #define class #error DONT_USE_CPLUSPLUS_RESERVED_NAMES >-#define private #error DONT_USE_CPLUSPLUS_RESERVED_NAMES >+/* allow to build with newer heimdal releases */ >+/* #define private #error DONT_USE_CPLUSPLUS_RESERVED_NAMES */ > #define public #error DONT_USE_CPLUSPLUS_RESERVED_NAMES > #define protected #error DONT_USE_CPLUSPLUS_RESERVED_NAMES > #define template #error DONT_USE_CPLUSPLUS_RESERVED_NAMES >@@ -1414,7 +1415,7 @@ > void setup_kaddr( krb5_address *pkaddr, struct sockaddr *paddr); > int create_kerberos_key_from_string(krb5_context context, krb5_principal host_princ, krb5_data *password, krb5_keyblock *key, krb5_enctype enctype); > int create_kerberos_key_from_string_direct(krb5_context context, krb5_principal host_princ, krb5_data *password, krb5_keyblock *key, krb5_enctype enctype); >-void get_auth_data_from_tkt(DATA_BLOB *auth_data, krb5_ticket *tkt); >+BOOL get_auth_data_from_tkt(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, krb5_ticket *tkt); > krb5_const_principal get_principal_from_tkt(krb5_ticket *tkt); > krb5_error_code krb5_locate_kdc(krb5_context ctx, const krb5_data *realm, struct sockaddr **addr_pp, int *naddrs, int get_masters); > krb5_error_code get_kerberos_allowed_etypes(krb5_context context, krb5_enctype **enctypes); >Index: include/rpc_netlogon.h >=================================================================== >--- include/rpc_netlogon.h (revision 10425) >+++ include/rpc_netlogon.h (working copy) >@@ -84,6 +84,18 @@ > #define NL_CTRL_REPL_IN_PROGRESS 0x0002 > #define NL_CTRL_FULL_SYNC 0x0004 > >+#define LOGON_EXTRA_SIDS 0x0020 >+#define LOGON_RESOURCE_GROUPS 0x0200 >+ >+#define SE_GROUP_MANDATORY 0x00000001 >+#define SE_GROUP_ENABLED_BY_DEFAULT 0x00000002 >+#define SE_GROUP_ENABLED 0x00000004 >+#define SE_GROUP_OWNER 0x00000008 >+#define SE_GROUP_USE_FOR_DENY_ONLY 0x00000010 >+#define SE_GROUP_LOGON_ID 0xC0000000 >+#define SE_GROUP_RESOURCE 0x20000000 >+ >+ > #if 0 > /* I think this is correct - it's what gets parsed on the wire. JRA. */ > /* NET_USER_INFO_2 */ >@@ -186,6 +198,13 @@ > uint32 num_other_sids; /* number of foreign/trusted domain sids */ > uint32 buffer_other_sids; > >+ /* The next three uint32 are not really part of user_info_3 but here >+ * for parsing convenience. They are only valid in Kerberos PAC >+ * parsing - Guenther */ >+ uint32 ptr_res_group_dom_sid; >+ uint32 res_group_count; >+ uint32 ptr_res_groups; >+ > UNISTR2 uni_user_name; /* username unicode string */ > UNISTR2 uni_full_name; /* user's full name unicode string */ > UNISTR2 uni_logon_script; /* logon script unicode string */ >Index: include/ads.h >=================================================================== >--- include/ads.h (revision 10425) >+++ include/ads.h (working copy) >@@ -130,7 +130,7 @@ > #define UF_UNUSED_5 0x00800000 > > #define UF_UNUSED_6 0x01000000 >-#define UF_UNUSED_7 0x02000000 >+#define UF_NO_AUTH_DATA_REQUIRED 0x02000000 > #define UF_UNUSED_8 0x04000000 > #define UF_UNUSED_9 0x08000000 > >Index: configure.in >=================================================================== >--- configure.in (revision 10425) >+++ configure.in (working copy) >@@ -3048,9 +3048,77 @@ > AC_CHECK_FUNC_EXT(krb5_krbhst_get_addrinfo, $KRB5_LIBS) > AC_CHECK_FUNC_EXT(krb5_c_enctype_compare, $KRB5_LIBS) > AC_CHECK_FUNC_EXT(krb5_enctypes_compatible_keys, $KRB5_LIBS) >+ AC_CHECK_FUNC_EXT(krb5_crypto_init, $KRB5_LIBS) >+ AC_CHECK_FUNC_EXT(krb5_crypto_destroy, $KRB5_LIBS) >+ AC_CHECK_FUNC_EXT(krb5_decode_ap_req, $KRB5_LIBS) >+ AC_CHECK_FUNC_EXT(decode_krb5_ap_req, $KRB5_LIBS) >+ AC_CHECK_FUNC_EXT(krb5_free_ap_req, $KRB5_LIBS) >+ AC_CHECK_FUNC_EXT(free_AP_REQ, $KRB5_LIBS) >+ AC_CHECK_FUNC_EXT(krb5_c_verify_checksum, $KRB5_LIBS) >+ AC_CHECK_FUNC_EXT(krb5_principal_compare_any_realm, $KRB5_LIBS) >+ AC_CHECK_FUNC_EXT(krb5_parse_name_norealm, $KRB5_LIBS) >+ AC_CHECK_FUNC_EXT(krb5_princ_size, $KRB5_LIBS) > > LIBS="$KRB5_LIBS $LIBS" >- >+ >+ AC_CACHE_CHECK(whether krb5_verify_checksum takes 7 arguments, smb_krb5_verify_checksum, [ >+ AC_TRY_COMPILE([ >+ #include <krb5.h>], >+ [krb5_verify_checksum(0, 0, 0, 0, 0, 0, 0);], >+ [smb_krb5_verify_checksum=7], >+ [smb_krb5_verify_checksum=6], >+ ) >+ ]) >+ AC_DEFINE_UNQUOTED(KRB5_VERIFY_CHECKSUM_ARGS, $smb_krb5_verify_checksum, [Number of arguments to krb5_verify_checksum]) >+ >+ AC_CACHE_CHECK([for checksum in krb5_checksum], >+ samba_cv_HAVE_CHECKSUM_IN_KRB5_CHECKSUM,[ >+ AC_TRY_COMPILE([#include <krb5.h>], >+ [krb5_checksum cksum; cksum.checksum.length = 0;], >+ samba_cv_HAVE_CHECKSUM_IN_KRB5_CHECKSUM=yes, >+ samba_cv_HAVE_CHECKSUM_IN_KRB5_CHECKSUM=no)]) >+ >+ if test x"$samba_cv_HAVE_CHECKSUM_IN_KRB5_CHECKSUM" = x"yes"; then >+ AC_DEFINE(HAVE_CHECKSUM_IN_KRB5_CHECKSUM,1, >+ [Whether the krb5_checksum struct has a checksum property]) >+ fi >+ >+ AC_CACHE_CHECK([for etype in EncryptedData], >+ samba_cv_HAVE_ETYPE_IN_ENCRYPTEDDATA,[ >+ AC_TRY_COMPILE([#include <krb5.h>], >+ [EncryptedData edata; edata.etype = 0;], >+ samba_cv_HAVE_ETYPE_IN_ENCRYPTEDDATA=yes, >+ samba_cv_HAVE_ETYPE_IN_ENCRYPTEDDATA=no)]) >+ >+ if test x"$samba_cv_HAVE_ETYPE_IN_ENCRYPTEDDATA" = x"yes"; then >+ AC_DEFINE(HAVE_ETYPE_IN_ENCRYPTEDDATA,1, >+ [Whether the EncryptedData struct has a etype property]) >+ fi >+ >+ AC_CACHE_CHECK([for ticket pointer in krb5_ap_req], >+ samba_cv_HAVE_TICKET_POINTER_IN_KRB5_AP_REQ,[ >+ AC_TRY_COMPILE([#include <krb5.h>], >+ [krb5_ap_req *ap_req; ap_req->ticket = NULL;], >+ samba_cv_HAVE_TICKET_POINTER_IN_KRB5_AP_REQ=yes, >+ samba_cv_HAVE_TICKET_POINTER_IN_KRB5_AP_REQ=no)]) >+ >+ if test x"$samba_cv_HAVE_TICKET_POINTER_IN_KRB5_AP_REQ" = x"yes"; then >+ AC_DEFINE(HAVE_TICKET_POINTER_IN_KRB5_AP_REQ,1, >+ [Whether the krb5_ap_req struct has a ticket pointer]) >+ fi >+ >+ AC_CACHE_CHECK([for krb5_crypto type], >+ samba_cv_HAVE_KRB5_CRYPTO,[ >+ AC_TRY_COMPILE([#include <krb5.h>], >+ [krb5_crypto crypto;], >+ samba_cv_HAVE_KRB5_CRYPTO=yes, >+ samba_cv_HAVE_KRB5_CRYPTO=no)]) >+ >+ if test x"$samba_cv_HAVE_KRB5_CRYPTO" = x"yes"; then >+ AC_DEFINE(HAVE_KRB5_CRYPTO,1, >+ [Whether the type krb5_crypto exists]) >+ fi >+ > AC_CACHE_CHECK([for krb5_encrypt_block type], > samba_cv_HAVE_KRB5_ENCRYPT_BLOCK,[ > AC_TRY_COMPILE([#include <krb5.h>], >@@ -3178,6 +3246,30 @@ > [Whether the KV5M_KEYTAB option is available]) > fi > >+ AC_CACHE_CHECK([for KRB5_KU_OTHER_CKSUM], >+ samba_cv_HAVE_KRB5_KU_OTHER_CKSUM,[ >+ AC_TRY_COMPILE([#include <krb5.h>], >+ [krb5_keyusage usage = KRB5_KU_OTHER_CKSUM;], >+ samba_cv_HAVE_KRB5_KU_OTHER_CKSUM=yes, >+ samba_cv_HAVE_KRB5_KU_OTHER_CKSUM=no)]) >+ >+ if test x"$samba_cv_HAVE_KRB5_KU_OTHER_CKSUM" = x"yes"; then >+ AC_DEFINE(HAVE_KRB5_KU_OTHER_CKSUM,1, >+ [Whether KRB5_KU_OTHER_CKSUM is available]) >+ fi >+ >+ AC_CACHE_CHECK([for KRB5_KEYUSAGE_APP_DATA_CKSUM], >+ samba_cv_HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM,[ >+ AC_TRY_COMPILE([#include <krb5.h>], >+ [krb5_keyusage usage = KRB5_KEYUSAGE_APP_DATA_CKSUM;], >+ samba_cv_HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM=yes, >+ samba_cv_HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM=no)]) >+ >+ if test x"$samba_cv_HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM" = x"yes"; then >+ AC_DEFINE(HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM,1, >+ [Whether KRB5_KEYUSAGE_APP_DATA_CKSUM is available]) >+ fi >+ > AC_CACHE_CHECK([for the krb5_princ_component macro], > samba_cv_HAVE_KRB5_PRINC_COMPONENT,[ > AC_TRY_LINK([#include <krb5.h>], >Index: libads/kerberos_verify.c >=================================================================== >--- libads/kerberos_verify.c (revision 10425) >+++ libads/kerberos_verify.c (working copy) >@@ -4,8 +4,9 @@ > Copyright (C) Andrew Tridgell 2001 > Copyright (C) Remus Koos 2001 > Copyright (C) Luke Howard 2003 >- Copyright (C) Guenther Deschner 2003 >+ Copyright (C) Guenther Deschner 2003, 2005 > Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003 >+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005 > > This program is free software; you can redistribute it and/or modify > it under the terms of the GNU General Public License as published by >@@ -37,7 +38,8 @@ > ***********************************************************************************/ > > static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context auth_context, >- const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt) >+ const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt, >+ krb5_keyblock **keyblock) > { > krb5_error_code ret = 0; > BOOL auth_ok = False; >@@ -100,12 +102,18 @@ > p_packet->length = ticket->length; > p_packet->data = (krb5_pointer)ticket->data; > *pp_tkt = NULL; >- ret = krb5_rd_req(context, &auth_context, p_packet, kt_entry.principal, keytab, NULL, pp_tkt); >+ >+ ret = krb5_rd_req_return_keyblock_from_keytab(context, &auth_context, p_packet, >+ kt_entry.principal, keytab, >+ NULL, pp_tkt, keyblock); >+ > if (ret) { >- DEBUG(10, ("ads_keytab_verify_ticket: krb5_rd_req(%s) failed: %s\n", >+ DEBUG(10,("ads_keytab_verify_ticket: " >+ "krb5_rd_req_return_keyblock_from_keytab(%s) failed: %s\n", > entry_princ_s, error_message(ret))); > } else { >- DEBUG(3,("ads_keytab_verify_ticket: krb5_rd_req succeeded for principal %s\n", >+ DEBUG(3,("ads_keytab_verify_ticket: " >+ "krb5_rd_req_return_keyblock_from_keytab succeeded for principal %s\n", > entry_princ_s)); > auth_ok = True; > break; >@@ -172,8 +180,9 @@ > ***********************************************************************************/ > > static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context auth_context, >- krb5_principal host_princ, >- const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt) >+ krb5_principal host_princ, >+ const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt, >+ krb5_keyblock **keyblock) > { > krb5_error_code ret = 0; > BOOL auth_ok = False; >@@ -182,6 +191,8 @@ > krb5_enctype *enctypes = NULL; > int i; > >+ ZERO_STRUCTP(keyblock); >+ > if (!secrets_init()) { > DEBUG(1,("ads_secrets_verify_ticket: secrets_init failed\n")); > return False; >@@ -222,20 +233,23 @@ > > krb5_auth_con_setuseruserkey(context, auth_context, key); > >- krb5_free_keyblock(context, key); >- > if (!(ret = krb5_rd_req(context, &auth_context, p_packet, > NULL, > NULL, NULL, pp_tkt))) { > DEBUG(10,("ads_secrets_verify_ticket: enc type [%u] decrypted message !\n", > (unsigned int)enctypes[i] )); > auth_ok = True; >+ krb5_copy_keyblock(context, key, keyblock); >+ krb5_free_keyblock(context, key); > break; > } > > DEBUG((ret != KRB5_BAD_ENCTYPE) ? 3 : 10, > ("ads_secrets_verify_ticket: enc type [%u] failed to decrypt with error %s\n", > (unsigned int)enctypes[i], error_message(ret))); >+ >+ krb5_free_keyblock(context, key); >+ > } > > out: >@@ -251,27 +265,33 @@ > authorization_data if available. > ***********************************************************************************/ > >-NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket, >- char **principal, DATA_BLOB *auth_data, >+NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx, >+ const char *realm, const DATA_BLOB *ticket, >+ char **principal, PAC_DATA **pac_data, > DATA_BLOB *ap_rep, > DATA_BLOB *session_key) > { > NTSTATUS sret = NT_STATUS_LOGON_FAILURE; >+ DATA_BLOB auth_data; > krb5_context context = NULL; > krb5_auth_context auth_context = NULL; > krb5_data packet; > krb5_ticket *tkt = NULL; > krb5_rcache rcache = NULL; >+ krb5_keyblock *keyblock = NULL; >+ time_t authtime; > int ret; > > krb5_principal host_princ = NULL; >+ krb5_const_principal client_principal = NULL; > char *host_princ_s = NULL; > BOOL got_replay_mutex = False; > > BOOL auth_ok = False; >+ BOOL got_auth_data = False; > > ZERO_STRUCT(packet); >- ZERO_STRUCTP(auth_data); >+ ZERO_STRUCT(auth_data); > ZERO_STRUCTP(ap_rep); > ZERO_STRUCTP(session_key); > >@@ -335,20 +355,30 @@ > } > > if (lp_use_kerberos_keytab()) { >- auth_ok = ads_keytab_verify_ticket(context, auth_context, ticket, &packet, &tkt); >+ auth_ok = ads_keytab_verify_ticket(context, auth_context, ticket, &packet, &tkt, &keyblock); > } > if (!auth_ok) { > auth_ok = ads_secrets_verify_ticket(context, auth_context, host_princ, >- ticket, &packet, &tkt); >+ ticket, &packet, &tkt, &keyblock); > } > > release_server_mutex(); > got_replay_mutex = False; > >+#if 0 >+ /* Heimdal leaks here, if we fix the leak, MIT crashes */ >+ if (rcache) { >+ krb5_rc_close(context, rcache); >+ } >+#endif >+ > if (!auth_ok) { > DEBUG(3,("ads_verify_ticket: krb5_rd_req with auth failed (%s)\n", > error_message(ret))); > goto out; >+ } else { >+ authtime = get_authtime_from_tkt(tkt); >+ client_principal = get_principal_from_tkt(tkt); > } > > ret = krb5_mk_rep(context, auth_context, &packet); >@@ -369,21 +399,41 @@ > file_save("/tmp/ticket.dat", ticket->data, ticket->length); > #endif > >- get_auth_data_from_tkt(auth_data, tkt); >+ /* continue when no PAC is retrieved >+ (like accounts that have the UF_NO_AUTH_DATA_REQUIRED flag set) */ > >- { >- TALLOC_CTX *ctx = talloc_init("pac data"); >- decode_pac_data(auth_data, ctx); >- talloc_destroy(ctx); >+ got_auth_data = get_auth_data_from_tkt(mem_ctx, &auth_data, tkt); >+ if (!got_auth_data) { >+ DEBUG(3,("ads_verify_ticket: did not retrieve auth data. continuing without PAC\n")); > } > >+ if (got_auth_data && pac_data != NULL) { >+ >+ sret = decode_pac_data(mem_ctx, &auth_data, context, keyblock, client_principal, authtime, pac_data); >+ if (!NT_STATUS_IS_OK(sret)) { >+ DEBUG(0,("ads_verify_ticket: failed to decode PAC_DATA: %s\n", nt_errstr(sret))); >+ goto out; >+ } >+ data_blob_free(&auth_data); >+ } >+ > #if 0 >+#if defined(HAVE_KRB5_TKT_ENC_PART2) >+ /* MIT */ > if (tkt->enc_part2) { > file_save("/tmp/authdata.dat", > tkt->enc_part2->authorization_data[0]->contents, > tkt->enc_part2->authorization_data[0]->length); > } >+#else >+ /* Heimdal */ >+ if (tkt->ticket.authorization_data) { >+ file_save("/tmp/authdata.dat", >+ tkt->ticket.authorization_data->val->ad_data.data, >+ tkt->ticket.authorization_data->val->ad_data.length); >+ } > #endif >+#endif > > if ((ret = krb5_unparse_name(context, get_principal_from_tkt(tkt), > principal))) { >@@ -402,7 +452,7 @@ > } > > if (!NT_STATUS_IS_OK(sret)) { >- data_blob_free(auth_data); >+ data_blob_free(&auth_data); > } > > if (!NT_STATUS_IS_OK(sret)) { >@@ -413,6 +463,10 @@ > krb5_free_principal(context, host_princ); > } > >+ if (keyblock) { >+ krb5_free_keyblock(context, keyblock); >+ } >+ > if (tkt != NULL) { > krb5_free_ticket(context, tkt); > } >Index: libads/authdata.c >=================================================================== >--- libads/authdata.c (revision 10425) >+++ libads/authdata.c (working copy) >@@ -2,6 +2,11 @@ > Unix SMB/CIFS implementation. > kerberos authorization data (PAC) utility library > Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003 >+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005 >+ Copyright (C) Andrew Tridgell 2001 >+ Copyright (C) Luke Howard 2002-2003 >+ Copyright (C) Stefan Metzmacher 2004-2005 >+ Copyright (C) Guenther Deschner 2005 > > This program is free software; you can redistribute it and/or modify > it under the terms of the GNU General Public License as published by >@@ -22,17 +27,28 @@ > > #ifdef HAVE_KRB5 > >-static DATA_BLOB unwrap_pac(DATA_BLOB *auth_data) >+BOOL unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, DATA_BLOB *unwrapped_pac_data) > { > DATA_BLOB pac_contents; > ASN1_DATA data; > int data_type; > >+ if (!auth_data->length) { >+ return False; >+ } >+ > asn1_load(&data, *auth_data); > asn1_start_tag(&data, ASN1_SEQUENCE(0)); > asn1_start_tag(&data, ASN1_SEQUENCE(0)); > asn1_start_tag(&data, ASN1_CONTEXT(0)); > asn1_read_Integer(&data, &data_type); >+ >+ if (data_type != KRB5_AUTHDATA_WIN2K_PAC ) { >+ DEBUG(10,("authorization data is not a Windows PAC (type: %d)\n", data_type)); >+ asn1_free(&data); >+ return False; >+ } >+ > asn1_end_tag(&data); > asn1_start_tag(&data, ASN1_CONTEXT(1)); > asn1_read_OctetString(&data, &pac_contents); >@@ -40,7 +56,12 @@ > asn1_end_tag(&data); > asn1_end_tag(&data); > asn1_free(&data); >- return pac_contents; >+ >+ *unwrapped_pac_data = data_blob_talloc(mem_ctx, pac_contents.data, pac_contents.length); >+ >+ data_blob_free(&pac_contents); >+ >+ return True; > } > > static BOOL pac_io_logon_name(const char *desc, PAC_LOGON_NAME *logon_name, >@@ -75,6 +96,8 @@ > } > > >+ >+#if 0 /* Unused (handled now in net_io_user_info3()) - Guenther */ > static BOOL pac_io_krb_sids(const char *desc, KRB_SID_AND_ATTRS *sid_and_attr, > prs_struct *ps, int depth) > { >@@ -159,6 +182,7 @@ > return True; > > } >+#endif > > static BOOL pac_io_group_membership(const char *desc, > GROUP_MEMBERSHIP *membership, >@@ -216,27 +240,34 @@ > > } > >+#if 0 /* Unused, replaced using an expanded net_io_user_info3() now - Guenther */ > static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info, > prs_struct *ps, int depth) > { >- uint32 garbage; >+ uint32 garbage, i; >+ > if (NULL == info) > return False; > > prs_debug(ps, depth, desc, "pac_io_pac_logon_info"); > depth++; > >- if (!prs_uint32("unknown", ps, depth, &garbage)) >+ if (!prs_align(ps)) > return False; >- if (!prs_uint32("unknown", ps, depth, &garbage)) >+ if (!prs_uint32("unknown", ps, depth, &garbage)) /* 00081001 */ > return False; >+ if (!prs_uint32("unknown", ps, depth, &garbage)) /* cccccccc */ >+ return False; > if (!prs_uint32("bufferlen", ps, depth, &garbage)) > return False; >- if (!prs_uint32("bufferlenhi", ps, depth, &garbage)) >+ if (!prs_uint32("bufferlenhi", ps, depth, &garbage)) /* 00000000 */ > return False; >+ > if (!prs_uint32("pointer", ps, depth, &garbage)) > return False; > >+ if (!prs_align(ps)) >+ return False; > if (!smb_io_time("logon_time", &info->logon_time, ps, depth)) > return False; > if (!smb_io_time("logoff_time", &info->logoff_time, ps, depth)) >@@ -270,7 +301,7 @@ > > if (!prs_uint16("logon_count", ps, depth, &info->logon_count)) > return False; >- if (!prs_uint16("reserved12", ps, depth, &info->reserved12)) >+ if (!prs_uint16("bad_password_count", ps, depth, &info->bad_password_count)) > return False; > if (!prs_uint32("user_rid", ps, depth, &info->user_rid)) > return False; >@@ -287,14 +318,8 @@ > if (!prs_uint32("user_flags", ps, depth, &info->user_flags)) > return False; > >- if (!prs_uint32("reserved13.0", ps, depth, &info->reserved13[0])) >+ if (!prs_uint8s(False, "session_key", ps, depth, info->session_key, 16)) > return False; >- if (!prs_uint32("reserved13.1", ps, depth, &info->reserved13[1])) >- return False; >- if (!prs_uint32("reserved13.2", ps, depth, &info->reserved13[2])) >- return False; >- if (!prs_uint32("reserved13.3", ps, depth, &info->reserved13[3])) >- return False; > > if (!smb_io_unihdr("hdr_dom_controller", > &info->hdr_dom_controller, ps, depth)) >@@ -306,31 +331,18 @@ > if (!prs_uint32("ptr_dom_sid", ps, depth, &info->ptr_dom_sid)) > return False; > >- if (!prs_uint32("reserved16.0", ps, depth, &info->reserved16[0])) >+ if (!prs_uint8s(False, "lm_session_key", ps, depth, info->lm_session_key, 8)) > return False; >- if (!prs_uint32("reserved16.1", ps, depth, &info->reserved16[1])) >- return False; > >- /* might be acb_info */ >- if (!prs_uint32("reserved17", ps, depth, &info->reserved17)) >+ if (!prs_uint32("acct_flags", ps, depth, &info->acct_flags)) > return False; > >+ for (i = 0; i < 7; i++) >+ { >+ if (!prs_uint32("unkown", ps, depth, &info->unknown[i])) /* unknown */ >+ return False; >+ } > >- if (!prs_uint32("reserved18.0", ps, depth, &info->reserved18[0])) >- return False; >- if (!prs_uint32("reserved18.1", ps, depth, &info->reserved18[1])) >- return False; >- if (!prs_uint32("reserved18.2", ps, depth, &info->reserved18[2])) >- return False; >- if (!prs_uint32("reserved18.3", ps, depth, &info->reserved18[3])) >- return False; >- if (!prs_uint32("reserved18.4", ps, depth, &info->reserved18[4])) >- return False; >- if (!prs_uint32("reserved18.5", ps, depth, &info->reserved18[5])) >- return False; >- if (!prs_uint32("reserved18.6", ps, depth, &info->reserved18[6])) >- return False; >- > if (!prs_uint32("sid_count", ps, depth, &info->sid_count)) > return False; > if (!prs_uint32("ptr_extra_sids", ps, depth, &info->ptr_extra_sids)) >@@ -395,44 +407,109 @@ > &info->res_group_dom_sid, ps, depth)) > return False; > >- if (info->ptr_res_groups) >+ if (info->ptr_res_groups) { >+ >+ if (!(info->user_flgs & LOGON_RESOURCE_GROUPS)) { >+ DEBUG(0,("user_flgs attribute does not have LOGON_RESOURCE_GROUPS\n")); >+ /* return False; */ >+ } >+ > if (!pac_io_group_membership_array("res group membership", > &info->res_groups, > info->res_group_count, > ps, depth)) > return False; >+ } > > return True; > } >+#endif > >+static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info, >+ prs_struct *ps, int depth) >+{ >+ uint32 garbage; >+ BOOL kerb_validation_info = True; > >+ if (NULL == info) >+ return False; >+ >+ prs_debug(ps, depth, desc, "pac_io_pac_logon_info"); >+ depth++; >+ >+ if (!prs_align(ps)) >+ return False; >+ if (!prs_uint32("unknown", ps, depth, &garbage)) /* 00081001 */ >+ return False; >+ if (!prs_uint32("unknown", ps, depth, &garbage)) /* cccccccc */ >+ return False; >+ if (!prs_uint32("bufferlen", ps, depth, &garbage)) >+ return False; >+ if (!prs_uint32("bufferlenhi", ps, depth, &garbage)) /* 00000000 */ >+ return False; >+ >+ if(!net_io_user_info3("", &info->info3, ps, depth, 3, kerb_validation_info)) >+ return False; >+ >+ if (info->info3.ptr_res_group_dom_sid) { >+ if (!smb_io_dom_sid2("res_group_dom_sid", >+ &info->res_group_dom_sid, ps, depth)) >+ return False; >+ } >+ >+ if (info->info3.ptr_res_groups) { >+ >+ if (!(info->info3.user_flgs & LOGON_RESOURCE_GROUPS)) { >+ DEBUG(0,("user_flgs attribute does not have LOGON_RESOURCE_GROUPS\n")); >+ /* return False; */ >+ } >+ >+ if (!pac_io_group_membership_array("res group membership", >+ &info->res_groups, >+ info->info3.res_group_count, >+ ps, depth)) >+ return False; >+ } >+ >+ return True; >+} >+ >+ >+ > static BOOL pac_io_pac_signature_data(const char *desc, > PAC_SIGNATURE_DATA *data, uint32 length, > prs_struct *ps, int depth) > { > uint32 siglen = length - sizeof(uint32); >- if (NULL == data) >- return False; >- > prs_debug(ps, depth, desc, "pac_io_pac_signature_data"); > depth++; >+ >+ if (data == NULL) >+ return False; > >+ if (!prs_align(ps)) >+ return False; > if (!prs_uint32("type", ps, depth, &data->type)) > return False; >- if (UNMARSHALLING(ps)) { >- data->signature = PRS_ALLOC_MEM(ps, unsigned char, siglen); >- if (!data->signature) { >+ >+ if (UNMARSHALLING(ps) && length) { >+ data->signature.buffer = PRS_ALLOC_MEM(ps, uint8, siglen); >+ if (!data->signature.buffer) { > DEBUG(3, ("No memory available\n")); > return False; > } > } >- if (!prs_uint8s(False, "signature", ps, depth, data->signature,siglen)) >+ >+ data->signature.buf_len = siglen; >+ >+ if (!prs_uint8s(False, "signature", ps, depth, data->signature.buffer, data->signature.buf_len)) > return False; > >+ > return True; > } > >-static BOOL pac_io_pac_info_hdr_ctr(const char *desc, PAC_INFO_HDR *hdr, >+static BOOL pac_io_pac_info_hdr_ctr(const char *desc, PAC_BUFFER *hdr, > prs_struct *ps, int depth) > { > if (NULL == hdr) >@@ -445,8 +522,8 @@ > return False; > > if (hdr->offset != prs_offset(ps)) { >- DEBUG(5, ("offset in header(x%x) and data(x%x) do not match\n", >- hdr->offset, prs_offset(ps))); >+ DEBUG(5,("offset in header(x%x) and data(x%x) do not match, correcting\n", >+ hdr->offset, prs_offset(ps))); > prs_set_offset(ps, hdr->offset); > } > >@@ -518,10 +595,15 @@ > prs_set_offset(ps, prs_offset(ps) + hdr->size); > } > >+#if 0 >+ /* obscure pad */ >+ if (!prs_uint32("pad", ps, depth, &hdr->pad)) >+ return False; >+#endif > return True; > } > >-static BOOL pac_io_pac_info_hdr(const char *desc, PAC_INFO_HDR *hdr, >+static BOOL pac_io_pac_info_hdr(const char *desc, PAC_BUFFER *hdr, > prs_struct *ps, int depth) > { > if (NULL == hdr) >@@ -563,19 +645,19 @@ > return False; > > if (UNMARSHALLING(ps) && data->num_buffers > 0) { >- if ((data->pac_info_hdr_ptr = PRS_ALLOC_MEM(ps, PAC_INFO_HDR, data->num_buffers)) == NULL) { >+ if ((data->pac_buffer = PRS_ALLOC_MEM(ps, PAC_BUFFER, data->num_buffers)) == NULL) { > return False; > } > } > > for (i=0; i<data->num_buffers; i++) { >- if (!pac_io_pac_info_hdr(desc, &data->pac_info_hdr_ptr[i], ps, >+ if (!pac_io_pac_info_hdr(desc, &data->pac_buffer[i], ps, > depth)) > return False; > } > > for (i=0; i<data->num_buffers; i++) { >- if (!pac_io_pac_info_hdr_ctr(desc, &data->pac_info_hdr_ptr[i], >+ if (!pac_io_pac_info_hdr_ctr(desc, &data->pac_buffer[i], > ps, depth)) > return False; > } >@@ -583,25 +665,300 @@ > return True; > } > >-PAC_DATA *decode_pac_data(DATA_BLOB *auth_data, TALLOC_CTX *ctx) >+static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx, >+ DATA_BLOB pac_data, >+ PAC_SIGNATURE_DATA *sig, >+ krb5_context context, >+ krb5_keyblock *keyblock) > { >- DATA_BLOB pac_data_blob = unwrap_pac(auth_data); >+ krb5_error_code ret; >+ krb5_checksum cksum; >+ krb5_keyusage usage = 0; >+ >+ smb_krb5_checksum_from_pac_sig(&cksum, sig); >+ >+#ifdef HAVE_KRB5_KU_OTHER_CKSUM /* Heimdal */ >+ usage = KRB5_KU_OTHER_CKSUM; >+#elif defined(HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM) /* MIT */ >+ usage = KRB5_KEYUSAGE_APP_DATA_CKSUM; >+#else >+#error UNKNOWN_KRB5_KEYUSAGE >+#endif >+ >+ ret = smb_krb5_verify_checksum(context, >+ keyblock, >+ usage, >+ &cksum, >+ pac_data.data, >+ pac_data.length); >+ >+ if (ret) { >+ DEBUG(2,("check_pac_checksum: PAC Verification failed: %s (%d)\n", >+ error_message(ret), ret)); >+ return NT_STATUS_ACCESS_DENIED; >+ } >+ >+ return NT_STATUS_OK; >+} >+ >+static NTSTATUS parse_pac_data(TALLOC_CTX *mem_ctx, DATA_BLOB *pac_data_blob, PAC_DATA *pac_data) >+{ > prs_struct ps; >- PAC_DATA *pac_data; >+ PAC_DATA *my_pac; > >- DEBUG(5,("dump_pac_data\n")); >- prs_init(&ps, pac_data_blob.length, ctx, UNMARSHALL); >- prs_copy_data_in(&ps, (char *)pac_data_blob.data, pac_data_blob.length); >+ if (!prs_init(&ps, pac_data_blob->length, mem_ctx, UNMARSHALL)) >+ return NT_STATUS_NO_MEMORY; >+ >+ if (!prs_copy_data_in(&ps, (char *)pac_data_blob->data, pac_data_blob->length)) >+ return NT_STATUS_INVALID_PARAMETER; >+ > prs_set_offset(&ps, 0); > >- data_blob_free(&pac_data_blob); >+ my_pac = TALLOC_ZERO_P(mem_ctx, PAC_DATA); >+ if (!pac_io_pac_data("pac data", my_pac, &ps, 0)) >+ return NT_STATUS_INVALID_PARAMETER; > >- pac_data = TALLOC_ZERO_P(ctx, PAC_DATA); >- pac_io_pac_data("pac data", pac_data, &ps, 0); >- > prs_mem_free(&ps); > >- return pac_data; >+ *pac_data = *my_pac; >+ >+ return NT_STATUS_OK; > } > >+/* just for debugging, will be removed later - Guenther */ >+char *pac_group_attr_string(uint32 attr) >+{ >+ fstring name = ""; >+ >+ if (!attr) >+ return NULL; >+ >+ if (attr & SE_GROUP_MANDATORY) fstrcat(name, "SE_GROUP_MANDATORY "); >+ if (attr & SE_GROUP_ENABLED_BY_DEFAULT) fstrcat(name, "SE_GROUP_ENABLED_BY_DEFAULT "); >+ if (attr & SE_GROUP_ENABLED) fstrcat(name, "SE_GROUP_ENABLED "); >+ if (attr & SE_GROUP_OWNER) fstrcat(name, "SE_GROUP_OWNER "); >+ if (attr & SE_GROUP_USE_FOR_DENY_ONLY) fstrcat(name, "SE_GROUP_USE_FOR_DENY_ONLY "); >+ if (attr & SE_GROUP_LOGON_ID) fstrcat(name, "SE_GROUP_LOGON_ID "); >+ if (attr & SE_GROUP_RESOURCE) fstrcat(name, "SE_GROUP_RESOURCE "); >+ >+ return SMB_STRDUP(name); >+} >+ >+/* just for debugging, will be removed later - Guenther */ >+static void dump_pac_logon_info(PAC_LOGON_INFO *logon_info) { >+ >+ DOM_SID dom_sid, res_group_dom_sid; >+ int i; >+ char *attr_string; >+ uint32 user_flgs = logon_info->info3.user_flgs; >+ >+ if (logon_info->info3.ptr_res_group_dom_sid) { >+ sid_copy(&res_group_dom_sid, &logon_info->res_group_dom_sid.sid); >+ } >+ sid_copy(&dom_sid, &logon_info->info3.dom_sid.sid); >+ >+ DEBUG(10,("The PAC:\n")); >+ >+ DEBUGADD(10,("\tUser Flags: 0x%x (%d)\n", user_flgs, user_flgs)); >+ if (user_flgs & LOGON_EXTRA_SIDS) >+ DEBUGADD(10,("\tUser Flags: LOGON_EXTRA_SIDS 0x%x (%d)\n", LOGON_EXTRA_SIDS, LOGON_EXTRA_SIDS)); >+ if (user_flgs & LOGON_RESOURCE_GROUPS) >+ DEBUGADD(10,("\tUser Flags: LOGON_RESOURCE_GROUPS 0x%x (%d)\n", LOGON_RESOURCE_GROUPS, LOGON_RESOURCE_GROUPS)); >+ DEBUGADD(10,("\tUser SID: %s-%d\n", sid_string_static(&dom_sid), logon_info->info3.user_rid)); >+ DEBUGADD(10,("\tGroup SID: %s-%d\n", sid_string_static(&dom_sid), logon_info->info3.group_rid)); >+ >+ DEBUGADD(10,("\tGroup Membership (Global and Universal Groups of own domain):\n")); >+ for (i = 0; i < logon_info->info3.num_groups; i++) { >+ attr_string = pac_group_attr_string(logon_info->info3.gids[i].attr); >+ DEBUGADD(10,("\t\t%d: sid: %s-%d\n\t\t attr: 0x%x == %s\n", >+ i, sid_string_static(&dom_sid), >+ logon_info->info3.gids[i].g_rid, >+ logon_info->info3.gids[i].attr, >+ attr_string)); >+ SAFE_FREE(attr_string); >+ } >+ >+ DEBUGADD(10,("\tGroup Membership (Domain Local Groups and Groups from Trusted Domains):\n")); >+ for (i = 0; i < logon_info->info3.num_other_sids; i++) { >+ attr_string = pac_group_attr_string(logon_info->info3.other_sids_attrib[i]); >+ DEBUGADD(10,("\t\t%d: sid: %s\n\t\t attr: 0x%x == %s\n", >+ i, sid_string_static(&logon_info->info3.other_sids[i].sid), >+ logon_info->info3.other_sids_attrib[i], >+ attr_string)); >+ SAFE_FREE(attr_string); >+ } >+ >+ DEBUGADD(10,("\tGroup Membership (Ressource Groups (SID History ?)):\n")); >+ for (i = 0; i < logon_info->info3.res_group_count; i++) { >+ attr_string = pac_group_attr_string(logon_info->res_groups.group_membership[i].attrs); >+ DEBUGADD(10,("\t\t%d: sid: %s-%d\n\t\t attr: 0x%x == %s\n", >+ i, sid_string_static(&res_group_dom_sid), >+ logon_info->res_groups.group_membership[i].rid, >+ logon_info->res_groups.group_membership[i].attrs, >+ attr_string)); >+ SAFE_FREE(attr_string); >+ } >+} >+ >+NTSTATUS decode_pac_data(TALLOC_CTX *mem_ctx, >+ DATA_BLOB *pac_data_blob, >+ krb5_context context, >+ krb5_keyblock *service_keyblock, >+ krb5_const_principal client_principal, >+ time_t tgs_authtime, >+ PAC_DATA **pac_data) >+ >+{ >+ DATA_BLOB modified_pac_blob; >+ PAC_DATA *my_pac; >+ NTSTATUS nt_status; >+ krb5_error_code ret; >+ PAC_SIGNATURE_DATA *srv_sig = NULL; >+ PAC_SIGNATURE_DATA *kdc_sig = NULL; >+ PAC_LOGON_NAME *logon_name = NULL; >+ PAC_LOGON_INFO *logon_info = NULL; >+ krb5_principal client_principal_pac; >+ NTTIME tgs_authtime_nttime; >+ int i, srv_sig_pos = 0, kdc_sig_pos = 0; >+ fstring username; >+ >+ *pac_data = NULL; >+ >+ my_pac = talloc(mem_ctx, PAC_DATA); >+ if (!my_pac) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ nt_status = parse_pac_data(mem_ctx, pac_data_blob, my_pac); >+ if (!NT_STATUS_IS_OK(nt_status)) { >+ DEBUG(0,("decode_pac_data: failed to parse PAC\n")); >+ return nt_status; >+ } >+ >+ modified_pac_blob = data_blob_talloc(mem_ctx, pac_data_blob->data, pac_data_blob->length); >+ >+ if (my_pac->num_buffers < 4) { >+ nt_status = NT_STATUS_INVALID_PARAMETER; >+ goto out; >+ } >+ >+ /* store signatures */ >+ for (i=0; i < my_pac->num_buffers; i++) { >+ >+ switch (my_pac->pac_buffer[i].type) { >+ >+ case PAC_TYPE_SERVER_CHECKSUM: >+ if (!my_pac->pac_buffer[i].ctr->pac.srv_cksum) { >+ break; >+ } >+ >+ srv_sig = my_pac->pac_buffer[i].ctr->pac.srv_cksum; >+ >+ /* get position of signature buffer */ >+ srv_sig_pos = my_pac->pac_buffer[i].offset; >+ srv_sig_pos += sizeof(uint32); >+ >+ break; >+ >+ case PAC_TYPE_PRIVSVR_CHECKSUM: >+ if (!my_pac->pac_buffer[i].ctr->pac.privsrv_cksum) { >+ break; >+ } >+ >+ kdc_sig = my_pac->pac_buffer[i].ctr->pac.privsrv_cksum; >+ >+ /* get position of signature buffer */ >+ kdc_sig_pos = my_pac->pac_buffer[i].offset; >+ kdc_sig_pos += sizeof(uint32); >+ >+ break; >+ >+ case PAC_TYPE_LOGON_NAME: >+ if (!my_pac->pac_buffer[i].ctr->pac.logon_name) { >+ break; >+ } >+ >+ logon_name = my_pac->pac_buffer[i].ctr->pac.logon_name; >+ break; >+ >+ case PAC_TYPE_LOGON_INFO: >+ if (!my_pac->pac_buffer[i].ctr->pac.logon_info) { >+ break; >+ } >+ >+ logon_info = my_pac->pac_buffer[i].ctr->pac.logon_info; >+ break; >+ } >+ >+ } >+ >+ if (!srv_sig || !kdc_sig || !logon_name || !logon_info) { >+ nt_status = NT_STATUS_INVALID_PARAMETER; >+ goto out; >+ } >+ >+ /* zero PAC_SIGNATURE_DATA signature buffer */ >+ memset(&modified_pac_blob.data[srv_sig_pos], '\0', srv_sig->signature.buf_len); >+ memset(&modified_pac_blob.data[kdc_sig_pos], '\0', kdc_sig->signature.buf_len); >+ >+ /* check server signature */ >+ nt_status = check_pac_checksum(mem_ctx, modified_pac_blob, srv_sig, context, service_keyblock); >+ if (!NT_STATUS_IS_OK(nt_status)) { >+ DEBUG(0,("decode_pac_data: failed to verify PAC server signature\n")); >+ goto out; >+ } >+ >+ /* Convert to NT time, so as not to loose accuracy in comparison */ >+ unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime); >+ >+ if (!nt_time_equals(&tgs_authtime_nttime, &logon_name->logon_time)) { >+ >+ DEBUG(2,("decode_pac_data: Logon time mismatch between ticket and PAC!\n")); >+ DEBUGADD(2, ("decode_pac_data: PAC: %s\n", >+ http_timestring(nt_time_to_unix(&logon_name->logon_time)))); >+ DEBUGADD(2, ("decode_pac_data: Ticket: %s\n", >+ http_timestring(nt_time_to_unix(&tgs_authtime_nttime)))); >+ >+ nt_status = NT_STATUS_ACCESS_DENIED; >+ goto out; >+ } >+ >+ if (!logon_name->len) { >+ DEBUG(2,("decode_pac_data: No Logon Name available\n")); >+ nt_status = NT_STATUS_INVALID_PARAMETER; >+ goto out; >+ } >+ rpcstr_pull(username, logon_name->username, sizeof(username), -1, STR_TERMINATE); >+ >+ ret = smb_krb5_parse_name_norealm(context, username, &client_principal_pac); >+ if (ret) { >+ DEBUG(2,("decode_pac_data: Could not parse name from incoming PAC: [%s]: %s\n", >+ username, error_message(ret))); >+ nt_status = NT_STATUS_INVALID_PARAMETER; >+ goto out; >+ } >+ >+ if (!smb_krb5_principal_compare_any_realm(context, client_principal, client_principal_pac)) { >+ DEBUG(2,("decode_pac_data: Name in PAC [%s] does not match principal name in ticket\n", >+ username)); >+ nt_status = NT_STATUS_ACCESS_DENIED; >+ goto out; >+ } >+ >+ DEBUG(10,("Successfully validated Kerberos PAC\n")); >+ >+ dump_pac_logon_info(logon_info); >+ >+ *pac_data = my_pac; >+ >+ nt_status = NT_STATUS_OK; >+ >+out: >+ if (client_principal_pac) { >+ krb5_free_principal(context, client_principal_pac); >+ } >+ >+ return nt_status; >+} >+ > #endif >Index: utils/ntlm_auth.c >=================================================================== >--- utils/ntlm_auth.c (revision 10425) >+++ utils/ntlm_auth.c (working copy) >@@ -793,6 +793,7 @@ > DATA_BLOB token; > NTSTATUS status; > ssize_t len; >+ TALLOC_CTX *mem_ctx = talloc_init("manage_gss_spnego_request"); > > char *user = NULL; > char *domain = NULL; >@@ -895,7 +896,6 @@ > if (strcmp(request.negTokenInit.mechTypes[0], OID_KERBEROS5_OLD) == 0) { > > char *principal; >- DATA_BLOB auth_data; > DATA_BLOB ap_rep; > DATA_BLOB session_key; > >@@ -910,11 +910,13 @@ > response.negTokenTarg.mechListMIC = data_blob(NULL, 0); > response.negTokenTarg.responseToken = data_blob(NULL, 0); > >- status = ads_verify_ticket(lp_realm(), >+ status = ads_verify_ticket(mem_ctx, lp_realm(), > &request.negTokenInit.mechToken, >- &principal, &auth_data, &ap_rep, >+ &principal, NULL, &ap_rep, > &session_key); > >+ talloc_destroy(mem_ctx); >+ > /* Now in "principal" we have the name we are > authenticated as. */ > >@@ -934,7 +936,6 @@ > user = SMB_STRDUP(principal); > > data_blob_free(&ap_rep); >- data_blob_free(&auth_data); > > SAFE_FREE(principal); > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 2804
:
1277
|
1278
| 1461