[PATCH] Add posix_whoami command to smbclient.

Jeremy Allison jra at samba.org
Wed May 25 16:31:10 UTC 2016


Does what it says on the tin :-).

Adds async cli_posix_whoami interfaces to
the cliXXX library, and adds a command in
smbclient to execute it (plus documentation).

I'm doing this so it will be easier to write
tests that explore what the server process
token looks like under various different
setups.

It's also pretty handy for debugging
authorization problems for a logged-on
user.

Please review and push if happy !

Jeremy.
-------------- next part --------------
From 49c1a33953814612cb2f2ba977e5ebaff4f2350b Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 24 May 2016 16:58:11 -0700
Subject: [PATCH 1/3] s3: libsmb: Add sync and async cli_posix_whoami().

Will add as a comment to smbclient, plus will be useful for testing.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/libsmb/clifsinfo.c | 253 +++++++++++++++++++++++++++++++++++++++++++++
 source3/libsmb/proto.h     |  21 ++++
 2 files changed, 274 insertions(+)

diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c
index 6d5a86c..e989bf8 100644
--- a/source3/libsmb/clifsinfo.c
+++ b/source3/libsmb/clifsinfo.c
@@ -29,6 +29,7 @@
 #include "auth/gensec/gensec.h"
 #include "../libcli/smb/smbXcli_base.h"
 #include "auth/credentials/credentials.h"
