r17616: Add the lm and nt hashes to the cached credentials
authorJeremy Allison <jra@samba.org>
Sun, 20 Aug 2006 01:25:26 +0000 (01:25 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:38:43 +0000 (11:38 -0500)
stored - only store the password if we're going to
be doing a krb5 refresh. GD please review this change !
Now to add code to reference count the cached creds
(to allow multiple pam_logon/pam_logoffs to keep the
creds around), ensure that the cred cache is called
on all successful pam_logons (if we have winbindd cache
pam credentials = true, set this by default) and finally
ensure the creds cache is changed on successful password
change. GD - you *really* need to review this :-).
Jeremy.

source/nsswitch/winbindd_ccache_access.c
source/nsswitch/winbindd_cred_cache.c
source/nsswitch/winbindd_nss.h

index 35d2cb4e51131fd13c2729ef54c504f73d182996..6ac3942a8d64120b0a33e9cf4fd60c6e980b4a05 100644 (file)
@@ -40,9 +40,10 @@ static BOOL client_can_access_ccache_entry(uid_t client_uid,
        return False;
 }
 
-static NTSTATUS do_ntlm_auth_with_password(const char *username,
+static NTSTATUS do_ntlm_auth_with_hashes(const char *username,
                                        const char *domain,
-                                       const char *password,
+                                       const unsigned char lm_hash[LM_HASH_LEN],
+                                       const unsigned char nt_hash[NT_HASH_LEN],
                                        const DATA_BLOB initial_msg,
                                        const DATA_BLOB challenge_msg,
                                        DATA_BLOB *auth_msg)
@@ -75,10 +76,10 @@ static NTSTATUS do_ntlm_auth_with_password(const char *username,
                goto done;
        }
 
-       status = ntlmssp_set_password(ntlmssp_state, password);
+       status = ntlmssp_set_hashes(ntlmssp_state, lm_hash, nt_hash);
         
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(1, ("Could not set password: %s\n",
+               DEBUG(1, ("Could not set hashes: %s\n",
                        nt_errstr(status)));
                goto done;
        }
@@ -256,7 +257,8 @@ enum winbindd_result winbindd_dual_ccache_ntlm_auth(struct winbindd_domain *doma
        if (!initial.data || !challenge.data) {
                result = NT_STATUS_NO_MEMORY;
        } else {
-               result = do_ntlm_auth_with_password(name_user, name_domain, entry->pass,
+               result = do_ntlm_auth_with_hashes(name_user, name_domain,
+                                               entry->lm_hash, entry->nt_hash,
                                                initial, challenge, &auth);
        }
 
index 688c8828d39c7c78a2ec7e99246cffd9b43da708..b56003a469b64266983f5b3057775033a3fbfe0e 100644 (file)
@@ -25,7 +25,7 @@
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 
-#define MAX_CCACHES 100 
+#define MAX_CCACHES 10000
 
 static struct WINBINDD_CCACHE_ENTRY *ccache_list;
 
@@ -75,19 +75,24 @@ NTSTATUS remove_ccache_by_ccname(const char *ccname)
                        DLIST_REMOVE(ccache_list, entry);
                        TALLOC_FREE(entry->event); /* unregisters events */
 #ifdef HAVE_MUNLOCK
-                       if (entry->pass) {      
-                               size_t len = strlen(entry->pass)+1;
+                       if (entry->nt_hash) {   
+                               size_t len = NT_HASH_LEN + LM_HASH_LEN;
+
+                               if (entry->pass) {
+                                       len += strlen(entry->pass)+1;
+                               }
+
 #ifdef DEBUG_PASSWORD
-                               DEBUG(10,("unlocking memory: %p\n", entry->pass));
+                               DEBUG(10,("unlocking memory: %p\n", entry->nt_hash));
 #endif
-                               memset(entry->pass, 0, len);
-                               if ((munlock(entry->pass, len)) == -1) {
+                               memset(entry->nt_hash, 0, len);
+                               if ((munlock(entry->nt_hash, len)) == -1) {
                                        DEBUG(0,("failed to munlock memory: %s (%d)\n", 
                                                strerror(errno), errno));
                                        return map_nt_error_from_unix(errno);
                                }
 #ifdef DEBUG_PASSWORD
-                               DEBUG(10,("munlocked memory: %p\n", entry->pass));
+                               DEBUG(10,("munlocked memory: %p\n", entry->nt_hash));
 #endif
                        }
 #endif /* HAVE_MUNLOCK */
@@ -109,7 +114,6 @@ static void krb5_ticket_refresh_handler(struct timed_event *te,
        time_t new_start;
        struct timeval t;
 
-
        DEBUG(10,("krb5_ticket_refresh_handler called\n"));
        DEBUGADD(10,("event called for: %s, %s\n", entry->ccname, entry->username));
 
@@ -245,30 +249,47 @@ NTSTATUS add_ccache_to_list(const char *princ_name,
                NT_STATUS_HAVE_NO_MEMORY(new_entry->service);
        }
 
-       if (schedule_refresh_event && pass) {
-#ifdef HAVE_MLOCK
-               size_t len = strlen(pass)+1;
-               
-               new_entry->pass = (char *)TALLOC_ZERO(mem_ctx, len);
-               NT_STATUS_HAVE_NO_MEMORY(new_entry->pass);
+       if (pass) {
+               size_t len = NT_HASH_LEN + LM_HASH_LEN;
+
+               /* We only store the plaintext if we're going to
+                  schedule a krb5 refresh. */
+
+               if (schedule_refresh_event) {
+                       len += strlen(pass)+1;
+               }
                
+               /* new_entry->nt_hash is the base pointer for the block
+                  of memory pointed into by new_entry->lm_hash and
+                  new_entry->pass (if we're storing plaintext). */
+
+               new_entry->nt_hash = (unsigned char *)TALLOC_ZERO(mem_ctx, len);
+               NT_STATUS_HAVE_NO_MEMORY(new_entry->nt_hash);
+
+               new_entry->lm_hash = new_entry->nt_hash + NT_HASH_LEN;
+#ifdef HAVE_MLOCK
 #ifdef DEBUG_PASSWORD
-               DEBUG(10,("mlocking memory: %p\n", new_entry->pass));
+               DEBUG(10,("mlocking memory: %p\n", new_entry->nt_hash));
 #endif         
-               if ((mlock(new_entry->pass, len)) == -1) {
+               if ((mlock(new_entry->nt_hash, len)) == -1) {
                        DEBUG(0,("failed to mlock memory: %s (%d)\n", 
                                strerror(errno), errno));
                        return map_nt_error_from_unix(errno);
                } 
                
 #ifdef DEBUG_PASSWORD
-               DEBUG(10,("mlocked memory: %p\n", new_entry->pass));
+               DEBUG(10,("mlocked memory: %p\n", new_entry->nt_hash));
 #endif         
-               memcpy(new_entry->pass, pass, len);
-#else
-               new_entry->pass = talloc_strdup(mem_ctx, pass);
-               NT_STATUS_HAVE_NO_MEMORY(new_entry->pass);
 #endif /* HAVE_MLOCK */
+
+               /* Create and store the password hashes. */
+               E_md4hash(pass, new_entry->nt_hash);
+               E_deshash(pass, new_entry->lm_hash);
+
+               if (schedule_refresh_event) {
+                       new_entry->pass = (char *)new_entry->lm_hash + LM_HASH_LEN;
+                       memcpy(new_entry->pass, pass, len - NT_HASH_LEN - LM_HASH_LEN);
+               }
        }
 
        new_entry->create_time = create_time;
@@ -279,7 +300,6 @@ NTSTATUS add_ccache_to_list(const char *princ_name,
        }
        new_entry->uid = uid;
 
-
        if (schedule_refresh_event && renew_until > 0) {
 
                struct timeval t = timeval_set((ticket_end -1 ), 0);
@@ -316,7 +336,7 @@ NTSTATUS init_ccache_list(void)
                return NT_STATUS_OK;
        }
 
-       mem_ctx = talloc_init("winbindd_ccache_krb5_handling");
+       mem_ctx = talloc_init("winbindd_ccache_handling");
        if (mem_ctx == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
index b19026b4dbf126813a691c81f48c518c6408f324..f393512b72a5844e1ed24cfc570b738bdcdc33af 100644 (file)
@@ -462,6 +462,8 @@ struct WINBINDD_CCACHE_ENTRY {
        const char *service;
        const char *username;
        const char *sid_string;
+       unsigned char *nt_hash; /* Base pointer for the following 2 */
+       unsigned char *lm_hash;
        char *pass;
        uid_t uid;
        time_t create_time;