[PATCHES] Handle expired sessions in winbindd

Christof Schmitt cs at samba.org
Wed Jan 13 21:47:02 UTC 2016


On Tue, Jan 12, 2016 at 04:23:17PM -0700, Christof Schmitt wrote:
> On Tue, Jan 12, 2016 at 11:06:05PM +0100, Stefan Metzmacher wrote:
> > Hi Jeremy,
> > 
> > > So I've reviewed these and the patches LGTM except
> > > for the aptly named:
> > > 
> > > [PATCH 1/8] DONOTPUSH: Hack admember selftest to have winbind receive SESSION_EXPIRED
> > > 
> > > :-). They certainly clarify the retry logic a lot,
> > > and make the ads methods matchthe logic in
> > > source3/winbindd/winbindd_reconnect.c.
> > > 
> > > If I don't hear otherwise I'll push patches
> > > 2-8 in the next day or so !
> > 
> > Thanks!
> > 
> > Can you create a bug report for it unless we already have one
> > and add the BUG: tags to the commit messages,
> > we should at least backport this to 4.3.
> 
> There is no bugzilla yet. I can open one tomorrow, unless someone else
> does it earlier. I also started implementing a better test environment,
> as suggested by modifying the requested ticket expiration time. The
> patches should have all the important parts, but need to be debugged. If
> someone is interested i can post the current patch series.

The attached patches are my current work in progress to setup a test
with short ticket lifetimes in winbindd. The current problem is that i
cannot get the kerberos library to honor the requested short ticket
lifetime. With the attached patches applied, i can run:

SELFTEST_TESTENV=ad_member make testenv WINBINDD_OPTIONS="-d10"
bin/smbcontrol --configfile st/ad_member/lib/server.conf winbindd set-option krb:requested_lifetime=10
bin/wbinfo -t

The logs show that a short lifetime is requested through
in_creds.times.endtime, but this is not reflected in the output:

cli_session_setup_kerberos_send: DEBUG current time Wed, 13 Jan 2016 14:39:58 MST, life_time 10, expire_time Wed, 13 Jan 2016 14:40:08 MST
smb_krb5_get_credentials: DEBUG expire_time in: Wed, 13 Jan 2016 14:40:08 MST
smb_krb5_get_credentials: DEBUG expire_time out: Thu, 14 Jan 2016 00:39:27 MST
ads_cleanup_expired_creds: Ticket in ccache[MEMORY:cliconnect] expiration Thu, 14 Jan 2016 00:39:27 MST
ads_krb5_mk_req: Ticket (cifs/localdc.samba.example.com at SAMBA.EXAMPLE.COM) in ccache (MEMORY:cliconnect) is valid until: (Thu, 14 Jan 2016 00:39:27 MST - 1452757167)

Does anybody have an idea what i might be missing?

Thanks,

Christof
-------------- next part --------------
From b436f109da2607bb14be1378ed90c4371a97691d Mon Sep 17 00:00:00 2001
From: Christof Schmitt <cs at samba.org>
Date: Tue, 12 Jan 2016 12:15:17 -0700
Subject: [PATCH 1/8] winbindd: Introduce helper function for forwarding
 message to children

Signed-off-by: Christof Schmitt <cs at samba.org>
---
 source3/winbindd/winbindd_dual.c | 25 ++++++++++++-------------
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c
index 17a89a7..3882d90 100644
--- a/source3/winbindd/winbindd_dual.c
+++ b/source3/winbindd/winbindd_dual.c
@@ -601,6 +601,17 @@ void winbindd_flush_negative_conn_cache(struct winbindd_domain *domain)
 	}
 }
 
