[PATCH] net cache samlogon list|show|ndrdump|delete (was: RFC: net cache samlogon list|show|delete)

Ralph Böhme slow at samba.org
Mon Jul 3 12:34:00 UTC 2017


On Mon, Jul 03, 2017 at 02:15:35PM +0200, Ralph Böhme via samba-technical wrote:
> On Mon, Jul 03, 2017 at 01:42:21PM +0200, Ralph Böhme via samba-technical wrote:
> > On Wed, Jun 28, 2017 at 09:14:44AM +0200, Ralph Böhme wrote:
> > > On Wed, Jun 28, 2017 at 09:11:40AM +0200, Stefan Metzmacher wrote:
> > > > Hi Ralph,
> > > > 
> > > > >> I'm working on an enhancement to net that will allow the user to work on the
> > > > >> samlogon cache (netsamlogon_cache.tdb).
> > > > >>
> > > > >> I added this as a subcommand to the existing net cache commands. Any better
> > > > >> suggestions?
> > > > >>
> > > > >> Here's what I already have:
> > > > >>
> > > > >> $ sudo ./bin/net cache samlogon 
> > > > >> Invalid command: net cache samlogon 
> > > > >> Usage:
> > > > >> net cache samlogon list            List samlogon cache
> > > > >> net cache samlogon show            Show samlogon cache entry
> > > > >> net cache samlogon delete          Delete samlogon cache entry
> > > > >>
> > > > >> $ sudo ./bin/net cache samlogon list
> > > > >> SID                                                Name                                     When cached
> > > > >> ----------------------------------------------------------------------------------------------------------------------------
> > > > >> S-1-5-21-364438107-531279461-249741216-1000        SLOWSERVER\slow                          Sun Mar 27 12:26:55 PM 2016 CEST
> > > > >>
> > > > >> $ sudo ./bin/net cache samlogon show S-1-5-21-364438107-531279461-249741216-1000
> > > > >> Name: SLOWSERVER\slow
> > > > >> SID  0: S-1-5-21-364438107-531279461-249741216-1000
> > > > >> SID  1: S-1-5-21-364438107-531279461-249741216-513
> > > > > 
> > > > > fwiw, this lists all groups of the user... Better example:
> > > > > 
> > > > > $ sudo ./bin/net cache samlogon show S-1-5-21-364438107-531279461-249741216-1003
> > > > > Name: SLOWSERVER\slow
> > > > > SID  0: S-1-5-21-364438107-531279461-249741216-1003
> > > > > SID  1: S-1-5-21-364438107-531279461-249741216-513
> > > > > SID  2: S-1-5-21-364438107-531279461-249741216-1010
> > > > > SID  3: S-1-5-21-364438107-531279461-249741216-1011
> > > > 
> > > > A mode that dump the whole cache entry with ndr_print
> > > > whould be useful, similar to "net primarytrust dumpinfo",
> > > > see https://git.samba.org/?p=samba.git;a=commitdiff;h=c7c17d9f503d6037aa
> > > 
> > > yup, though about that as well. Will add it...
> > 
> > patch attached.
> 
> here it is.

attached is an updated version where I removed an overlooked if(0) {...}.

Cheerio!
-slow
-------------- next part --------------
From 8e54f302db8739ca2bcee834c48b7629c16fd16c Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Mon, 3 Jul 2017 12:38:22 +0200
Subject: [PATCH 1/3] netlogon.idl: mark session keys with NDR_SECRET

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 librpc/idl/netlogon.idl | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/librpc/idl/netlogon.idl b/librpc/idl/netlogon.idl
index 9a5159d..22f86b9 100644
--- a/librpc/idl/netlogon.idl
+++ b/librpc/idl/netlogon.idl
@@ -231,11 +231,11 @@ interface netlogon
 		uint32 primary_gid;
 		samr_RidWithAttributeArray groups;
 		netr_UserFlags user_flags;
-		netr_UserSessionKey key;
+		[flag(NDR_SECRET)] netr_UserSessionKey key;
 		lsa_StringLarge logon_server;
 		lsa_StringLarge logon_domain;
 		dom_sid2 *domain_sid;
-		netr_LMSessionKey LMSessKey;
+		[flag(NDR_SECRET)] netr_LMSessionKey LMSessKey;
 		samr_AcctFlags acct_flags;
 		uint32 sub_auth_status;
 		NTTIME last_successful_logon;