+#include "../librpc/gen_ndr/ndr_security.h"
 
 /****************************************************************************
  Get UNIX extensions version info.
@@ -773,3 +774,255 @@ NTSTATUS cli_force_encryption(struct cli_state *c,
 					password,
 					domain);
 }
+
+/****************************************************************************
+ Do a UNIX extensions SMB_QUERY_POSIX_WHOAMI call.
+****************************************************************************/
+
+struct posix_whoami_state {
+	uint16_t setup[1];
+	uint8_t param[2];
+	uint32_t max_rdata;
+	bool guest;
+	uint64_t uid;
+	uint64_t gid;
+	uint32_t num_gids;
+	uint64_t *gids;
+	uint32_t num_sids;
+	struct dom_sid *sids;
+};
+
+static void cli_posix_whoami_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_posix_whoami_send(TALLOC_CTX *mem_ctx,
+					struct tevent_context *ev,
+					struct cli_state *cli)
+{
+	struct tevent_req *req = NULL, *subreq = NULL;
+	struct posix_whoami_state *state = NULL;
+
+	req = tevent_req_create(mem_ctx, &state, struct posix_whoami_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	/* Setup setup word. */
+	SSVAL(state->setup, 0, TRANSACT2_QFSINFO);
+	SSVAL(state->param, 0, SMB_QUERY_POSIX_WHOAMI);
+
+	state->max_rdata = 62*1024;
+
+	subreq = cli_trans_send(state,                  /* mem ctx. */
+				ev,                     /* event ctx. */
+				cli,                    /* cli_state. */
+				SMBtrans2,              /* cmd. */
+				NULL,                   /* pipe name. */
+				-1,                     /* fid. */
+				0,                      /* function. */
+				0,                      /* flags. */
+				state->setup,           /* setup. */
+				1,                      /* num setup uint16_t words. */
+				0,                      /* max returned setup. */
+				state->param,           /* param. */
+				2,                      /* num param. */
+				0,                      /* max returned param. */
+				NULL,	                /* data. */
+				0,                      /* num data. */
+				state->max_rdata);      /* max returned data. */
+
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, cli_posix_whoami_done, req);
+	return req;
+}
+
+static void cli_posix_whoami_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+			subreq, struct tevent_req);
+	struct posix_whoami_state *state = tevent_req_data(
+			req, struct posix_whoami_state);
+	uint8_t *rdata = NULL;
+	uint8_t *p = NULL;
+	uint32_t num_rdata = 0;
+	uint32_t i;
+	NTSTATUS status;
+
+	status = cli_trans_recv(subreq,
+				state,
+				NULL,
+				NULL,
+				0,
+				NULL,
+                                NULL,
+				0,
+				NULL,
+				&rdata,
+				40,
+				&num_rdata);
+	TALLOC_FREE(subreq);
+        if (tevent_req_nterror(req, status)) {
+                return;
+        }
+
+	if (num_rdata < 40 || rdata + num_rdata < rdata) {
+		tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+		return;
+	}
+
+	state->guest = (IVAL(rdata, 0) & SMB_WHOAMI_GUEST);
+	state->uid = BVAL(rdata, 8);
+	state->gid = BVAL(rdata, 16);
+	state->num_gids = IVAL(rdata, 24);
+	state->num_sids = IVAL(rdata, 28);
+
+	state->gids = talloc_array(state, uint64_t, state->num_gids);
+	if (tevent_req_nomem(state->gids, req)) {
+		return;
+	}
+	state->sids = talloc_array(state, struct dom_sid, state->num_sids);
+	if (tevent_req_nomem(state->sids, req)) {
+		return;
+	}
+
+	p = rdata + 40;
+
+	for (i = 0; i < state->num_gids; i++) {
+		if (p + 8 > rdata + num_rdata) {
+			tevent_req_nterror(req,
+				NT_STATUS_INVALID_NETWORK_RESPONSE);
+			return;
+		}
+		state->gids[i] = IVAL(p, 0);
+		p += 8;
+	}
+
+	num_rdata -= (p - rdata);
+
+	for (i = 0; i < state->num_sids; i++) {
+		size_t sid_size;
+		DATA_BLOB in = data_blob_const(p, num_rdata);
+		enum ndr_err_code ndr_err;
+
+		ndr_err = ndr_pull_struct_blob(&in,
+				state,
+				&state->sids[i],
+				(ndr_pull_flags_fn_t)ndr_pull_dom_sid);
+		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+			tevent_req_nterror(req,
+				NT_STATUS_INVALID_NETWORK_RESPONSE);
+			return;
+		}
+
+		sid_size = ndr_size_dom_sid(&state->sids[i], 0);
+
+		if (sid_size > num_rdata) {
+			tevent_req_nterror(req,
+				NT_STATUS_INVALID_NETWORK_RESPONSE);
+			return;
+		}
+
+		p += sid_size;
+		num_rdata -= sid_size;
+        }
+        tevent_req_done(req);
+}
+
+NTSTATUS cli_posix_whoami_recv(struct tevent_req *req,
+			TALLOC_CTX *mem_ctx,
+			uint64_t *puid,
+			uint64_t *pgid,
+			uint32_t *pnum_gids,
+			uint64_t **pgids,
+			uint32_t *pnum_sids,
+			struct dom_sid **psids,
+			bool *pguest)
+{
+	NTSTATUS status;
+	struct posix_whoami_state *state = tevent_req_data(
+			req, struct posix_whoami_state);
+
+	if (tevent_req_is_nterror(req, &status)) {
+		return status;
+	}
+
+	if (puid) {
+		*puid = state->uid;
+	}
+	if (pgid) {
+		*pgid = state->gid;
+	}
+	if (pnum_gids) {
+		*pnum_gids = state->num_gids;
+	}
+	if (pgids) {
+		*pgids = talloc_move(mem_ctx, &state->gids);
+	}
+	if (pnum_sids) {
+		*pnum_sids = state->num_sids;
+	}
+	if (psids) {
+		*psids = talloc_move(mem_ctx, &state->sids);
+	}
+	if (pguest) {
+		*pguest = state->guest;
+	}
+	return NT_STATUS_OK;
+}
+
+NTSTATUS cli_posix_whoami(struct cli_state *cli,
+			TALLOC_CTX *mem_ctx,
+			uint64_t *puid,
+			uint64_t *pgid,
+			uint32_t *num_gids,
+			uint64_t **gids,
+			uint32_t *num_sids,
+			struct dom_sid **sids,
+			bool *pguest)
+{
+        TALLOC_CTX *frame = talloc_stackframe();
+        struct tevent_context *ev = NULL;
+        struct tevent_req *req = NULL;
+        NTSTATUS status = NT_STATUS_OK;
+
+        if (smbXcli_conn_has_async_calls(cli->conn)) {
+                /*
+                 * Can't use sync call while an async call is in flight
+                 */
+                status = NT_STATUS_INVALID_PARAMETER;
+                goto fail;
+        }
+
+        ev = samba_tevent_context_init(frame);
+        if (ev == NULL) {
+                status = NT_STATUS_NO_MEMORY;
+                goto fail;
+        }
+
+        req = cli_posix_whoami_send(frame,
+                                ev,
+                                cli);
+        if (req == NULL) {
+                status = NT_STATUS_NO_MEMORY;
+                goto fail;
+        }
+
+        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+                goto fail;
+        }
+
+        status = cli_posix_whoami_recv(req,
+			mem_ctx,
+			puid,
+			pgid,
+			num_gids,
+			gids,
+			num_sids,
+			sids,
+			pguest);
+
+ fail:
+        TALLOC_FREE(frame);
+        return status;
+}
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index dc9aa17..1e358f7 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -682,6 +682,27 @@ NTSTATUS cli_force_encryption(struct cli_state *c,
 			const char *username,
 			const char *password,
 			const char *domain);
