The Samba-Bugzilla – Attachment 5758 Details for
Bug 7099
Every Thursday at 11:08-11:15am Windows Client Connections break with Kerberos errors
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
v3-5-test patch (port from master)
v3-5-test.patch (text/plain), 11.01 KB, created by
Guenther Deschner
on 2010-06-02 08:57:18 UTC
(
hide
)
Description:
v3-5-test patch (port from master)
Filename:
MIME Type:
Creator:
Guenther Deschner
Created:
2010-06-02 08:57:18 UTC
Size:
11.01 KB
patch
obsolete
>From de87f3a6ba836edbdc7abb882e186137a5c83afb Mon Sep 17 00:00:00 2001 >From: Matthieu Patou <mat@matws.net> >Date: Fri, 21 May 2010 11:57:29 +0400 >Subject: [PATCH] s3: Allow previous password to be stored and use it to check tickets >MIME-Version: 1.0 >Content-Type: text/plain; charset=UTF-8 >Content-Transfer-Encoding: 8bit > >This patch is to fix bug 7099. It stores the current password in the > previous password key when the password is changed. It also check the > user ticket against previous password. > >Signed-off-by: Günther Deschner <gd@samba.org> >--- > source3/include/proto.h | 1 + > source3/include/secrets.h | 1 + > source3/libads/kerberos_verify.c | 95 +++++++++++++++++++++++--------------- > source3/passdb/secrets.c | 81 ++++++++++++++++++++++++++++++-- > 4 files changed, 137 insertions(+), 41 deletions(-) > >diff --git a/source3/include/proto.h b/source3/include/proto.h >index 04065b0..9da40b0 100644 >--- a/source3/include/proto.h >+++ b/source3/include/proto.h >@@ -4713,6 +4713,7 @@ bool secrets_delete_machine_password(const char *domain); > bool secrets_delete_machine_password_ex(const char *domain); > bool secrets_delete_domain_sid(const char *domain); > bool secrets_store_machine_password(const char *pass, const char *domain, enum netr_SchannelType sec_channel); >+char *secrets_fetch_prev_machine_password(const char *domain); > char *secrets_fetch_machine_password(const char *domain, > time_t *pass_last_set_time, > enum netr_SchannelType *channel); >diff --git a/source3/include/secrets.h b/source3/include/secrets.h >index f369379..41d1af3 100644 >--- a/source3/include/secrets.h >+++ b/source3/include/secrets.h >@@ -25,6 +25,7 @@ > */ > #define SECRETS_MACHINE_ACCT_PASS "SECRETS/$MACHINE.ACC" > #define SECRETS_MACHINE_PASSWORD "SECRETS/MACHINE_PASSWORD" >+#define SECRETS_MACHINE_PASSWORD_PREV "SECRETS/MACHINE_PASSWORD.PREV" > #define SECRETS_MACHINE_LAST_CHANGE_TIME "SECRETS/MACHINE_LAST_CHANGE_TIME" > #define SECRETS_MACHINE_SEC_CHANNEL_TYPE "SECRETS/MACHINE_SEC_CHANNEL_TYPE" > #define SECRETS_MACHINE_TRUST_ACCOUNT_NAME "SECRETS/SECRETS_MACHINE_TRUST_ACCOUNT_NAME" >diff --git a/source3/libads/kerberos_verify.c b/source3/libads/kerberos_verify.c >index bf9bca6..68ba73c 100644 >--- a/source3/libads/kerberos_verify.c >+++ b/source3/libads/kerberos_verify.c >@@ -307,8 +307,10 @@ static krb5_error_code ads_secrets_verify_ticket(krb5_context context, > { > krb5_error_code ret = 0; > bool auth_ok = False; >+ bool cont = true; > char *password_s = NULL; >- krb5_data password; >+ /* Let's make some room for 2 password (old and new)*/ >+ krb5_data passwords[2]; > krb5_enctype enctypes[] = { > #if defined(ENCTYPE_ARCFOUR_HMAC) > ENCTYPE_ARCFOUR_HMAC, >@@ -318,12 +320,13 @@ static krb5_error_code ads_secrets_verify_ticket(krb5_context context, > ENCTYPE_NULL > }; > krb5_data packet; >- int i; >+ int i, j; > > *pp_tkt = NULL; > *keyblock = NULL; > *perr = 0; > >+ ZERO_STRUCT(passwords); > > if (!secrets_init()) { > DEBUG(1,("ads_secrets_verify_ticket: secrets_init failed\n")); >@@ -338,8 +341,15 @@ static krb5_error_code ads_secrets_verify_ticket(krb5_context context, > return False; > } > >- password.data = password_s; >- password.length = strlen(password_s); >+ passwords[0].data = password_s; >+ passwords[0].length = strlen(password_s); >+ >+ password_s = secrets_fetch_prev_machine_password(lp_workgroup()); >+ if (password_s) { >+ DEBUG(10,("ads_secrets_verify_ticket: found previous password\n")); >+ passwords[1].data = password_s; >+ passwords[1].length = strlen(password_s); >+ } > > /* CIFS doesn't use addresses in tickets. This would break NAT. JRA */ > >@@ -347,50 +357,61 @@ static krb5_error_code ads_secrets_verify_ticket(krb5_context context, > packet.data = (char *)ticket->data; > > /* We need to setup a auth context with each possible encoding type in turn. */ >- for (i=0;enctypes[i];i++) { >- krb5_keyblock *key = NULL; >+ for (j=0; j<2 && passwords[j].length; j++) { > >- if (!(key = SMB_MALLOC_P(krb5_keyblock))) { >- ret = ENOMEM; >- goto out; >- } >- >- if (create_kerberos_key_from_string(context, host_princ, &password, key, enctypes[i], false)) { >- SAFE_FREE(key); >- continue; >- } >+ for (i=0;enctypes[i];i++) { >+ krb5_keyblock *key = NULL; > >- krb5_auth_con_setuseruserkey(context, auth_context, key); >+ if (!(key = SMB_MALLOC_P(krb5_keyblock))) { >+ ret = ENOMEM; >+ goto out; >+ } > >- if (!(ret = krb5_rd_req(context, &auth_context, &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; >- } >+ if (create_kerberos_key_from_string(context, host_princ, &passwords[j], key, enctypes[i], false)) { >+ SAFE_FREE(key); >+ continue; >+ } >+ >+ krb5_auth_con_setuseruserkey(context, auth_context, key); >+ >+ if (!(ret = krb5_rd_req(context, &auth_context, &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; >+ cont = false; >+ 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))); >+ 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))); >+ >+ /* successfully decrypted but ticket is just not valid at the moment */ >+ if (ret == KRB5KRB_AP_ERR_TKT_NYV || >+ ret == KRB5KRB_AP_ERR_TKT_EXPIRED || >+ ret == KRB5KRB_AP_ERR_SKEW) { >+ krb5_free_keyblock(context, key); >+ cont = false; >+ break; >+ } > >- /* successfully decrypted but ticket is just not valid at the moment */ >- if (ret == KRB5KRB_AP_ERR_TKT_NYV || >- ret == KRB5KRB_AP_ERR_TKT_EXPIRED || >- ret == KRB5KRB_AP_ERR_SKEW) { > krb5_free_keyblock(context, key); >+ } >+ if (!cont) { >+ /* If we found a valid pass then no need to try >+ * the next one or we have invalid ticket so no need >+ * to try next password*/ > break; > } >- >- krb5_free_keyblock(context, key); >- > } > > out: >- SAFE_FREE(password_s); >+ SAFE_FREE(passwords[0].data); >+ SAFE_FREE(passwords[1].data); > *perr = ret; > return auth_ok; > } >diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c >index 67216a7..4eca9db 100644 >--- a/source3/passdb/secrets.c >+++ b/source3/passdb/secrets.c >@@ -324,6 +324,23 @@ static const char *machine_last_change_time_keystr(const char *domain) > > > /** >+ * Form a key for fetching the machine previous trust account password >+ * >+ * @param domain domain name >+ * >+ * @return keystring >+ **/ >+static const char *machine_prev_password_keystr(const char *domain) >+{ >+ char *keystr; >+ >+ keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s", >+ SECRETS_MACHINE_PASSWORD_PREV, domain); >+ SMB_ASSERT(keystr != NULL); >+ return keystr; >+} >+ >+/** > * Form a key for fetching the machine trust account password > * > * @param domain domain name >@@ -571,21 +588,42 @@ bool secrets_store_trusted_domain_password(const char* domain, const char* pwd, > } > > /************************************************************************ >- Routine to delete the plaintext machine account password >+ Routine to delete the old plaintext machine account password if any >+************************************************************************/ >+ >+static bool secrets_delete_prev_machine_password(const char *domain) >+{ >+ char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL); >+ if (oldpass == NULL) { >+ return true; >+ } >+ SAFE_FREE(oldpass); >+ return secrets_delete(machine_prev_password_keystr(domain)); >+} >+ >+/************************************************************************ >+ Routine to delete the plaintext machine account password and old >+ password if any > ************************************************************************/ > > bool secrets_delete_machine_password(const char *domain) > { >+ if (!secrets_delete_prev_machine_password(domain)) { >+ return false; >+ } > return secrets_delete(machine_password_keystr(domain)); > } > > /************************************************************************ >- Routine to delete the plaintext machine account password, sec channel type and >- last change time from secrets database >+ Routine to delete the plaintext machine account password, old password, >+ sec channel type and last change time from secrets database > ************************************************************************/ > > bool secrets_delete_machine_password_ex(const char *domain) > { >+ if (!secrets_delete_prev_machine_password(domain)) { >+ return false; >+ } > if (!secrets_delete(machine_password_keystr(domain))) { > return false; > } >@@ -605,8 +643,28 @@ bool secrets_delete_domain_sid(const char *domain) > } > > /************************************************************************ >+ Routine to store the previous machine password (by storing the current password >+ as the old) >+************************************************************************/ >+ >+static bool secrets_store_prev_machine_password(const char *domain) >+{ >+ char *oldpass; >+ bool ret; >+ >+ oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL); >+ if (oldpass == NULL) { >+ return true; >+ } >+ ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1); >+ SAFE_FREE(oldpass); >+ return ret; >+} >+ >+/************************************************************************ > Routine to set the plaintext machine account password for a realm >-the password is assumed to be a null terminated ascii string >+ the password is assumed to be a null terminated ascii string. >+ Before storing > ************************************************************************/ > > bool secrets_store_machine_password(const char *pass, const char *domain, >@@ -616,6 +674,10 @@ bool secrets_store_machine_password(const char *pass, const char *domain, > uint32 last_change_time; > uint32 sec_channel_type; > >+ if (!secrets_store_prev_machine_password(domain)) { >+ return false; >+ } >+ > ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1); > if (!ret) > return ret; >@@ -629,6 +691,17 @@ bool secrets_store_machine_password(const char *pass, const char *domain, > return ret; > } > >+ >+/************************************************************************ >+ Routine to fetch the previous plaintext machine account password for a realm >+ the password is assumed to be a null terminated ascii string. >+************************************************************************/ >+ >+char *secrets_fetch_prev_machine_password(const char *domain) >+{ >+ return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL); >+} >+ > /************************************************************************ > Routine to fetch the plaintext machine account password for a realm > the password is assumed to be a null terminated ascii string. >-- >1.6.6.1 >
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
Flags:
idra
:
review+
Actions:
View
Attachments on
bug 7099
:
5273
|
5728
|
5735
|
5752
| 5758