-- 
2.9.4


From 2707477e63bc6fd03f7ab00c01a714b129951f5b Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 27 Jun 2017 17:34:34 +0200
Subject: [PATCH 2/3] samlogon_cache: add netsamlog_cache_for_all()

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/libsmb/samlogon_cache.c | 102 ++++++++++++++++++++++++++++++++++++++++
 source3/libsmb/samlogon_cache.h |   5 ++
 2 files changed, 107 insertions(+)

diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c
index 5a16686..0a2890e 100644
--- a/source3/libsmb/samlogon_cache.c
+++ b/source3/libsmb/samlogon_cache.c
@@ -291,3 +291,105 @@ bool netsamlogon_cache_have(const struct dom_sid *sid)
 	ok = tdb_exists(netsamlogon_tdb, string_term_tdb_data(keystr));
 	return ok;
 }
+
+struct netsamlog_cache_forall_state {
+	TALLOC_CTX *mem_ctx;
+	int (*cb)(const char *sid_str,
+		  time_t when_cached,
+		  struct netr_SamInfo3 *,
+		  void *private_data);
+	void *private_data;
+};
+
+static int netsamlog_cache_traverse_cb(struct tdb_context *tdb,
+				       TDB_DATA key,
+				       TDB_DATA data,
+				       void *private_data)
+{
+	struct netsamlog_cache_forall_state *state =
+		(struct netsamlog_cache_forall_state *)private_data;
+	TALLOC_CTX *mem_ctx = NULL;
+	DATA_BLOB blob;
+	const char *sid_str = NULL;
+	struct dom_sid sid;
+	struct netsamlogoncache_entry r;
+	enum ndr_err_code ndr_err;
+	int ret;
+	bool ok;
+
+	if (key.dsize == 0) {
+		return 0;
+	}
+	if (key.dptr[key.dsize - 1] != '\0') {
+		return 0;
+	}
+	if (data.dptr == NULL) {
+		return 0;
+	}
+	sid_str = (char *)key.dptr;
+
+	ok = string_to_sid(&sid, sid_str);
+	if (!ok) {
+		DBG_ERR("String to SID failed for %s\n", sid_str);
+		return -1;
+	}
+
+	if (sid.num_auths != 5) {
+		return 0;
+	}
+
+	mem_ctx = talloc_new(state->mem_ctx);
+	if (mem_ctx == NULL) {
+		return -1;
+	}
+
+	blob = data_blob_const(data.dptr, data.dsize);
+
+	ndr_err = ndr_pull_struct_blob(
+		&blob, state->mem_ctx, &r,
+		(ndr_pull_flags_fn_t)ndr_pull_netsamlogoncache_entry);
+
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		DBG_ERR("failed to pull entry from cache\n");
+		return -1;
+	}
+
+	ret = state->cb(sid_str, r.timestamp, &r.info3, state->private_data);
+
+	TALLOC_FREE(mem_ctx);
+	return ret;
+}
+
+int netsamlog_cache_for_all(int (*cb)(const char *sid_str,
+				      time_t when_cached,
+				      struct netr_SamInfo3 *,
+				      void *private_data),
+			    void *private_data)
+{
+	int ret;
+	TALLOC_CTX *mem_ctx = NULL;
+	struct netsamlog_cache_forall_state state;
+
+	if (!netsamlogon_cache_init()) {
+		DBG_ERR("Cannot open %s\n", NETSAMLOGON_TDB);
+		return -1;
+	}
+
+	mem_ctx = talloc_init("netsamlog_cache_for_all");
+	if (mem_ctx == NULL) {
+		return -1;
+	}
+
+	state = (struct netsamlog_cache_forall_state) {
+		.mem_ctx = mem_ctx,
+		.cb = cb,
+		.private_data = private_data,
+	};
+
+	ret = tdb_traverse_read(netsamlogon_tdb,
+				netsamlog_cache_traverse_cb,
+				&state);
+
+	TALLOC_FREE(state.mem_ctx);
+	return ret;
+}
diff --git a/source3/libsmb/samlogon_cache.h b/source3/libsmb/samlogon_cache.h
index 221e67b..29e0cea 100644
--- a/source3/libsmb/samlogon_cache.h
+++ b/source3/libsmb/samlogon_cache.h
@@ -37,5 +37,10 @@ bool netsamlogon_cache_store(const char *username,
 struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx,
 					    const struct dom_sid *user_sid);
 bool netsamlogon_cache_have(const struct dom_sid *sid);