+static void winbindd_messaging_send_to_children(struct messaging_context *msg_ctx,
+						uint32_t msg_type, DATA_BLOB *data)
+{
+	struct winbindd_child *child;
+
+	for (child = winbindd_children; child != NULL; child = child->next) {
+		DBG_DEBUG("Sending message to pid %u.\n", (unsigned int)child->pid);
+		messaging_send(msg_ctx, pid_to_procid(child->pid), msg_type, data);
+	}
+}
+
 /* 
  * Parent winbindd process sets its own debug level first and then
  * sends a message to all the winbindd children to adjust their debug
@@ -613,22 +624,10 @@ void winbind_msg_debug(struct messaging_context *msg_ctx,
 			 struct server_id server_id,
 			 DATA_BLOB *data)
 {
-	struct winbindd_child *child;
-
 	DEBUG(10,("winbind_msg_debug: got debug message.\n"));
 
 	debug_message(msg_ctx, private_data, MSG_DEBUG, server_id, data);
-
-	for (child = winbindd_children; child != NULL; child = child->next) {
-
-		DEBUG(10,("winbind_msg_debug: sending message to pid %u.\n",
-			(unsigned int)child->pid));
-
-		messaging_send_buf(msg_ctx, pid_to_procid(child->pid),
-			   MSG_DEBUG,
-			   data->data,
-			   strlen((char *) data->data) + 1);
-	}
+	winbindd_messaging_send_to_children(msg_ctx, MSG_DEBUG, data);
 }
 
 /* Set our domains as offline and forward the offline message to our children. */
-- 
1.8.3.1


From 7b67c130e5d36757a7f9afdf269607a0633341ad Mon Sep 17 00:00:00 2001
From: Christof Schmitt <cs at samba.org>
Date: Tue, 12 Jan 2016 12:15:54 -0700
Subject: [PATCH 2/8] smbcontrol: Allow setting of config option in running
 process

---
 librpc/idl/messaging.idl   |  1 +
 source3/utils/smbcontrol.c | 13 +++++++++++++
 2 files changed, 14 insertions(+)

diff --git a/librpc/idl/messaging.idl b/librpc/idl/messaging.idl
index ca99f41..bb38d6c 100644
--- a/librpc/idl/messaging.idl
+++ b/librpc/idl/messaging.idl
@@ -41,6 +41,7 @@ interface messaging
 
 		/* Changes to smb.conf are really of general interest */
 		MSG_SMB_CONF_UPDATED		= 0x0021,
+		MSG_SET_OPTION			= 0x0022,
 
 		MSG_PREFORK_CHILD_EVENT		= 0x0031,
 		MSG_PREFORK_PARENT_EVENT	= 0x0032,
diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c
index d1eb7dd..e563b1f 100644
--- a/source3/utils/smbcontrol.c
+++ b/source3/utils/smbcontrol.c
@@ -1281,6 +1281,18 @@ static bool do_reload_config(struct tevent_context *ev_ctx,
 	return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
 }
 
+static bool do_set_option(struct tevent_context *ev_ctx,
+			  struct messaging_context *msg_ctx,
+			  const struct server_id pid,
+			  const int argc, const char **argv)
+{
+	if (argc != 2) {
+		fprintf(stderr, "Usage: smbcontrol <dest> set-option <option>\n");
+	}
+
+	return send_message(msg_ctx, pid, MSG_SET_OPTION, argv[1], strlen(argv[1]) + 1);
+}
+
 static bool do_reload_printers(struct tevent_context *ev_ctx,
 			       struct messaging_context *msg_ctx,
 			       const struct server_id pid,
@@ -1390,6 +1402,7 @@ static const struct {
 	{ "shutdown", do_shutdown, "Shut down daemon" },
 	{ "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
 	{ "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
+	{ "set-option", do_set_option, "Set config option in running process" },
 	{ "reload-printers", do_reload_printers, "Force smbd to reload printers"},
 	{ "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
 	{ "online", do_winbind_online, "Ask winbind to go into online state"},
-- 
1.8.3.1


From c4e0e32dd607d86c2b4d90e8714e3a4b2df8f942 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <cs at samba.org>
Date: Tue, 12 Jan 2016 12:19:49 -0700
Subject: [PATCH 3/8] docs: Document new set-option in smbcontrol

---
 docs-xml/manpages/smbcontrol.1.xml | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/docs-xml/manpages/smbcontrol.1.xml b/docs-xml/manpages/smbcontrol.1.xml
index 713c146..3b1c868 100644
--- a/docs-xml/manpages/smbcontrol.1.xml
+++ b/docs-xml/manpages/smbcontrol.1.xml
@@ -272,6 +272,13 @@
 	</varlistentry>
 
 	<varlistentry>
+	<term>set-option</term>
+	<listitem><para>Set config option in running process. Can be sent
+	to <constant>winbindd</constant>.
+	</para></listitem>
+	</varlistentry>
+
+	<varlistentry>
 	<term>reload-printers</term>
 	<listitem><para>Force smbd to reload printers. Can only be sent to
 	<constant>smbd</constant>.
-- 
1.8.3.1


From 13f72b61f4a9f64fb1564bc96b90749813463669 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <cs at samba.org>
Date: Tue, 12 Jan 2016 12:50:01 -0700
Subject: [PATCH 4/8] param: Introduce helper function for setting option from
 string

Signed-off-by: Christof Schmitt <cs at samba.org>
---
 source3/include/proto.h  |  1 +
 source3/param/loadparm.c | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/source3/include/proto.h b/source3/include/proto.h
index cc00a84..c36d57c 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -1014,6 +1014,7 @@ void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm);
 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm);
 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue);
 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue);
+bool lp_set_option(const char *option);
 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal);
 bool lp_snum_ok(int iService);
 void lp_add_one_printer(const char *name, const char *comment,
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 9f4a2b4..d531f2b 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -2527,6 +2527,29 @@ bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
 	return ret;
 }
 
