summaryrefslogtreecommitdiff
path: root/source3/nsswitch/winbindd_pam.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2006-08-26 02:53:45 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:38:53 -0500
commite627362622344f70cd12ded917fe9d82feb63f1a (patch)
treefe1030ad60424820b76b65d8a4c619f6b334326d /source3/nsswitch/winbindd_pam.c
parent47e29ebe0975f63f972d137fca30fec843492f78 (diff)
downloadsamba-e627362622344f70cd12ded917fe9d82feb63f1a.tar.gz
samba-e627362622344f70cd12ded917fe9d82feb63f1a.tar.bz2
samba-e627362622344f70cd12ded917fe9d82feb63f1a.zip
r17837: Split out the storing of memory cached credentials
from the krb5 ticket renewal code. This allows cached credentials to be stored for single sign-on via ntlm_auth for machines in a domain still using NTLM. Also (hopefully) fixes the reference counting problem with pam_logon/logoff so multiple logons/logoffs won't lose cached credentials. This compiles, but I'm intending to test it over the weekend so don't complain too much :-). I also want it in the tree so Coverity can scan it for errors. Guenther, check this over please - I ran through the architecture with Jerry and he's ok with it, but this is modifying your code a lot. Jeremy. (This used to be commit 679eeeb91155dad3942efde6ae9f8d81faf18c5b)
Diffstat (limited to 'source3/nsswitch/winbindd_pam.c')
-rw-r--r--source3/nsswitch/winbindd_pam.c111
1 files changed, 62 insertions, 49 deletions
diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c
index c93f4c98b6..f87749abed 100644
--- a/source3/nsswitch/winbindd_pam.c
+++ b/source3/nsswitch/winbindd_pam.c
@@ -405,6 +405,7 @@ static void setup_return_cc_name(struct winbindd_cli_state *state, const char *c
Authenticate a user with a clear text password using Kerberos and fill up
ccache if required
**********************************************************************/
+
static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain,
struct winbindd_cli_state *state,
NET_USER_INFO_3 **info3)
@@ -630,9 +631,10 @@ failed:
"%s\n", error_message(krb5_ret)));
}
- if (!NT_STATUS_IS_OK(remove_ccache_by_ccname(cc))) {
+ if (!NT_STATUS_IS_OK(remove_ccache(state->request.data.auth.user))) {
DEBUG(3,("winbindd_raw_kerberos_login: "
- "could not remove ccache\n"));
+ "could not remove ccache for user %s\n",
+ state->request.data.auth.user));
}
done:
@@ -1224,7 +1226,7 @@ process_result:
DOM_SID user_sid;
- /* In all codepaths were result == NT_STATUS_OK info3 must have
+ /* In all codepaths where result == NT_STATUS_OK info3 must have
been initialized. */
if (!info3) {
result = NT_STATUS_INTERNAL_ERROR;
@@ -1265,27 +1267,40 @@ process_result:
}
- if ((state->request.flags & WBFLAG_PAM_CACHED_LOGIN) &&
- lp_winbind_offline_logon()) {
+ if ((state->request.flags & WBFLAG_PAM_CACHED_LOGIN)) {
+
+ /* Store in-memory creds for single-signon using ntlm_auth. */
+ result = winbindd_add_memory_creds(state->request.data.auth.user,
+ state->request.data.auth.pass);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("Failed to store memory creds: %s\n", nt_errstr(result)));
+ goto done;
+ }
- result = winbindd_store_creds(domain,
+ if (lp_winbind_offline_logon()) {
+ result = winbindd_store_creds(domain,
state->mem_ctx,
state->request.data.auth.user,
state->request.data.auth.pass,
info3, NULL);
- if (!NT_STATUS_IS_OK(result)) {
- DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result)));
- goto done;
- }
+ if (!NT_STATUS_IS_OK(result)) {
+
+ /* Release refcount. */
+ winbindd_delete_memory_creds(state->request.data.auth.user);
+ DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result)));
+ goto done;
+ }
+ }
}
- result = fillup_password_policy(domain, state);
+ result = fillup_password_policy(domain, state);
- if (!NT_STATUS_IS_OK(result)) {
- DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(result)));
- goto done;
- }
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(result)));
+ goto done;
+ }
}
@@ -1739,17 +1754,26 @@ void winbindd_pam_chauthtok(struct winbindd_cli_state *state)
}
done:
- if (NT_STATUS_IS_OK(result) && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN) &&
- lp_winbind_offline_logon()) {
- NTSTATUS cred_ret;
+ if (NT_STATUS_IS_OK(result) && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN)) {
- cred_ret = winbindd_update_creds_by_name(contact_domain,
+ /* Update the single sign-on memory creds. */
+ result = winbindd_replace_memory_creds(state->request.data.chauthtok.user,
+ newpass);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("Failed to replace memory creds: %s\n", nt_errstr(result)));
+ goto process_result;
+ }
+
+ if (lp_winbind_offline_logon()) {
+ result = winbindd_update_creds_by_name(contact_domain,
state->mem_ctx, user,
newpass);
- if (!NT_STATUS_IS_OK(cred_ret)) {
- DEBUG(10,("Failed to store creds: %s\n", nt_errstr(cred_ret)));
- goto process_result; /* FIXME: hm, risking inconsistant cache ? */
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result)));
+ goto process_result;
+ }
}
}
@@ -1827,7 +1851,6 @@ enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
{
NTSTATUS result = NT_STATUS_NOT_SUPPORTED;
- struct WINBINDD_CCACHE_ENTRY *entry;
int ret;
DEBUG(3, ("[%5lu]: pam dual logoff %s\n", (unsigned long)state->pid,
@@ -1840,52 +1863,42 @@ enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain,
#ifdef HAVE_KRB5
- /* what we need here is to find the corresponding krb5 ccache name *we*
- * created for a given username and destroy it (as the user who created it) */
-
- entry = get_ccache_by_username(state->request.data.logoff.user);
- if (entry == NULL) {
- DEBUG(10,("winbindd_pam_logoff: could not get ccname for user %s\n",
- state->request.data.logoff.user));
- goto process_result;
- }
-
- DEBUG(10,("winbindd_pam_logoff: found ccache [%s]\n", entry->ccname));
-
- if (entry->uid < 0 || state->request.data.logoff.uid < 0) {
+ if (state->request.data.logoff.uid < 0) {
DEBUG(0,("winbindd_pam_logoff: invalid uid\n"));
goto process_result;
}
- if (entry->uid != state->request.data.logoff.uid) {
- DEBUG(0,("winbindd_pam_logoff: uid's differ: %d != %d\n",
- entry->uid, state->request.data.logoff.uid));
- goto process_result;
- }
-
- if (!strcsequal(entry->ccname, state->request.data.logoff.krb5ccname)) {
- DEBUG(0,("winbindd_pam_logoff: krb5ccnames differ: (daemon) %s != (client) %s\n",
- entry->ccname, state->request.data.logoff.krb5ccname));
+ /* what we need here is to find the corresponding krb5 ccache name *we*
+ * created for a given username and destroy it (as the user who created it) */
+
+ if (!ccache_entry_identical(state->request.data.logoff.user,
+ state->request.data.logoff.uid,
+ state->request.data.logoff.krb5ccname)) {
+ DEBUG(0,("winbindd_pam_logoff: cached entry differs.\n"));
goto process_result;
}
- ret = ads_kdestroy(entry->ccname);
+ ret = ads_kdestroy(state->request.data.logoff.krb5ccname);
if (ret) {
DEBUG(0,("winbindd_pam_logoff: failed to destroy user ccache %s with: %s\n",
- entry->ccname, error_message(ret)));
+ state->request.data.logoff.krb5ccname, error_message(ret)));
} else {
DEBUG(10,("winbindd_pam_logoff: successfully destroyed ccache %s for user %s\n",
- entry->ccname, state->request.data.logoff.user));
- remove_ccache_by_ccname(entry->ccname);
+ state->request.data.logoff.krb5ccname, state->request.data.logoff.user));
}
+ remove_ccache(state->request.data.logoff.user);
+
result = krb5_to_nt_status(ret);
#else
result = NT_STATUS_NOT_SUPPORTED;
#endif
process_result:
+
+ winbindd_delete_memory_creds(state->request.data.logoff.user);
+
state->response.data.auth.nt_status = NT_STATUS_V(result);
fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));