The branch, master has been updated via bc3fcb2 s3: docs: Add documentation for posix_whoami command in smbclient. via 17045c3 s3: smbclient: Add posix_whoami command. via 46695fa s3: libsmb: Add sync and async cli_posix_whoami(). from 92b4b6b s3-smbd: Support systemd 230
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit bc3fcb23fae3cf0daaab0bcbfde346931ef178bd Author: Jeremy Allison <j...@samba.org> Date: Wed May 25 09:17:40 2016 -0700 s3: docs: Add documentation for posix_whoami command in smbclient. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Thu May 26 02:43:55 CEST 2016 on sn-devel-144 commit 17045c315a3d66992049556c3c51eabb0e557088 Author: Jeremy Allison <j...@samba.org> Date: Wed May 25 09:15:13 2016 -0700 s3: smbclient: Add posix_whoami command. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> commit 46695fa2c8116d9ea52186b95587dbee9b1e103d Author: Jeremy Allison <j...@samba.org> Date: Tue May 24 16:58:11 2016 -0700 s3: libsmb: Add sync and async cli_posix_whoami(). Will add as a command to smbclient, plus will be useful for testing. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Uri Simchoni <u...@samba.org> ----------------------------------------------------------------------- Summary of changes: docs-xml/manpages/smbclient.1.xml | 8 ++ source3/client/client.c | 46 +++++++ source3/libsmb/clifsinfo.c | 260 ++++++++++++++++++++++++++++++++++++++ source3/libsmb/proto.h | 21 +++ 4 files changed, 335 insertions(+) Changeset truncated at 500 lines: 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> diff --git a/source3/client/client.c b/source3/client/client.c index 831b9bc..45dc11c 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}}, diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c index 6d5a86c..795d12b 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,262 @@ 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; + } + + /* + * Not strictly needed - cli_trans_recv() + * will ensure at least 40 bytes here. Added + * as more of a reminder to be careful when + * parsing network packets in C. + */ + + 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] = BVAL(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 */ -- Samba Shared Repository