+bool lp_set_option(const char *option)
+{
+	char *p, *s;
+	bool ret;
+
+	s = talloc_strdup(NULL, option);
+	if (!s) {
+		return false;
+	}
+
+	p = strchr(s, '=');
+	if (!p) {
+		talloc_free(s);
+		return false;
+	}
+
+	*p = 0;
+
+	ret = lp_set_cmdline(s, p+1);
+	talloc_free(s);
+	return ret;
+}
+
 /***************************************************************************
  Process a parameter.
 ***************************************************************************/
-- 
1.8.3.1


From d7276fa6282bc4750aa77972deb6311a3acdf7db Mon Sep 17 00:00:00 2001
From: Christof Schmitt <cs at samba.org>
Date: Tue, 12 Jan 2016 12:58:53 -0700
Subject: [PATCH 5/8] winbindd: Handle SET_OPTION message

---
 source3/winbindd/winbindd.c       |  2 ++
 source3/winbindd/winbindd_dual.c  | 24 +++++++++++++++++++++++-
 source3/winbindd/winbindd_proto.h |  5 +++++
 3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c
index d555127..139d576 100644
--- a/source3/winbindd/winbindd.c
+++ b/source3/winbindd/winbindd.c
@@ -1398,6 +1398,8 @@ static void winbindd_register_handlers(struct messaging_context *msg_ctx,
 			   MSG_DEBUG,
 			   winbind_msg_debug);
 
+	messaging_register(msg_ctx, NULL, MSG_SET_OPTION, winbind_msg_set_option);
+
 	netsamlogon_cache_init(); /* Non-critical */
 
 	/* clear the cached list of trusted domains */
diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c
index 3882d90..bb16ee6 100644
--- a/source3/winbindd/winbindd_dual.c
+++ b/source3/winbindd/winbindd_dual.c
@@ -630,6 +630,16 @@ void winbind_msg_debug(struct messaging_context *msg_ctx,
 	winbindd_messaging_send_to_children(msg_ctx, MSG_DEBUG, data);
 }
 
