partial smbclient / smbcalcs merge
Roger Standridge
roger at digitalfountain.com
Tue Jan 29 22:27:20 GMT 2002
My first post, I am going to write it as if I have targeted the right
place, sorry if I haven't... where should it go?
Attached is a patch against the 2.2.2 release that adds a 'showacl'
(show access control list) command to smbclient. Essentially I copied
part of util/smbcalcs.c into client/client.c and modified the display
format.
<example interaction>
smb: \> help showacl
HELP showacl:
<remote name> [-n | --numeric | -x | --explicit]
show access control list for remote file
smb: \> showacl 1.txt
REVISION:1
OWNER:BUILTIN\Administrators
GROUP:DIGITALFOUNTAIN\Developers
ACL:DIGITALFOUNTAIN\joeuser:ALLOWED/3/Modify
ACL:Everyone:ALLOWED/16/Full Control
smb: \> showacl 1.txt -n
REVISION:1
OWNER:S-1-5-32-544
GROUP:S-1-5-21-1533814122-1651835022-184960113-1005
ACL:S-1-5-21-1533814122-1651835022-184960113-1087:0/3/0x001301bf
ACL:S-1-1-0:0/16/0x001f01ff
smb: \> showacl 1.txt --explicit
REVISION:1
OWNER:BUILTIN\Administrators
GROUP:DIGITALFOUNTAIN\Developers
ACL:DIGITALFOUNTAIN\joeuser:ALLOWED/3/
FILE_READ_DATA
FILE_WRITE_DATA
FILE_APPEND_DATA
FILE_READ_EA
FILE_WRITE_EA
FILE_EXECUTE
FILE_READ_ATTRIBUTES
FILE_WRITE_ATTRIBUTES
DELETE
READ_CONTROL
SYNCHRONIZE
ACL:Everyone:ALLOWED/16/
FILE_READ_DATA
FILE_WRITE_DATA
FILE_APPEND_DATA
FILE_READ_EA
FILE_WRITE_EA
FILE_EXECUTE
FILE_DELETE_CHILD
FILE_READ_ATTRIBUTES
FILE_WRITE_ATTRIBUTES
DELETE
READ_CONTROL
WRITE_DAC
WRITE_OWNER
SYNCHRONIZE
</example interaction>
Notes:
o Permission summary strings mimic those from W2K permission control
dialog (Read / Write / Read & Execute / Modify / Full Control).
I found the MS cacls program too broken to bother imitating.
o -n or --numeric option displays in the numeric format of the
original smbcacls program
o -x or --explicit option displays the string equivelant of
each permission, one per line below the ace (much like the
MS cacls program.
o tried to mimic the code style of the original, sorry if I missed
o only compiled on Debian GNU/Linux i386, Potato and Sid
(But there is very little new code here).
o usage extends multiple lines, sorry, not consistent
o accepts relative and absolute paths of filenames as well
as '.' and '..' (other commands do not)
o tested only against W2K
o Makefile.in patch needlessly changes style of CLIENT_OBJ and
SMBCACLS_OBJ variables.
o options follow filename... seemed the right thing to do,
but I don't see any other commands that take options (similar
things seem to be done by placing smbclient in recursive mode,
etc.).
o Summary permission strings work both for ALLOWED and DENIED
access control lists, but I discovered that SYNCHRONIZE was
not in the bit-mask for DENIED ACEs..., so I blanked out
checking for it... blah, blah... needs investigation.
-Roger Standridge
<roger @ digitalfountain.com>
-------------- next part --------------
diff -rc samba-2.2.2-10.orig/source/Makefile.in samba-2.2.2-10-smbclient-showalc-patched/source/Makefile.in
*** samba-2.2.2-10.orig/source/Makefile.in Wed Jan 23 11:33:19 2002
--- samba-2.2.2-10-smbclient-showalc-patched/source/Makefile.in Tue Jan 29 10:37:25 2002
***************
*** 283,290 ****
LIBSMBCLIENT_OBJ = libsmb/libsmbclient.o $(LIB_OBJ) $(LIBSMB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ)
CLIENT_OBJ = client/client.o client/clitar.o \
! $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
! $(READLINE_OBJ)
CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ)
--- 283,309 ----
LIBSMBCLIENT_OBJ = libsmb/libsmbclient.o $(LIB_OBJ) $(LIBSMB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ)
CLIENT_OBJ = client/client.o client/clitar.o \
! $(PARAM_OBJ) \
! $(LIBSMB_OBJ) \
! $(UBIQX_OBJ) \
! $(LIB_OBJ) \
! $(LIBMSRPC_OBJ) \
! $(RPC_PARSE_OBJ) \
! $(PASSDB_OBJ) \
! \
! $(READLINE_OBJ)
!
! SMBCACLS_OBJ = utils/smbcacls.o \
! $(PARAM_OBJ) \
! $(LIBSMB_OBJ) \
! $(UBIQX_OBJ) \
! $(LIB_OBJ) \
! $(LIBMSRPC_OBJ) \
! $(RPC_PARSE_OBJ) \
! $(PASSDB_OBJ) \
! \
! $(LOCKING_OBJ)
!
CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ)
***************
*** 311,321 ****
LOCKTEST_OBJ = utils/locktest.o $(LOCKING_OBJ) $(LIBSMB_OBJ) $(PARAM_OBJ) \
$(UBIQX_OBJ) $(LIB_OBJ)
-
- SMBCACLS_OBJ = utils/smbcacls.o $(LOCKING_OBJ) $(LIBSMB_OBJ) $(PARAM_OBJ) \
- $(UBIQX_OBJ) $(LIB_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_OBJ) \
- $(LIBMSRPC_OBJ)
-
LOCKTEST2_OBJ = utils/locktest2.o $(LOCKING_OBJ) $(LIBSMB_OBJ) $(PARAM_OBJ) \
$(UBIQX_OBJ) $(LIB_OBJ)
--- 330,335 ----
diff -rc samba-2.2.2-10.orig/source/client/client.c samba-2.2.2-10-smbclient-showalc-patched/source/client/client.c
*** samba-2.2.2-10.orig/source/client/client.c Wed Jan 23 11:33:19 2002
--- samba-2.2.2-10-smbclient-showalc-patched/source/client/client.c Tue Jan 29 10:37:09 2002
***************
*** 34,39 ****
--- 34,40 ----
pstring cd_path = "";
static pstring service;
static pstring desthost;
+ static pstring servername;
extern pstring global_myname;
static pstring password;
static pstring username;
***************
*** 1682,1687 ****
--- 1683,1986 ----
}
/****************************************************************************
+ show access control list for file. (rws)
+ (Code taken from utils/smbcalcs.c)
+ ****************************************************************************/
+
+ struct cli_state lsa_cli;
+ POLICY_HND pol;
+
+ /* Open cli connection and policy handle */
+ static BOOL open_policy_hnd(void)
+ {
+ /* Were globals in smbcalcs.*/
+ static BOOL got_policy_hnd = False;
+ static struct ntuser_creds creds;
+
+ creds.pwd.null_pwd = 1;
+
+ /* Initialise cli LSA connection */
+ if (!lsa_cli.initialised &&
+ !cli_lsa_initialise(&lsa_cli, servername, &creds)) {
+ return False;
+ }
+
+ /* Open policy handle */
+
+ if (!got_policy_hnd) {
+
+ /* Some systems don't support SEC_RIGHTS_MAXIMUM_ALLOWED,
+ but NT sends 0x2000000 so we might as well do it too. */
+
+ if (cli_lsa_open_policy(&lsa_cli, lsa_cli.mem_ctx, True,
+ GENERIC_EXECUTE_ACCESS, &pol)
+ != NT_STATUS_OK) {
+ return False;
+ }
+
+ got_policy_hnd = True;
+ }
+
+ return True;
+ }
+
+ /* Access Control Entry output format codes. */
+ enum AceDisplayForm
+ {
+ FORM_NORMAL, /* Attempt standard string description first. */
+ FORM_NUMERIC, /* Only output numeric values. */
+ FORM_EXPLICIT /* Explicitly list the permissions. */
+ };
+
+ /* convert a SID to a string, either numeric or username/group */
+ static void SidToString(fstring str, DOM_SID *sid, enum AceDisplayForm form)
+ {
+ char **names = NULL;
+ uint32 *types = NULL;
+ int num_names;
+
+ sid_to_string(str, sid);
+
+ if (FORM_NUMERIC == form)
+ return;
+
+ /* Ask LSA to convert the sid to a name */
+ if (!open_policy_hnd())
+ {
+ DEBUG(0, ("Error in open_policy_hnd()\n"));
+ return;
+ }
+ if (cli_lsa_lookup_sids(&lsa_cli, lsa_cli.mem_ctx,
+ &pol, 1, sid, &names, &types,
+ &num_names) != NT_STATUS_OK ||
+ !names || !names[0]) {
+ return;
+ }
+
+ /* Converted OK */
+ fstrcpy(str, names[0]);
+ }
+
+ /* Structure for mapping bit fields in access
+ control entries to string descriptions. */
+ struct perm_value {
+ char *perm;
+ uint32 mask;
+ };
+
+ /* Names of bit fields within acess control entry permission mask */
+ static struct perm_value explicit_values[] =
+ {
+ { "FILE_READ_DATA", FILE_READ_DATA },
+ { "FILE_WRITE_DATA", FILE_WRITE_DATA },
+ { "FILE_APPEND_DATA", FILE_APPEND_DATA },
+ { "FILE_READ_EA", FILE_READ_EA },
+ { "FILE_WRITE_EA", FILE_WRITE_EA },
+ { "FILE_EXECUTE", FILE_EXECUTE },
+ { "FILE_DELETE_CHILD", FILE_DELETE_CHILD },
+ { "FILE_READ_ATTRIBUTES", FILE_READ_ATTRIBUTES },
+ { "FILE_WRITE_ATTRIBUTES", FILE_WRITE_ATTRIBUTES },
+
+ { "DELETE", DELETE_ACCESS },
+ { "READ_CONTROL", READ_CONTROL_ACCESS },
+ { "WRITE_DAC", WRITE_DAC_ACCESS },
+ { "WRITE_OWNER", WRITE_OWNER_ACCESS },
+ { "SYNCHRONIZE", SYNCHRONIZE_ACCESS },
+ { NULL, 0 },
+ };
+
+ /*
+ Standard values for file permissions (in W2K). Discovered by
+ testing... then looking in smb.h ;).
+
+ MS cacls just seemed too messed up to imitate its behavior.
+
+ Masking out the SYNCHRONIZE_ACCESS values because the 'denied'
+ access control entries do not seem to have them for standard values.
+ */
+ static struct perm_value standard_values[] =
+ {
+ { "Read",
+ (FILE_GENERIC_READ)
+ & ~SYNCHRONIZE_ACCESS },
+
+ { "Read & Execute",
+ (FILE_GENERIC_EXECUTE
+ | FILE_GENERIC_READ)
+ & ~SYNCHRONIZE_ACCESS },
+
+ /* I don't think smb.h has FILE_GENERIC_WRITE correct
+ (or it isn't what I think it is ;). */
+ { "Write",
+ (FILE_WRITE_DATA
+ | FILE_APPEND_DATA
+ | FILE_WRITE_EA
+ | FILE_WRITE_ATTRIBUTES)
+ & ~SYNCHRONIZE_ACCESS },
+
+ { "Modify",
+ (FILE_GENERIC_READ
+ | FILE_GENERIC_WRITE
+ | FILE_GENERIC_EXECUTE
+ | DELETE_ACCESS)
+ & ~SYNCHRONIZE_ACCESS },
+
+ { "Full Control",
+ (FILE_GENERIC_ALL)
+ & ~SYNCHRONIZE_ACCESS },
+
+ { NULL, 0 },
+ };
+
+ static void print_ace(SEC_ACE *ace, enum AceDisplayForm form)
+ {
+ const char * indent = " ";
+ struct perm_value *v;
+ fstring sidstr;
+ uint32 leftover;
+ uint32 tmp_mask;
+
+ SidToString(sidstr, &ace->sid, form);
+
+ DEBUG(0,("%s:", sidstr));
+
+ if (FORM_NUMERIC == form ) {
+ DEBUG(0,("%d/%d/0x%08x",
+ ace->type, ace->flags, ace->info.mask));
+ return;
+ }
+
+ /* Ace type */
+
+ if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED) {
+ DEBUG(0,("ALLOWED"));
+ } else if (ace->type == SEC_ACE_TYPE_ACCESS_DENIED) {
+ DEBUG(0,("DENIED"));
+ } else {
+ DEBUG(0,("%d", ace->type));
+ }
+
+ /* Not sure what flags can be set in a file ACL */
+ DEBUG(0,("/%d/", ace->flags));
+
+ /* Standard permissions, (rws : w2k form) */
+ if (FORM_NORMAL == form) {
+ /* Mask out the SYNCHRONIZE_ACCESS */
+ tmp_mask = ace->info.mask & ~SYNCHRONIZE_ACCESS;
+ for (v = standard_values; v->perm; v++) {
+ if (tmp_mask == v->mask) {
+ DEBUG(0,("%s", v->perm));
+ return;
+ }
+ }
+ DEBUG(0,("(special access:)"));
+ }
+
+ /* Print each access description, 1 per line, indented. */
+ leftover = ace->info.mask;
+ for (v = explicit_values; v->perm; v++) {
+ if ((ace->info.mask & v->mask)) {
+ leftover &= ~v->mask;
+ DEBUG(0,("\n%s%s", indent, v->perm));
+ }
+ }
+ if (leftover) DEBUG(0,("\n%suninterpreted : 0x%08x",
+ indent, leftover));
+ }
+
+ static void cmd_showacl(void)
+ {
+ #define SHOWACL_USAGE "<remote name> [-n | --numeric | -x | --explicit] \n"
+
+ int fnum;
+ fstring filename;
+ fstring buf;
+ enum AceDisplayForm form = FORM_NORMAL;
+ int i;
+ SEC_DESC *sd;
+ TALLOC_CTX *ctx;
+
+ /* - get/convert filename option - */
+ if (!next_token(NULL,buf,NULL,sizeof(filename))) {
+ DEBUG(0,(SHOWACL_USAGE));
+ return;
+ }
+ string_replace( buf, '/','\\');
+
+ /* allow '.' and '..' converting them to '.\' and '.\\' */
+ if (strequal(buf, ".") || strequal(buf, ".."))
+ pstrcat(buf, "\\");
+
+ /* construct full name, leading '\'
+ indicates absolute path */
+ if (strnequal(buf, "\\", 1)) {
+ pstrcpy(filename, buf);
+ } else {
+ pstrcpy(filename, cur_dir);
+ pstrcat(filename, buf);
+ }
+ dos_clean_name(filename);
+ DEBUG(3,("file name : %s\n", filename));
+
+ /* - get format option - */
+ if (next_token(NULL,buf,NULL,sizeof(buf))) {
+ if (strequal("-n", buf) ||
+ strnequal("--n", buf, strlen("--n"))) {
+ form = FORM_NUMERIC;
+
+ } else if(strequal("-x", buf) ||
+ strnequal("--e",buf, strlen("--e"))) {
+ form = FORM_EXPLICIT;
+
+ } else {
+ DEBUG(0, (SHOWACL_USAGE));
+ return;
+ }
+ }
+
+ /* - Reject further options - */
+ if (next_token(NULL,buf,NULL,sizeof(buf))) {
+ DEBUG(0, (SHOWACL_USAGE));
+ return;
+ }
+
+ /* - Retrieve - */
+ if (-1 == (fnum = cli_nt_create(cli, filename, READ_CONTROL_ACCESS))) {
+ printf("Failed to open %s: %s\n", filename, cli_errstr(cli));
+ return;
+ }
+
+ if (!(sd = cli_query_secdesc(cli, fnum, ctx))) {
+ printf("ERROR: secdesc query failed: %s\n", cli_errstr(cli));
+ return;
+ }
+
+ /* - Print - */
+ /* revision should be '1' */
+ DEBUG(0,("REVISION:%d\n", sd->revision));
+
+ /* Print owner sid */
+ if (sd->owner_sid) SidToString(buf, sd->owner_sid, form);
+ else fstrcpy(buf, "");
+ DEBUG(0,("OWNER:%s\n", buf));
+
+ /* Print group sid */
+ if (sd->grp_sid) SidToString(buf, sd->grp_sid, form);
+ else fstrcpy(buf, "");
+ DEBUG(0,("GROUP:%s\n", buf));
+
+ /* Print access control entries */
+ for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
+ SEC_ACE *ace = &sd->dacl->ace[i];
+ DEBUG(0,("ACL:"));
+ print_ace(ace, form);
+ DEBUG(0,("\n"));
+ }
+
+ cli_close(cli, fnum);
+ }
+
+ /****************************************************************************
try and browse available connections on a host
****************************************************************************/
static BOOL list_servers(char *wk_grp)
***************
*** 1756,1761 ****
--- 2055,2063 ----
{"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
{"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
{"history",cmd_history,"displays the command history",{COMPL_NONE,COMPL_NONE}},
+ {"showacl",cmd_showacl,
+ SHOWACL_USAGE "\tshow access control list for remote file",
+ {COMPL_NONE,COMPL_NONE}},
{"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}},
{"",NULL,NULL,{COMPL_NONE,COMPL_NONE}}
};
***************
*** 1984,1989 ****
--- 2286,2292 ----
sharename = strchr(server,'\\');
if (!sharename) return NULL;
*sharename = 0;
+ fstrcpy(servername, servicename);
sharename++;
}
More information about the smb-clients
mailing list