+struct tevent_req *cli_posix_whoami_send(TALLOC_CTX *mem_ctx,
+			struct tevent_context *ev,
+			struct cli_state *cli);
+NTSTATUS cli_posix_whoami_recv(struct tevent_req *req,
+			TALLOC_CTX *mem_ctx,
+			uint64_t *puid,
+			uint64_t *pgid,
+			uint32_t *pnum_gids,
+			uint64_t **pgids,
+			uint32_t *pnum_sids,
+			struct dom_sid **psids,
+			bool *pguest);
+NTSTATUS cli_posix_whoami(struct cli_state *cli,
+			TALLOC_CTX *mem_ctx,
+			uint64_t *puid,
+			uint64_t *pgid,
+			uint32_t *num_gids,
+			uint64_t **gids,
+			uint32_t *num_sids,
+			struct dom_sid **sids,
+			bool *pguest);
 
 /* The following definitions come from libsmb/clilist.c  */
 
-- 
2.8.0.rc3.226.g39d4020


From 2b671f19c07174002e6c5c5f349f70f87c888cbc Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Wed, 25 May 2016 09:15:13 -0700
Subject: [PATCH 2/3] s3: smbclient: Add posix_whoami command.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/client/client.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/source3/client/client.c b/source3/client/client.c
index 831b9bc..fe7ca46 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -2956,6 +2956,50 @@ static int cmd_unlock(void)
 	return 0;
 }
 
+static int cmd_posix_whoami(void)
+{
+	TALLOC_CTX *ctx = talloc_tos();
+	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+	uint64_t uid = 0;
+	uint64_t gid= 0;
+	uint32_t num_gids = 0;
+	uint32_t num_sids = 0;
+	uint64_t *gids = NULL;
+	struct dom_sid *sids = NULL;
+	bool guest = false;
+	uint32_t i;
+
+	status = cli_posix_whoami(cli,
+			ctx,
+			&uid,
+			&gid,
+			&num_gids,
+			&gids,
+			&num_sids,
+			&sids,
+			&guest);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		d_printf("posix_whoami failed with error %s\n", nt_errstr(status));
+		return 1;
+	}
+
+	d_printf("GUEST:%s\n", guest ? "True" : "False");
+	d_printf("uid:%" PRIu64 "\n", uid);
+	d_printf("gid:%" PRIu64 "\n", gid);
+	d_printf("num_gids:%" PRIu32 "\n", num_gids);
+	for (i = 0; i < num_gids; i++) {
+		d_printf("gids[%" PRIu32 "]:%" PRIu64 "\n", i, gids[i]);
+	}
+	d_printf("num_sids:%" PRIu32 "\n", num_sids);
+	for (i = 0; i < num_sids; i++) {
+		char *sid_str = dom_sid_string(ctx, &sids[i]);
+		d_printf("sids[%" PRIu32 "]:%s\n", i, sid_str);
+		TALLOC_FREE(sid_str);
+	}
+	return 0;
+}
+
 
 /****************************************************************************
  Remove a directory.
@@ -4931,6 +4975,8 @@ static struct {
   {"posix_mkdir",cmd_posix_mkdir,"<name> 0<mode> creates a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
   {"posix_rmdir",cmd_posix_rmdir,"<name> removes a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
   {"posix_unlink",cmd_posix_unlink,"<name> removes a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
+  {"posix_whoami",cmd_posix_whoami,"retun logged on user information "
+			"using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
   {"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
   {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}},
   {"put",cmd_put,"<local name> [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}},
-- 
2.8.0.rc3.226.g39d4020


From 09d3577d5d6b0da8910243ce63100727cc3668c7 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Wed, 25 May 2016 09:17:40 -0700
Subject: [PATCH 3/3] s3: docs: Add documentation for posix_whoami command in
 smbclient.

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 docs-xml/manpages/smbclient.1.xml | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/docs-xml/manpages/smbclient.1.xml b/docs-xml/manpages/smbclient.1.xml
index faf1ca1..6b5468a 100644
--- a/docs-xml/manpages/smbclient.1.xml
+++ b/docs-xml/manpages/smbclient.1.xml
@@ -924,6 +924,14 @@
 		</varlistentry>
 
 		<varlistentry>
+		<term>posix_whoami</term>
+		<listitem><para>Query the remote server for the user token using the CIFS UNIX
+		extensions WHOAMI call. Prints out the guest status, user, group, group list and
+		sid list that the remote server is using on behalf of the logged on user.
+		</para></listitem>
+		</varlistentry>
+
+		<varlistentry>
 		<term>print <file name></term>
 		<listitem><para>Print the specified file from the local machine
 		through a printable service on the server. </para></listitem>
-- 
2.8.0.rc3.226.g39d4020



More information about the samba-technical mailing list