summaryrefslogtreecommitdiff
path: root/source3/libads
diff options
context:
space:
mode:
authorMatthieu Patou <mat@matws.net>2010-05-21 11:57:29 +0400
committerGünther Deschner <gd@samba.org>2010-06-02 14:32:23 +0200
commit57ab910b6f3a24bf188415baf58de610203594b1 (patch)
treedf32dc663dbbda02d4a76bc92b935d6ba58f81ae /source3/libads
parent95863bfb5e547132c8f02c49a2bed1ec308d8f5e (diff)
downloadsamba-57ab910b6f3a24bf188415baf58de610203594b1.tar.gz
samba-57ab910b6f3a24bf188415baf58de610203594b1.tar.bz2
samba-57ab910b6f3a24bf188415baf58de610203594b1.zip
s3: Allow previous password to be stored and use it to check tickets
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>
Diffstat (limited to 'source3/libads')
-rw-r--r--source3/libads/kerberos_verify.c95
1 files changed, 58 insertions, 37 deletions
diff --git a/source3/libads/kerberos_verify.c b/source3/libads/kerberos_verify.c
index 4d7bb8d20b..c07259394b 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;
}