auth/credentials: add cli_credentials_[g|s]et_old_nt_hash()
authorStefan Metzmacher <metze@samba.org>
Mon, 9 Feb 2015 08:04:42 +0000 (09:04 +0100)
committerGünther Deschner <gd@samba.org>
Thu, 12 Mar 2015 16:13:42 +0000 (17:13 +0100)
The machine and trust accounts it's important to retry
netr_Authenticate3() with the previous (old) nt_hash.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Guenther Deschner <gd@samba.org>
auth/credentials/credentials.c
auth/credentials/credentials.h
auth/credentials/credentials_internal.h
auth/credentials/credentials_ntlm.c

index a9e4fc864d46426de0d769fa0e5926fdd216bad6..42aa2a3c51e96816317213b32af0dc0975b63cd8 100644 (file)
@@ -70,6 +70,7 @@ _PUBLIC_ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx)
        cred->bind_dn = NULL;
 
        cred->nt_hash = NULL;
+       cred->old_nt_hash = NULL;
 
        cred->lm_response.data = NULL;
        cred->lm_response.length = 0;
@@ -481,6 +482,7 @@ _PUBLIC_ bool cli_credentials_set_old_password(struct cli_credentials *cred,
                /* Don't print the actual password in talloc memory dumps */
                talloc_set_name_const(cred->old_password, "password set via cli_credentials_set_old_password");
        }
+       cred->old_nt_hash = NULL;
        return true;
 }
 
@@ -524,6 +526,46 @@ _PUBLIC_ struct samr_Password *cli_credentials_get_nt_hash(struct cli_credential
        return NULL;
 }
 
+/**
+ * Obtain the old password, in the form MD4(unicode(password)) for this credentials context.
+ *
+ * Sometimes we only have this much of the password, while the rest of
+ * the time this call avoids calling E_md4hash themselves.
+ *
+ * @param cred credentials context
+ * @retval If set, the cleartext password, otherwise NULL
+ */
+_PUBLIC_ struct samr_Password *cli_credentials_get_old_nt_hash(struct cli_credentials *cred,
+                                                              TALLOC_CTX *mem_ctx)
+{
+       const char *old_password = NULL;
+
+       if (cred->old_nt_hash != NULL) {
+               struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
+               if (!nt_hash) {
+                       return NULL;
+               }
+
+               *nt_hash = *cred->old_nt_hash;
+
+               return nt_hash;
+       }
+
+       old_password = cli_credentials_get_old_password(cred);
+       if (old_password) {
+               struct samr_Password *nt_hash = talloc(mem_ctx, struct samr_Password);
+               if (!nt_hash) {
+                       return NULL;
+               }
+
+               E_md4hash(old_password, nt_hash->hash);
+
+               return nt_hash;
+       }
+
+       return NULL;
+}
+
 /**
  * Obtain the 'short' or 'NetBIOS' domain for this credentials context.
  * @param cred credentials context
index 814f01648b0decb0b59b7294f9e62a96bb55a959..d875fb575723abbeef23145d5a8897b54228e40a 100644 (file)
@@ -146,6 +146,8 @@ struct cli_credentials *cli_credentials_init_anon(TALLOC_CTX *mem_ctx);
 void cli_credentials_parse_string(struct cli_credentials *credentials, const char *data, enum credentials_obtained obtained);
 struct samr_Password *cli_credentials_get_nt_hash(struct cli_credentials *cred,
                                                  TALLOC_CTX *mem_ctx);
+struct samr_Password *cli_credentials_get_old_nt_hash(struct cli_credentials *cred,
+                                                     TALLOC_CTX *mem_ctx);
 bool cli_credentials_set_realm(struct cli_credentials *cred, 
                               const char *val, 
                               enum credentials_obtained obtained);
@@ -197,6 +199,8 @@ bool cli_credentials_set_utf16_password(struct cli_credentials *cred,
 bool cli_credentials_set_nt_hash(struct cli_credentials *cred,
                                 const struct samr_Password *nt_hash, 
                                 enum credentials_obtained obtained);
+bool cli_credentials_set_old_nt_hash(struct cli_credentials *cred,
+                                    const struct samr_Password *nt_hash);
 bool cli_credentials_set_ntlm_response(struct cli_credentials *cred,
                                       const DATA_BLOB *lm_response, 
                                       const DATA_BLOB *nt_response, 
index d05d1532cb0c1033244d1a5498ad6c5dc9c96890..aa01ccc1c4975eb5b09b3f5cc67efb0088d792d9 100644 (file)
@@ -60,6 +60,7 @@ struct cli_credentials {
 
        /* Allows authentication from a keytab or similar */
        struct samr_Password *nt_hash;
+       struct samr_Password *old_nt_hash;
 
        /* Allows NTLM pass-though authentication */
        DATA_BLOB lm_response;
index f339c9b6dc2646147322862136b603dec5f0e009..327cf1396f68b49faed9786991ca18083bf2d6cf 100644 (file)
@@ -289,6 +289,23 @@ _PUBLIC_ bool cli_credentials_set_nt_hash(struct cli_credentials *cred,
        return false;
 }
 
+_PUBLIC_ bool cli_credentials_set_old_nt_hash(struct cli_credentials *cred,
+                                             const struct samr_Password *nt_hash)
+{
+       cli_credentials_set_old_password(cred, NULL, CRED_SPECIFIED);
+       if (nt_hash) {
+               cred->old_nt_hash = talloc(cred, struct samr_Password);
+               if (cred->old_nt_hash == NULL) {
+                       return false;
+               }
+               *cred->old_nt_hash = *nt_hash;
+       } else {
+               cred->old_nt_hash = NULL;
+       }
+
+       return true;
+}
+
 _PUBLIC_ bool cli_credentials_set_ntlm_response(struct cli_credentials *cred,
                                                const DATA_BLOB *lm_response, 
                                                const DATA_BLOB *nt_response,