partial smbclient / smbcalcs merge

Roger Standridge roger at digitalfountain.com
Tue Jan 29 22:50:54 GMT 2002


My bad.  I found the patch submission page on the samba website: 
http://samba.org/samba-patches/.  I sending this quick followup to 
hopefully avoid several similar responses to the list.

-roger

Roger Standridge wrote:

> 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>
> 
> 
> ------------------------------------------------------------------------
> 
> 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