+void winbind_msg_set_option(struct messaging_context *msg_ctx,
+			    void *private_data,
+			    uint32_t msg_type,
+			    struct server_id server_id,
+			    DATA_BLOB *data)
+{
+	lp_set_option((const char *)data->data);
+	winbindd_messaging_send_to_children(msg_ctx, MSG_SET_OPTION, data);
+}
+
 /* Set our domains as offline and forward the offline message to our children. */
 
 void winbind_msg_offline(struct messaging_context *msg_ctx,
@@ -1243,6 +1253,15 @@ static void child_msg_dump_event_list(struct messaging_context *msg,
 	dump_event_list(winbind_event_context());
 }
 
+static void child_set_option(struct messaging_context *msg,
+			     void *private_data,
+			     uint32_t msg_type,
+			     struct server_id server_id,
+			     DATA_BLOB *data)
+{
+	lp_set_option((const char *)data->data);
+}
+
 NTSTATUS winbindd_reinit_after_fork(const struct winbindd_child *myself,
 				    const char *logfilename)
 {
@@ -1292,6 +1311,8 @@ NTSTATUS winbindd_reinit_after_fork(const struct winbindd_child *myself,
 			     MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
 	messaging_deregister(winbind_messaging_context(),
 			     MSG_DEBUG, NULL);
+	messaging_deregister(winbind_messaging_context(),
+			     MSG_SET_OPTION, NULL);
 
 	messaging_deregister(winbind_messaging_context(),
 			     MSG_WINBIND_DOMAIN_OFFLINE, NULL);
@@ -1504,7 +1525,8 @@ static bool fork_domain_child(struct winbindd_child *child)
 	messaging_register(winbind_messaging_context(), NULL,
 			   MSG_WINBIND_IP_DROPPED,
 			   winbind_msg_ip_dropped);
-
+	messaging_register(winbind_messaging_context(), NULL,
+			   MSG_SET_OPTION, child_set_option);
 
 	primary_domain = find_our_domain();
 
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 9920a3f..1046bca 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -266,6 +266,11 @@ void winbind_msg_debug(struct messaging_context *msg_ctx,
 			 uint32_t msg_type,
 			 struct server_id server_id,
 			 DATA_BLOB *data);
+void winbind_msg_set_option(struct messaging_context *msg_ctx,
+			    void *private_data,
+			    uint32_t msg_type,
+			    struct server_id server_id,
+			    DATA_BLOB *data);
 void winbind_msg_offline(struct messaging_context *msg_ctx,
 			 void *private_data,
 			 uint32_t msg_type,
-- 
1.8.3.1


From 6b7cdee154dda2c371407211a200b924a7510667 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <cs at samba.org>
Date: Tue, 12 Jan 2016 14:11:05 -0700
Subject: [PATCH 6/8] krb5_wrap: Optionally use caller provided expiration time

---
 lib/krb5_wrap/krb5_samba.c | 6 ++++++
 lib/krb5_wrap/krb5_samba.h | 1 +
 2 files changed, 7 insertions(+)

diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c
index 13984e9..03eaad5 100644
--- a/lib/krb5_wrap/krb5_samba.c
+++ b/lib/krb5_wrap/krb5_samba.c
@@ -579,6 +579,7 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context,
 						       creds.client,
 						       creds.server,
 						       impersonate_princ,
+						       *expire_time,
 						       &credsp))) {
 			DEBUG(1,("ads_krb5_mk_req: smb_krb5_get_credentials failed for %s (%s)\n",
 				principal, error_message(retval)));
@@ -1540,6 +1541,7 @@ krb5_error_code smb_krb5_get_credentials(krb5_context context,
 					 krb5_principal me,
 					 krb5_principal server,
 					 krb5_principal impersonate_princ,
+					 time_t expire_time,
 					 krb5_creds **out_creds)
 {
 	krb5_error_code ret;
@@ -1565,6 +1567,10 @@ krb5_error_code smb_krb5_get_credentials(krb5_context context,
 		in_creds.client = me;
 		in_creds.server = server;
 
+		if (expire_time != 0) {
+			in_creds.times.endtime = expire_time;
+		}
+
 		ret = krb5_get_credentials(context, 0, ccache,
 					   &in_creds, &creds);
 	}
diff --git a/lib/krb5_wrap/krb5_samba.h b/lib/krb5_wrap/krb5_samba.h
index cef9144..ca03ce8 100644
--- a/lib/krb5_wrap/krb5_samba.h
+++ b/lib/krb5_wrap/krb5_samba.h
@@ -197,6 +197,7 @@ krb5_error_code smb_krb5_get_credentials(krb5_context context,
 					 krb5_principal me,
 					 krb5_principal server,
 					 krb5_principal impersonate_princ,
+					 time_t expire_time,
 					 krb5_creds **out_creds);
 krb5_error_code smb_krb5_keyblock_init_contents(krb5_context context,
 						krb5_enctype enctype,
-- 
1.8.3.1


From 1153fdd091d8e789ddbc8decfbacc3251cd372e1 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <cs at samba.org>
Date: Tue, 12 Jan 2016 14:11:35 -0700
Subject: [PATCH 7/8] libsmb: Allow specifying ticket expiration time

---
 source3/libsmb/cliconnect.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 530f5c3..b39f29d 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -1284,6 +1284,7 @@ static struct tevent_req *cli_session_setup_kerberos_send(
 	struct tevent_req *req, *subreq;
 	struct cli_session_setup_kerberos_state *state;
 	int rc;
+	time_t life_time, expire_time = 0;
 
 	DEBUG(2,("Doing kerberos session setup\n"));
 
@@ -1295,12 +1296,17 @@ static struct tevent_req *cli_session_setup_kerberos_send(
 	state->cli = cli;
 	state->ads_status = ADS_SUCCESS;
 
+	life_time = lp_parm_int(-1, "krb", "requested_life_time", 0);
+	if (life_time != 0) {
+		expire_time = time(NULL) + life_time;
+	}
+
 	/*
 	 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
 	 * we have to acquire a ticket. To be fixed later :-)
 	 */
 	rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
-				     &state->session_key_krb5, 0, NULL, NULL);
+				     &state->session_key_krb5, 0, NULL, &expire_time);
 	if (rc) {
 		NTSTATUS status;
 
-- 
1.8.3.1


From 19c0d1f21a6b2fb2b131f602e896d8b69a61e885 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <cs at samba.org>
Date: Wed, 13 Jan 2016 14:45:54 -0700
Subject: [PATCH 8/8] DEBUG

---
 lib/krb5_wrap/krb5_samba.c       | 9 +++++++++
 source3/libsmb/cliconnect.c      | 3 +++
 source3/winbindd/winbindd_dual.c | 1 +
 3 files changed, 13 insertions(+)

diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c
index 03eaad5..28edc9c 100644
--- a/lib/krb5_wrap/krb5_samba.c
+++ b/lib/krb5_wrap/krb5_samba.c
@@ -1571,8 +1571,17 @@ krb5_error_code smb_krb5_get_credentials(krb5_context context,
 			in_creds.times.endtime = expire_time;
 		}
 
+		DBG_ERR("DEBUG expire_time in: %s\n", http_timestring(talloc_tos(), in_creds.times.endtime));
+
+
 		ret = krb5_get_credentials(context, 0, ccache,
 					   &in_creds, &creds);
+
+		DBG_ERR("DEBUG expire_time out: %s\n", http_timestring(talloc_tos(), creds->times.endtime));
+
+		
+
+
 	}
 	if (ret) {
 		goto done;
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index b39f29d..1625014 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -1300,6 +1300,9 @@ static struct tevent_req *cli_session_setup_kerberos_send(
 	if (life_time != 0) {
 		expire_time = time(NULL) + life_time;
 	}
+	DBG_ERR("DEBUG current time %s, life_time %ld, expire_time %s\n",
+		http_timestring(talloc_tos(), (long)time(NULL)), life_time,
+		http_timestring(talloc_tos(), expire_time));
 
 	/*
 	 * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c
index bb16ee6..7861a4c 100644
--- a/source3/winbindd/winbindd_dual.c
+++ b/source3/winbindd/winbindd_dual.c
@@ -637,6 +637,7 @@ void winbind_msg_set_option(struct messaging_context *msg_ctx,
 			    DATA_BLOB *data)
 {
 	lp_set_option((const char *)data->data);
+	DBG_ERR("DEBUG lp_set_option %s\n", (const char *)data->data);
 	winbindd_messaging_send_to_children(msg_ctx, MSG_SET_OPTION, data);
 }
 
-- 
1.8.3.1



More information about the samba-technical mailing list