summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2006-08-20 01:25:26 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:38:43 -0500
commitb2d5dd7281805a25a86124d76dbc091fe12efff5 (patch)
treeafe2de67ddf4e2a57d16fbe7162bf21193b1ea61
parentffa590854ab5f2563c3398ae9ae3182e6abe3f82 (diff)
downloadsamba-b2d5dd7281805a25a86124d76dbc091fe12efff5.tar.gz
samba-b2d5dd7281805a25a86124d76dbc091fe12efff5.tar.bz2
samba-b2d5dd7281805a25a86124d76dbc091fe12efff5.zip
r17616: Add the lm and nt hashes to the cached credentials
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. (This used to be commit 017e7e14958d29246a1b221e33755bb91e96b08f)
-rw-r--r--source3/nsswitch/winbindd_ccache_access.c12
-rw-r--r--source3/nsswitch/winbindd_cred_cache.c66
-rw-r--r--source3/nsswitch/winbindd_nss.h2
3 files changed, 52 insertions, 28 deletions
diff --git a/source3/nsswitch/winbindd_ccache_access.c b/source3/nsswitch/winbindd_ccache_access.c
index 35d2cb4e51..6ac3942a8d 100644
--- a/source3/nsswitch/winbindd_ccache_access.c
+++ b/source3/nsswitch/winbindd_ccache_access.c
@@ -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);
}
diff --git a/source3/nsswitch/winbindd_cred_cache.c b/source3/nsswitch/winbindd_cred_cache.c
index 688c8828d3..b56003a469 100644
--- a/source3/nsswitch/winbindd_cred_cache.c
+++ b/source3/nsswitch/winbindd_cred_cache.c
@@ -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;
}
diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h
index b19026b4db..f393512b72 100644
--- a/source3/nsswitch/winbindd_nss.h
+++ b/source3/nsswitch/winbindd_nss.h
@@ -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;