X-Git-Url: http://git.samba.org/samba.git/?p=bbaumbach%2Fsamba-autobuild%2F.git;a=blobdiff_plain;f=source3%2Futils%2Fsmbcacls.c;h=e4ab4e9283a117bdde43042c63372768d2002f39;hp=914e99367bb71a71ebbb083247b712e1ddb5b671;hb=d824b98f80ba186030cbb70b3a1e5daf80469ecd;hpb=b12a4dd9b655485420d5c67dd143d8f49ac28a40 diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c index 914e99367bb..e4ab4e9283a 100644 --- a/source3/utils/smbcacls.c +++ b/source3/utils/smbcacls.c @@ -1,15 +1,15 @@ /* - Unix SMB/Netbios implementation. + Unix SMB/CIFS implementation. ACL get/set utility - Version 3.0 Copyright (C) Andrew Tridgell 2000 Copyright (C) Tim Potter 2000 Copyright (C) Jeremy Allison 2000 + Copyright (C) Jelmer Vernooij 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -24,33 +24,29 @@ #include "includes.h" -static fstring password; -static pstring username; static pstring owner_username; static fstring server; -static int got_pass; -static int test_args; -TALLOC_CTX *ctx; +static int test_args = False; +static TALLOC_CTX *ctx; #define CREATE_ACCESS_READ READ_CONTROL_ACCESS -#define CREATE_ACCESS_WRITE (WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS) /* numeric is set when the user wants numeric SIDs and ACEs rather than going via LSA calls to resolve them */ -static int numeric; +static BOOL numeric = False; enum acl_mode {SMB_ACL_SET, SMB_ACL_DELETE, SMB_ACL_MODIFY, SMB_ACL_ADD }; enum chown_mode {REQUEST_NONE, REQUEST_CHOWN, REQUEST_CHGRP}; enum exit_values {EXIT_OK, EXIT_FAILED, EXIT_PARSE_ERROR}; struct perm_value { - char *perm; + const char *perm; uint32 mask; }; /* These values discovered by inspection */ -static struct perm_value special_values[] = { +static const struct perm_value special_values[] = { { "R", 0x00120089 }, { "W", 0x00120116 }, { "X", 0x001200a0 }, @@ -60,31 +56,35 @@ static struct perm_value special_values[] = { { NULL, 0 }, }; -static struct perm_value standard_values[] = { +static const struct perm_value standard_values[] = { { "READ", 0x001200a9 }, { "CHANGE", 0x001301bf }, { "FULL", 0x001f01ff }, { NULL, 0 }, }; -struct cli_state lsa_cli; -POLICY_HND pol; -struct ntuser_creds creds; -BOOL got_policy_hnd; +static struct cli_state *global_hack_cli; +static struct rpc_pipe_client *global_pipe_hnd; +static POLICY_HND pol; +static BOOL got_policy_hnd; + +static struct cli_state *connect_one(const char *share); /* Open cli connection and policy handle */ static BOOL cacls_open_policy_hnd(void) { - creds.pwd.null_pwd = 1; - /* Initialise cli LSA connection */ - if (!lsa_cli.initialised && - !cli_lsa_initialise(&lsa_cli, server, &creds)) { - return False; + if (!global_hack_cli) { + NTSTATUS ret; + global_hack_cli = connect_one("IPC$"); + global_pipe_hnd = cli_rpc_pipe_open_noauth(global_hack_cli, PI_LSARPC, &ret); + if (!global_pipe_hnd) { + return False; + } } - + /* Open policy handle */ if (!got_policy_hnd) { @@ -92,7 +92,7 @@ static BOOL cacls_open_policy_hnd(void) /* Some systems don't support SEC_RIGHTS_MAXIMUM_ALLOWED, but NT sends 0x2000000 so we might as well do it too. */ - if (!NT_STATUS_IS_OK(cli_lsa_open_policy(&lsa_cli, lsa_cli.mem_ctx, True, + if (!NT_STATUS_IS_OK(rpccli_lsa_open_policy(global_pipe_hnd, global_hack_cli->mem_ctx, True, GENERIC_EXECUTE_ACCESS, &pol))) { return False; } @@ -106,9 +106,9 @@ static BOOL cacls_open_policy_hnd(void) /* convert a SID to a string, either numeric or username/group */ static void SidToString(fstring str, DOM_SID *sid) { + char **domains = NULL; char **names = NULL; - uint32 *types = NULL; - int num_names; + enum lsa_SidType *types = NULL; sid_to_string(str, sid); @@ -117,38 +117,41 @@ static void SidToString(fstring str, DOM_SID *sid) /* Ask LSA to convert the sid to a name */ if (!cacls_open_policy_hnd() || - !NT_STATUS_IS_OK(cli_lsa_lookup_sids(&lsa_cli, lsa_cli.mem_ctx, &pol, 1, sid, &names, - &types, &num_names)) || - !names || !names[0]) { + !NT_STATUS_IS_OK(rpccli_lsa_lookup_sids(global_pipe_hnd, global_hack_cli->mem_ctx, + &pol, 1, sid, &domains, + &names, &types)) || + !domains || !domains[0] || !names || !names[0]) { return; } /* Converted OK */ + + slprintf(str, sizeof(fstring) - 1, "%s%s%s", + domains[0], lp_winbind_separator(), + names[0]); - fstrcpy(str, names[0]); } /* convert a string to a SID, either numeric or username/group */ -static BOOL StringToSid(DOM_SID *sid, char *str) +static BOOL StringToSid(DOM_SID *sid, const char *str) { - uint32 *types = NULL; + enum lsa_SidType *types = NULL; DOM_SID *sids = NULL; - int num_sids; BOOL result = True; - + if (strncmp(str, "S-", 2) == 0) { return string_to_sid(sid, str); } if (!cacls_open_policy_hnd() || - !NT_STATUS_IS_OK(cli_lsa_lookup_names(&lsa_cli, lsa_cli.mem_ctx, &pol, 1, &str, - &sids, &types, &num_sids))) { + !NT_STATUS_IS_OK(rpccli_lsa_lookup_names(global_pipe_hnd, global_hack_cli->mem_ctx, + &pol, 1, &str, NULL, 1, &sids, + &types))) { result = False; goto done; } sid_copy(sid, &sids[0]); - done: return result; @@ -158,18 +161,18 @@ static BOOL StringToSid(DOM_SID *sid, char *str) /* print an ACE on a FILE, using either numeric or ascii representation */ static void print_ace(FILE *f, SEC_ACE *ace) { - struct perm_value *v; + const struct perm_value *v; fstring sidstr; int do_print = 0; uint32 got_mask; - SidToString(sidstr, &ace->sid); + SidToString(sidstr, &ace->trustee); fprintf(f, "%s:", sidstr); if (numeric) { fprintf(f, "%d/%d/0x%08x", - ace->type, ace->flags, ace->info.mask); + ace->type, ace->flags, ace->access_mask); return; } @@ -190,7 +193,7 @@ static void print_ace(FILE *f, SEC_ACE *ace) /* Standard permissions */ for (v = standard_values; v->perm; v++) { - if (ace->info.mask == v->mask) { + if (ace->access_mask == v->mask) { fprintf(f, "%s", v->perm); return; } @@ -199,11 +202,11 @@ static void print_ace(FILE *f, SEC_ACE *ace) /* Special permissions. Print out a hex value if we have leftover bits in the mask. */ - got_mask = ace->info.mask; + got_mask = ace->access_mask; again: for (v = special_values; v->perm; v++) { - if ((ace->info.mask & v->mask) == v->mask) { + if ((ace->access_mask & v->mask) == v->mask) { if (do_print) { fprintf(f, "%s", v->perm); } @@ -213,7 +216,7 @@ static void print_ace(FILE *f, SEC_ACE *ace) if (!do_print) { if (got_mask != 0) { - fprintf(f, "0x%08x", ace->info.mask); + fprintf(f, "0x%08x", ace->access_mask); } else { do_print = 1; goto again; @@ -223,21 +226,32 @@ static void print_ace(FILE *f, SEC_ACE *ace) /* parse an ACE in the same format as print_ace() */ -static BOOL parse_ace(SEC_ACE *ace, char *str) +static BOOL parse_ace(SEC_ACE *ace, const char *orig_str) { char *p; + const char *cp; fstring tok; - unsigned atype, aflags, amask; + unsigned int atype = 0; + unsigned int aflags = 0; + unsigned int amask = 0; DOM_SID sid; SEC_ACCESS mask; - struct perm_value *v; + const struct perm_value *v; + char *str = SMB_STRDUP(orig_str); + + if (!str) { + return False; + } ZERO_STRUCTP(ace); p = strchr_m(str,':'); - if (!p) return False; + if (!p) { + printf("ACE '%s': missing ':'.\n", orig_str); + SAFE_FREE(str); + return False; + } *p = '\0'; p++; - /* Try to parse numeric form */ if (sscanf(p, "%i/%i/%i", &atype, &aflags, &amask) == 3 && @@ -248,10 +262,17 @@ static BOOL parse_ace(SEC_ACE *ace, char *str) /* Try to parse text form */ if (!StringToSid(&sid, str)) { + printf("ACE '%s': failed to convert '%s' to SID\n", + orig_str, str); + SAFE_FREE(str); return False; } - if (!next_token(&p, tok, "/", sizeof(fstring))) { + cp = p; + if (!next_token(&cp, tok, "/", sizeof(fstring))) { + printf("ACE '%s': failed to find '/' character.\n", + orig_str); + SAFE_FREE(str); return False; } @@ -260,22 +281,34 @@ static BOOL parse_ace(SEC_ACE *ace, char *str) } else if (strncmp(tok, "DENIED", strlen("DENIED")) == 0) { atype = SEC_ACE_TYPE_ACCESS_DENIED; } else { + printf("ACE '%s': missing 'ALLOWED' or 'DENIED' entry at '%s'\n", + orig_str, tok); + SAFE_FREE(str); return False; } /* Only numeric form accepted for flags at present */ - if (!(next_token(&p, tok, "/", sizeof(fstring)) && + if (!(next_token(&cp, tok, "/", sizeof(fstring)) && sscanf(tok, "%i", &aflags))) { + printf("ACE '%s': bad integer flags entry at '%s'\n", + orig_str, tok); + SAFE_FREE(str); return False; } - if (!next_token(&p, tok, "/", sizeof(fstring))) { + if (!next_token(&cp, tok, "/", sizeof(fstring))) { + printf("ACE '%s': missing / at '%s'\n", + orig_str, tok); + SAFE_FREE(str); return False; } if (strncmp(tok, "0x", 2) == 0) { if (sscanf(tok, "%i", &amask) != 1) { + printf("ACE '%s': bad hex number at '%s'\n", + orig_str, tok); + SAFE_FREE(str); return False; } goto done; @@ -300,45 +333,53 @@ static BOOL parse_ace(SEC_ACE *ace, char *str) } } - if (!found) return False; + if (!found) { + printf("ACE '%s': bad permission value at '%s'\n", + orig_str, p); + SAFE_FREE(str); + return False; + } p++; } if (*p) { + SAFE_FREE(str); return False; } done: - mask.mask = amask; + mask = amask; init_sec_ace(ace, &sid, atype, mask, aflags); + SAFE_FREE(str); return True; } /* add an ACE to a list of ACEs in a SEC_ACL */ static BOOL add_ace(SEC_ACL **the_acl, SEC_ACE *ace) { - SEC_ACL *new; + SEC_ACL *new_ace; SEC_ACE *aces; if (! *the_acl) { - (*the_acl) = make_sec_acl(ctx, 3, 1, ace); - return True; + return (((*the_acl) = make_sec_acl(ctx, 3, 1, ace)) != NULL); } - aces = calloc(1+(*the_acl)->num_aces,sizeof(SEC_ACE)); - memcpy(aces, (*the_acl)->ace, (*the_acl)->num_aces * sizeof(SEC_ACE)); + if (!(aces = SMB_CALLOC_ARRAY(SEC_ACE, 1+(*the_acl)->num_aces))) { + return False; + } + memcpy(aces, (*the_acl)->aces, (*the_acl)->num_aces * sizeof(SEC_ACE)); memcpy(aces+(*the_acl)->num_aces, ace, sizeof(SEC_ACE)); - new = make_sec_acl(ctx,(*the_acl)->revision,1+(*the_acl)->num_aces, aces); - free(aces); - (*the_acl) = new; + new_ace = make_sec_acl(ctx,(*the_acl)->revision,1+(*the_acl)->num_aces, aces); + SAFE_FREE(aces); + (*the_acl) = new_ace; return True; } /* parse a ascii version of a security descriptor */ static SEC_DESC *sec_desc_parse(char *str) { - char *p = str; + const char *p = str; fstring tok; - SEC_DESC *ret; + SEC_DESC *ret = NULL; size_t sd_size; DOM_SID *grp_sid=NULL, *owner_sid=NULL; SEC_ACL *dacl=NULL; @@ -352,21 +393,29 @@ static SEC_DESC *sec_desc_parse(char *str) } if (strncmp(tok,"OWNER:", 6) == 0) { - owner_sid = (DOM_SID *)calloc(1, sizeof(DOM_SID)); + if (owner_sid) { + printf("Only specify owner once\n"); + goto done; + } + owner_sid = SMB_CALLOC_ARRAY(DOM_SID, 1); if (!owner_sid || !StringToSid(owner_sid, tok+6)) { printf("Failed to parse owner sid\n"); - return NULL; + goto done; } continue; } if (strncmp(tok,"GROUP:", 6) == 0) { - grp_sid = (DOM_SID *)calloc(1, sizeof(DOM_SID)); + if (grp_sid) { + printf("Only specify group once\n"); + goto done; + } + grp_sid = SMB_CALLOC_ARRAY(DOM_SID, 1); if (!grp_sid || !StringToSid(grp_sid, tok+6)) { printf("Failed to parse group sid\n"); - return NULL; + goto done; } continue; } @@ -374,25 +423,25 @@ static SEC_DESC *sec_desc_parse(char *str) if (strncmp(tok,"ACL:", 4) == 0) { SEC_ACE ace; if (!parse_ace(&ace, tok+4)) { - printf("Failed to parse ACL %s\n", tok); - return NULL; + goto done; } if(!add_ace(&dacl, &ace)) { printf("Failed to add ACL %s\n", tok); - return NULL; + goto done; } continue; } - printf("Failed to parse security descriptor\n"); - return NULL; + printf("Failed to parse token '%s' in security descriptor,\n", tok); + goto done; } - ret = make_sec_desc(ctx,revision, owner_sid, grp_sid, + ret = make_sec_desc(ctx,revision, SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL, dacl, &sd_size); - if (grp_sid) free(grp_sid); - if (owner_sid) free(owner_sid); + done: + SAFE_FREE(grp_sid); + SAFE_FREE(owner_sid); return ret; } @@ -402,9 +451,9 @@ static SEC_DESC *sec_desc_parse(char *str) static void sec_desc_print(FILE *f, SEC_DESC *sd) { fstring sidstr; - int i; + uint32 i; - printf("REVISION:%d\n", sd->revision); + fprintf(f, "REVISION:%d\n", sd->revision); /* Print owner and group sid */ @@ -414,10 +463,10 @@ static void sec_desc_print(FILE *f, SEC_DESC *sd) fstrcpy(sidstr, ""); } - printf("OWNER:%s\n", sidstr); + fprintf(f, "OWNER:%s\n", sidstr); - if (sd->grp_sid) { - SidToString(sidstr, sd->grp_sid); + if (sd->group_sid) { + SidToString(sidstr, sd->group_sid); } else { fstrcpy(sidstr, ""); } @@ -426,7 +475,7 @@ static void sec_desc_print(FILE *f, SEC_DESC *sd) /* Print aces */ for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) { - SEC_ACE *ace = &sd->dacl->ace[i]; + SEC_ACE *ace = &sd->dacl->aces[i]; fprintf(f, "ACL:"); print_ace(f, ace); fprintf(f, "\n"); @@ -439,29 +488,36 @@ dump the acls for a file *******************************************************/ static int cacl_dump(struct cli_state *cli, char *filename) { - int fnum; + int result = EXIT_FAILED; + int fnum = -1; SEC_DESC *sd; - if (test_args) return EXIT_OK; + if (test_args) + return EXIT_OK; fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ); + if (fnum == -1) { printf("Failed to open %s: %s\n", filename, cli_errstr(cli)); - return EXIT_FAILED; + goto done; } sd = cli_query_secdesc(cli, fnum, ctx); if (!sd) { printf("ERROR: secdesc query failed: %s\n", cli_errstr(cli)); - return EXIT_FAILED; + goto done; } sec_desc_print(stdout, sd); - cli_close(cli, fnum); + result = EXIT_OK; - return EXIT_OK; +done: + if (fnum != -1) + cli_close(cli, fnum); + + return result; } /***************************************************** @@ -496,12 +552,12 @@ static int owner_set(struct cli_state *cli, enum chown_mode change_mode, return EXIT_FAILED; } - sd = make_sec_desc(ctx,old->revision, - (change_mode == REQUEST_CHOWN) ? &sid : old->owner_sid, - (change_mode == REQUEST_CHGRP) ? &sid : old->grp_sid, - NULL, old->dacl, &sd_size); + sd = make_sec_desc(ctx,old->revision, old->type, + (change_mode == REQUEST_CHOWN) ? &sid : NULL, + (change_mode == REQUEST_CHGRP) ? &sid : NULL, + NULL, NULL, &sd_size); - fnum = cli_nt_create(cli, filename, CREATE_ACCESS_WRITE); + fnum = cli_nt_create(cli, filename, WRITE_OWNER_ACCESS); if (fnum == -1) { printf("Failed to open %s: %s\n", filename, cli_errstr(cli)); @@ -525,27 +581,39 @@ static int owner_set(struct cli_state *cli, enum chown_mode change_mode, static int ace_compare(SEC_ACE *ace1, SEC_ACE *ace2) { - if (sec_ace_equal(ace1, ace2)) return 0; - if (ace1->type != ace2->type) return ace2->type - ace1->type; - if (sid_compare(&ace1->sid, &ace2->sid)) return sid_compare(&ace1->sid, &ace2->sid); - if (ace1->flags != ace2->flags) return ace1->flags - ace2->flags; - if (ace1->info.mask != ace2->info.mask) return ace1->info.mask - ace2->info.mask; - if (ace1->size != ace2->size) return ace1->size - ace2->size; + if (sec_ace_equal(ace1, ace2)) + return 0; + + if (ace1->type != ace2->type) + return ace2->type - ace1->type; + + if (sid_compare(&ace1->trustee, &ace2->trustee)) + return sid_compare(&ace1->trustee, &ace2->trustee); + + if (ace1->flags != ace2->flags) + return ace1->flags - ace2->flags; + + if (ace1->access_mask != ace2->access_mask) + return ace1->access_mask - ace2->access_mask; + + if (ace1->size != ace2->size) + return ace1->size - ace2->size; + return memcmp(ace1, ace2, sizeof(SEC_ACE)); } static void sort_acl(SEC_ACL *the_acl) { - int i; + uint32 i; if (!the_acl) return; - qsort(the_acl->ace, the_acl->num_aces, sizeof(the_acl->ace[0]), QSORT_CAST ace_compare); + qsort(the_acl->aces, the_acl->num_aces, sizeof(the_acl->aces[0]), QSORT_CAST ace_compare); for (i=1;inum_aces;) { - if (sec_ace_equal(&the_acl->ace[i-1], &the_acl->ace[i])) { + if (sec_ace_equal(&the_acl->aces[i-1], &the_acl->aces[i])) { int j; for (j=i; jnum_aces-1; j++) { - the_acl->ace[j] = the_acl->ace[j+1]; + the_acl->aces[j] = the_acl->aces[j+1]; } the_acl->num_aces--; } else { @@ -562,7 +630,7 @@ static int cacl_set(struct cli_state *cli, char *filename, { int fnum; SEC_DESC *sd, *old; - int i, j; + uint32 i, j; size_t sd_size; int result = EXIT_OK; @@ -597,20 +665,13 @@ static int cacl_set(struct cli_state *cli, char *filename, BOOL found = False; for (j=0;old->dacl && jdacl->num_aces;j++) { - if (sec_ace_equal(&sd->dacl->ace[i], - &old->dacl->ace[j])) { - int k; + if (sec_ace_equal(&sd->dacl->aces[i], + &old->dacl->aces[j])) { + uint32 k; for (k=j; kdacl->num_aces-1;k++) { - old->dacl->ace[k] = old->dacl->ace[k+1]; + old->dacl->aces[k] = old->dacl->aces[k+1]; } old->dacl->num_aces--; - if (old->dacl->num_aces == 0) { - free(old->dacl->ace); - old->dacl->ace=NULL; - free(old->dacl); - old->dacl = NULL; - old->off_dacl = 0; - } found = True; break; } @@ -618,7 +679,7 @@ static int cacl_set(struct cli_state *cli, char *filename, if (!found) { printf("ACL for ACE:"); - print_ace(stdout, &sd->dacl->ace[i]); + print_ace(stdout, &sd->dacl->aces[i]); printf(" not found\n"); } } @@ -629,9 +690,9 @@ static int cacl_set(struct cli_state *cli, char *filename, BOOL found = False; for (j=0;old->dacl && jdacl->num_aces;j++) { - if (sid_equal(&sd->dacl->ace[i].sid, - &old->dacl->ace[j].sid)) { - old->dacl->ace[j] = sd->dacl->ace[i]; + if (sid_equal(&sd->dacl->aces[i].trustee, + &old->dacl->aces[j].trustee)) { + old->dacl->aces[j] = sd->dacl->aces[i]; found = True; } } @@ -639,16 +700,24 @@ static int cacl_set(struct cli_state *cli, char *filename, if (!found) { fstring str; - SidToString(str, &sd->dacl->ace[i].sid); + SidToString(str, &sd->dacl->aces[i].trustee); printf("ACL for SID %s not found\n", str); } } + if (sd->owner_sid) { + old->owner_sid = sd->owner_sid; + } + + if (sd->group_sid) { + old->group_sid = sd->group_sid; + } + break; case SMB_ACL_ADD: for (i=0;sd->dacl && idacl->num_aces;i++) { - add_ace(&old->dacl, &sd->dacl->ace[i]); + add_ace(&old->dacl, &sd->dacl->aces[i]); } break; @@ -661,11 +730,24 @@ static int cacl_set(struct cli_state *cli, char *filename, sort_acl(old->dacl); /* Create new security descriptor and set it */ - sd = make_sec_desc(ctx,old->revision, old->owner_sid, old->grp_sid, +#if 0 + /* We used to just have "WRITE_DAC_ACCESS" without WRITE_OWNER. + But if we're sending an owner, even if it's the same as the one + that already exists then W2K3 insists we open with WRITE_OWNER access. + I need to check that setting a SD with no owner set works against WNT + and W2K. JRA. + */ + + sd = make_sec_desc(ctx,old->revision, old->type, old->owner_sid, old->grp_sid, NULL, old->dacl, &sd_size); - fnum = cli_nt_create(cli, filename, CREATE_ACCESS_WRITE); + fnum = cli_nt_create(cli, filename, WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS); +#else + sd = make_sec_desc(ctx,old->revision, old->type, NULL, NULL, + NULL, old->dacl, &sd_size); + fnum = cli_nt_create(cli, filename, WRITE_DAC_ACCESS); +#endif if (fnum == -1) { printf("cacl_set failed to open %s: %s\n", filename, cli_errstr(cli)); return EXIT_FAILED; @@ -687,244 +769,145 @@ static int cacl_set(struct cli_state *cli, char *filename, /***************************************************** return a connection to a server *******************************************************/ -struct cli_state *connect_one(char *share) +static struct cli_state *connect_one(const char *share) { struct cli_state *c; - struct nmb_name called, calling; struct in_addr ip; - extern struct in_addr ipzero; - extern pstring global_myname; - - fstrcpy(server,share+2); - share = strchr_m(server,'\\'); - if (!share) return NULL; - *share = 0; - share++; - - ip = ipzero; - - make_nmb_name(&calling, global_myname, 0x0); - make_nmb_name(&called , server, 0x20); - - again: - ip = ipzero; - - /* have to open a new connection */ - if (!(c=cli_initialise(NULL)) || !cli_connect(c, server, &ip)) { - DEBUG(0,("Connection to %s failed\n", server)); - cli_shutdown(c); - safe_free(c); - return NULL; - } - - if (!cli_session_request(c, &calling, &called)) { - DEBUG(0,("session request to %s failed\n", called.name)); - cli_shutdown(c); - safe_free(c); - if (strcmp(called.name, "*SMBSERVER")) { - make_nmb_name(&called , "*SMBSERVER", 0x20); - goto again; - } - return NULL; - } - - DEBUG(4,(" session request ok\n")); - - if (!cli_negprot(c)) { - DEBUG(0,("protocol negotiation failed\n")); - cli_shutdown(c); - safe_free(c); - return NULL; - } - - if (!got_pass) { + NTSTATUS nt_status; + zero_ip(&ip); + + if (!cmdline_auth_info.got_pass) { char *pass = getpass("Password: "); if (pass) { - pstrcpy(password, pass); + pstrcpy(cmdline_auth_info.password, pass); + cmdline_auth_info.got_pass = True; } } - if (!cli_session_setup(c, username, - password, strlen(password), - password, strlen(password), - lp_workgroup())) { - DEBUG(0,("session setup failed: %s\n", cli_errstr(c))); - cli_shutdown(c); - safe_free(c); - return NULL; - } - - DEBUG(4,(" session setup ok\n")); - - if (!cli_send_tconX(c, share, "?????", - password, strlen(password)+1)) { - DEBUG(0,("tree connect failed: %s\n", cli_errstr(c))); - cli_shutdown(c); - safe_free(c); + if (NT_STATUS_IS_OK(nt_status = cli_full_connection(&c, global_myname(), server, + &ip, 0, + share, "?????", + cmdline_auth_info.username, lp_workgroup(), + cmdline_auth_info.password, 0, + cmdline_auth_info.signing_state, NULL))) { + return c; + } else { + DEBUG(0,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status))); return NULL; } - - DEBUG(4,(" tconx ok\n")); - - return c; -} - - -static void usage(void) -{ - printf( -"Usage: smbcacls //server1/share1 filename [options]\n\ -\n\ -\t-D delete an acl\n\ -\t-M modify an acl\n\ -\t-A add an acl\n\ -\t-S set acls\n\ -\t-C username change ownership of a file\n\ -\t-G username change group ownership of a file\n\ -\t-n don't resolve sids or masks to names\n\ -\t-h print help\n\ -\t-d debuglevel set debug output level\n\ -\t-U username user to autheticate as\n\ -\n\ -The username can be of the form username%%password or\n\ -workgroup\\username%%password.\n\n\ -An acl is of the form ACL::type/flags/mask\n\ -You can string acls together with spaces, commas or newlines\n\ -"); } /**************************************************************************** main program ****************************************************************************/ - int main(int argc,char *argv[]) + int main(int argc, const char *argv[]) { char *share; - pstring filename; - extern char *optarg; - extern int optind; int opt; - char *p; - static pstring servicesf = CONFIGFILE; - struct cli_state *cli=NULL; enum acl_mode mode = SMB_ACL_SET; - char *the_acl = NULL; + static char *the_acl = NULL; enum chown_mode change_mode = REQUEST_NONE; int result; - - ctx=talloc_init(); - - setlinebuf(stdout); - + fstring path; + pstring filename; + poptContext pc; + struct poptOption long_options[] = { + POPT_AUTOHELP + { "delete", 'D', POPT_ARG_STRING, NULL, 'D', "Delete an acl", "ACL" }, + { "modify", 'M', POPT_ARG_STRING, NULL, 'M', "Modify an acl", "ACL" }, + { "add", 'a', POPT_ARG_STRING, NULL, 'a', "Add an acl", "ACL" }, + { "set", 'S', POPT_ARG_STRING, NULL, 'S', "Set acls", "ACLS" }, + { "chown", 'C', POPT_ARG_STRING, NULL, 'C', "Change ownership of a file", "USERNAME" }, + { "chgrp", 'G', POPT_ARG_STRING, NULL, 'G', "Change group ownership of a file", "GROUPNAME" }, + { "numeric", 0, POPT_ARG_NONE, &numeric, True, "Don't resolve sids or masks to names" }, + { "test-args", 't', POPT_ARG_NONE, &test_args, True, "Test arguments"}, + POPT_COMMON_SAMBA + POPT_COMMON_CREDENTIALS + { NULL } + }; + + struct cli_state *cli; + + load_case_tables(); + + ctx=talloc_init("main"); + + /* set default debug level to 1 regardless of what smb.conf sets */ + setup_logging( "smbcacls", True ); + DEBUGLEVEL_CLASS[DBGC_ALL] = 1; dbf = x_stderr; + x_setbuf( x_stderr, NULL ); - if (argc < 3 || argv[1][0] == '-') { - usage(); - talloc_destroy(ctx); - exit(EXIT_PARSE_ERROR); - } - - setup_logging(argv[0],True); - - share = argv[1]; - pstrcpy(filename, argv[2]); - all_string_sub(share,"/","\\",0); - - argc -= 2; - argv += 2; - - TimeInit(); + setlinebuf(stdout); - lp_load(servicesf,True,False,False); + lp_load(dyn_CONFIGFILE,True,False,False,True); load_interfaces(); - if (getenv("USER")) { - pstrcpy(username,getenv("USER")); - - if ((p=strchr_m(username,'%'))) { - *p = 0; - pstrcpy(password,p+1); - got_pass = True; - memset(strchr_m(getenv("USER"), '%') + 1, 'X', - strlen(password)); - } - } + pc = poptGetContext("smbcacls", argc, argv, long_options, 0); + + poptSetOtherOptionHelp(pc, "//server1/share1 filename\nACLs look like: " + "'ACL:user:[ALLOWED|DENIED]/flags/permissions'"); - while ((opt = getopt(argc, argv, "U:nhS:D:A:M:C:G:td:")) != EOF) { + while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { - case 'U': - pstrcpy(username,optarg); - p = strchr_m(username,'%'); - if (p) { - *p = 0; - pstrcpy(password, p+1); - got_pass = 1; - } - break; - case 'S': - the_acl = optarg; + the_acl = smb_xstrdup(poptGetOptArg(pc)); mode = SMB_ACL_SET; break; case 'D': - the_acl = optarg; + the_acl = smb_xstrdup(poptGetOptArg(pc)); mode = SMB_ACL_DELETE; break; case 'M': - the_acl = optarg; + the_acl = smb_xstrdup(poptGetOptArg(pc)); mode = SMB_ACL_MODIFY; break; - case 'A': - the_acl = optarg; + case 'a': + the_acl = smb_xstrdup(poptGetOptArg(pc)); mode = SMB_ACL_ADD; break; case 'C': - pstrcpy(owner_username,optarg); + pstrcpy(owner_username,poptGetOptArg(pc)); change_mode = REQUEST_CHOWN; break; case 'G': - pstrcpy(owner_username,optarg); + pstrcpy(owner_username,poptGetOptArg(pc)); change_mode = REQUEST_CHGRP; break; - - case 'n': - numeric = 1; - break; - - case 't': - test_args = 1; - break; - - case 'h': - usage(); - talloc_destroy(ctx); - exit(EXIT_PARSE_ERROR); - - case 'd': - DEBUGLEVEL = atoi(optarg); - break; - - default: - printf("Unknown option %c (%d)\n", (char)opt, opt); - talloc_destroy(ctx); - exit(EXIT_PARSE_ERROR); } } - argc -= optind; - argv += optind; + /* Make connection to server */ + if(!poptPeekArg(pc)) { + poptPrintUsage(pc, stderr, 0); + return -1; + } + + fstrcpy(path, poptGetArg(pc)); - if (argc > 0) { - usage(); - talloc_destroy(ctx); - exit(EXIT_PARSE_ERROR); + if(!poptPeekArg(pc)) { + poptPrintUsage(pc, stderr, 0); + return -1; } + + pstrcpy(filename, poptGetArg(pc)); - /* Make connection to server */ + all_string_sub(path,"/","\\",0); + + fstrcpy(server,path+2); + share = strchr_m(server,'\\'); + if (!share) { + printf("Invalid argument: %s\n", share); + return -1; + } + + *share = 0; + share++; if (!test_args) { cli = connect_one(share); @@ -932,13 +915,15 @@ You can string acls together with spaces, commas or newlines\n\ talloc_destroy(ctx); exit(EXIT_FAILED); } + } else { + exit(0); } all_string_sub(filename, "/", "\\", 0); if (filename[0] != '\\') { pstring s; s[0] = '\\'; - safe_strcpy(&s[1], filename, sizeof(pstring)-1); + safe_strcpy(&s[1], filename, sizeof(pstring)-2); pstrcpy(filename, s); }