+int netsamlog_cache_for_all(int (*cb)(const char *sid_str,
+				      time_t when_cached,
+				      struct netr_SamInfo3 *,
+				      void *private_data),
+			    void *private_data);
 
 #endif
-- 
2.9.4


From 0fc3b60f73a38ab48bf8aeb399081bf9f0aba732 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Wed, 28 Jun 2017 07:14:36 +0200
Subject: [PATCH 3/3] net: add net cache samlogon list|show|delete

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/utils/net_cache.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 227 insertions(+)

diff --git a/source3/utils/net_cache.c b/source3/utils/net_cache.c
index 4de3a6c..f02cf4d 100644
--- a/source3/utils/net_cache.c
+++ b/source3/utils/net_cache.c
@@ -19,6 +19,10 @@
 
 #include "includes.h"
 #include "net.h"
+#include "libsmb/samlogon_cache.h"
+#include "../librpc/gen_ndr/netlogon.h"
+#include "../librpc/gen_ndr/ndr_netlogon.h"
+#include "libcli/security/dom_sid.h"
 
 /**
  * @file net_cache.c
@@ -340,6 +344,221 @@ static int net_cache_stabilize(struct net_context *c, int argc,
 	}
 	return 0;
 }
+
+static int netsamlog_cache_for_all_cb(const char *sid_str,
+				      time_t when_cached,
+				      struct netr_SamInfo3 *info3,
+				      void *private_data)
+{
+	struct net_context *c = (struct net_context *)private_data;
+	char *name = NULL;
+
+	name = talloc_asprintf(c, "%s\\%s",
+			       info3->base.logon_domain.string,
+			       info3->base.account_name.string);
+	if (name == NULL) {
+		return -1;
+	}
+
+	d_printf("%-50s %-40s When cached\n", "SID", "Name");
+	d_printf("------------------------------------------------------------"
+		 "------------------------------------------------------------"
+		 "----\n");
+	d_printf("%-50s %-40s %s\n",
+		 sid_str,
+		 name,
+		 timestring(c, when_cached));
+
+	return 0;
+}
+
+static int net_cache_samlogon_list(struct net_context *c,
+				   int argc,
+				   const char **argv)
+{
+	return netsamlog_cache_for_all(netsamlog_cache_for_all_cb, c);
+
+	return 0;
+}
+
+static int net_cache_samlogon_show(struct net_context *c,
+				   int argc,
+				   const char **argv)
+{
+	const char *sid_str = argv[0];
+	struct dom_sid sid;
+	struct dom_sid *user_sids = NULL;
+	uint32_t num_user_sids;
+	struct netr_SamInfo3 *info3 = NULL;
+	char *name = NULL;
+	uint32_t i;
+	NTSTATUS status;
+	bool ok;
+
+	if (argc != 1 || c->display_usage) {
+		d_printf("%s\n"
+			 "net cache samlogon show SID\n"
+			 "    %s\n",
+			 _("Usage:"),
+			 _("Show samlogon cache entry for SID."));
+		return 0;
+	}
+
+	ok = string_to_sid(&sid, sid_str);
+	if (!ok) {
+		d_printf("String to SID failed for %s\n", sid_str);
+		return -1;
+	}
+
+	info3 = netsamlogon_cache_get(c, &sid);
+	if (info3 == NULL) {
+		d_printf("SID %s not found in samlogon cache\n", sid_str);
+		return -1;
+	}
+
+	name = talloc_asprintf(c, "%s\\%s",
+			       info3->base.logon_domain.string,
+			       info3->base.account_name.string);
+	if (name == NULL) {
+		return -1;
+	}
+
+	d_printf("Name: %s\n", name);
+
+	status = sid_array_from_info3(c,
+				      info3,
+				      &user_sids,
+				      &num_user_sids,
+				      true);
+	if (!NT_STATUS_IS_OK(status)) {
+		d_printf("sid_array_from_info3 failed for %s\n", sid_str);
+		return -1;
+	}
+
+	for (i = 0; i < num_user_sids; i++) {
+		d_printf("SID %2" PRIu32 ": %s\n",
+			 i, sid_string_dbg(&user_sids[i]));
+	}
+
+	return 0;
+}
+
+static int net_cache_samlogon_ndrdump(struct net_context *c,
+				      int argc,
+				      const char **argv)
+{
+	const char *sid_str = NULL;
+	struct dom_sid sid;
+	struct netr_SamInfo3 *info3 = NULL;
+	struct ndr_print *ndr_print = NULL;
+	bool ok;
+
+	if (argc != 1 || c->display_usage) {
+		d_printf(  "%s\n"
+			   "net cache samlogon ndrdump SID\n"
+			   "    %s\n",
+			   _("Usage:"),
+			   _("Show samlogon cache entry for SID."));
+		return 0;
+	}
+
+	sid_str = argv[0];
+
+	ok = string_to_sid(&sid, sid_str);
+	if (!ok) {
+		d_printf("String to SID failed for %s\n", sid_str);
+		return -1;
+	}
+
+	info3 = netsamlogon_cache_get(c, &sid);
+	if (info3 == NULL) {
+		d_printf("SID %s not found in samlogon cache\n", sid_str);
+		return -1;
+	}
+
+	ndr_print = talloc_zero(c, struct ndr_print);
+	if (ndr_print == NULL) {
+		d_printf("Could not allocate memory.\n");
+		return -1;
+	}
+
+	ndr_print->print = ndr_print_printf_helper;
+	ndr_print->depth = 1;
+	ndr_print_netr_SamInfo3(ndr_print, "netr_SamInfo3", info3);
+	TALLOC_FREE(ndr_print);
+
+	return 0;
+}
+
+static int net_cache_samlogon_delete(struct net_context *c,
+				     int argc,
+				     const char **argv)
+{
+	const char *sid_str = argv[0];
+	struct dom_sid sid;
+	bool ok;
+
+	if (argc != 1 || c->display_usage) {
+		d_printf(  "%s\n"
+			   "net cache samlogon delete SID\n"
+			   "    %s\n",
+			 _("Usage:"),
+			 _("Delete samlogon cache entry for SID."));
+		return 0;
+	}
+
+	ok = string_to_sid(&sid, sid_str);
+	if (!ok) {
+		d_printf("String to SID failed for %s\n", sid_str);
+		return -1;
+	}
+
+	netsamlogon_clear_cached_user(&sid);
+
+	return 0;
+}
+
+static int net_cache_samlogon(struct net_context *c, int argc, const char **argv)
+{
+	struct functable func[] = {
+		{
+			"list",
+			net_cache_samlogon_list,
+			NET_TRANSPORT_LOCAL,
+			N_("List samlogon cache"),
+			N_("net cache samlogon list\n"
+			   "    List samlogon cachen\n")
+		},
+		{
+			"show",
+			net_cache_samlogon_show,
+			NET_TRANSPORT_LOCAL,
+			N_("Show samlogon cache entry"),
+			N_("net cache samlogon show SID\n"
+			   "    Show samlogon cache entry\n")
+		},
+		{
+			"ndrdump",
+			net_cache_samlogon_ndrdump,
+			NET_TRANSPORT_LOCAL,
+			N_("Dump the samlogon cache entry NDR blob"),
+			N_("net cache samlogon ndrdump SID\n"
+			   "    Dump the samlogon cache entry NDR blob\n")
+		},
+		{
+			"delete",
+			net_cache_samlogon_delete,
+			NET_TRANSPORT_LOCAL,
+			N_("Delete samlogon cache entry"),
+			N_("net cache samlogon delete SID\n"
+			   "    Delete samlogon cache entry\n")
+		},
+		{NULL, NULL, 0, NULL, NULL}
+	};
+
+	return net_run_function(c, argc, argv, "net cache samlogon", func);
+}
+
 /**
  * Entry point to 'net cache' subfunctionality
  *
@@ -413,6 +632,14 @@ int net_cache(struct net_context *c, int argc, const char **argv)
 			N_("net cache stabilize\n"
 			   "  Move transient cache content to stable storage")
 		},
+		{
+			"samlogon",
+			net_cache_samlogon,
+			NET_TRANSPORT_LOCAL,
+			N_("List contents of the samlogon cache"),
+			N_("net cache samlogon\n"
+			   "  List contents of the samlogon cache")
+		},
 		{NULL, NULL, 0, NULL, NULL}
 	};
 
-- 
2.9.4



More information about the samba-technical mailing list