📄 smbcacls.c
字号:
/* Unix SMB/CIFS implementation. ACL get/set utility 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 (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "includes.h"static pstring owner_username;static fstring server;static int test_args = False;static TALLOC_CTX *ctx;#define CREATE_ACCESS_READ READ_CONTROL_ACCESS/* numeric is set when the user wants numeric SIDs and ACEs rather than going via LSA calls to resolve them */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 { const char *perm; uint32 mask;};/* These values discovered by inspection */static const struct perm_value special_values[] = { { "R", 0x00120089 }, { "W", 0x00120116 }, { "X", 0x001200a0 }, { "D", 0x00010000 }, { "P", 0x00040000 }, { "O", 0x00080000 }, { NULL, 0 },};static const struct perm_value standard_values[] = { { "READ", 0x001200a9 }, { "CHANGE", 0x001301bf }, { "FULL", 0x001f01ff }, { NULL, 0 },};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){ /* Initialise cli LSA connection */ 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) { /* 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(rpccli_lsa_open_policy(global_pipe_hnd, global_hack_cli->mem_ctx, True, GENERIC_EXECUTE_ACCESS, &pol))) { return False; } got_policy_hnd = True; } return True;}/* 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; sid_to_string(str, sid); if (numeric) return; /* Ask LSA to convert the sid to a name */ if (!cacls_open_policy_hnd() || !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]); }/* convert a string to a SID, either numeric or username/group */static BOOL StringToSid(DOM_SID *sid, const char *str){ uint32 *types = NULL; DOM_SID *sids = NULL; BOOL result = True; if (strncmp(str, "S-", 2) == 0) { return string_to_sid(sid, str); } if (!cacls_open_policy_hnd() || !NT_STATUS_IS_OK(rpccli_lsa_lookup_names(global_pipe_hnd, global_hack_cli->mem_ctx, &pol, 1, &str, &sids, &types))) { result = False; goto done; } sid_copy(sid, &sids[0]); done: return result;}/* print an ACE on a FILE, using either numeric or ascii representation */static void print_ace(FILE *f, SEC_ACE *ace){ const struct perm_value *v; fstring sidstr; int do_print = 0; uint32 got_mask; SidToString(sidstr, &ace->trustee); fprintf(f, "%s:", sidstr); if (numeric) { fprintf(f, "%d/%d/0x%08x", ace->type, ace->flags, ace->info.mask); return; } /* Ace type */ if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED) { fprintf(f, "ALLOWED"); } else if (ace->type == SEC_ACE_TYPE_ACCESS_DENIED) { fprintf(f, "DENIED"); } else { fprintf(f, "%d", ace->type); } /* Not sure what flags can be set in a file ACL */ fprintf(f, "/%d/", ace->flags); /* Standard permissions */ for (v = standard_values; v->perm; v++) { if (ace->info.mask == v->mask) { fprintf(f, "%s", v->perm); return; } } /* Special permissions. Print out a hex value if we have leftover bits in the mask. */ got_mask = ace->info.mask; again: for (v = special_values; v->perm; v++) { if ((ace->info.mask & v->mask) == v->mask) { if (do_print) { fprintf(f, "%s", v->perm); } got_mask &= ~v->mask; } } if (!do_print) { if (got_mask != 0) { fprintf(f, "0x%08x", ace->info.mask); } else { do_print = 1; goto again; } }}/* parse an ACE in the same format as print_ace() */static BOOL parse_ace(SEC_ACE *ace, const char *orig_str){ char *p; const char *cp; fstring tok; unsigned int atype = 0; unsigned int aflags = 0; unsigned int amask = 0; DOM_SID sid; SEC_ACCESS mask; const struct perm_value *v; char *str = SMB_STRDUP(orig_str); if (!str) { return False; } ZERO_STRUCTP(ace); p = strchr_m(str,':'); 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 && StringToSid(&sid, str)) { goto done; } /* 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; } cp = p; if (!next_token(&cp, tok, "/", sizeof(fstring))) { printf("ACE '%s': failed to find '/' character.\n", orig_str); SAFE_FREE(str); return False; } if (strncmp(tok, "ALLOWED", strlen("ALLOWED")) == 0) { atype = SEC_ACE_TYPE_ACCESS_ALLOWED; } 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(&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(&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; } for (v = standard_values; v->perm; v++) { if (strcmp(tok, v->perm) == 0) { amask = v->mask; goto done; } } p = tok; while(*p) { BOOL found = False; for (v = special_values; v->perm; v++) { if (v->perm[0] == *p) { amask |= v->mask; found = True; } } 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; 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_ace; SEC_ACE *aces; if (! *the_acl) { (*the_acl) = make_sec_acl(ctx, 3, 1, ace); return True; } aces = SMB_CALLOC_ARRAY(SEC_ACE, 1+(*the_acl)->num_aces); memcpy(aces, (*the_acl)->ace, (*the_acl)->num_aces * sizeof(SEC_ACE)); memcpy(aces+(*the_acl)->num_aces, ace, sizeof(SEC_ACE)); 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){ const char *p = str; fstring tok; SEC_DESC *ret; size_t sd_size; DOM_SID *grp_sid=NULL, *owner_sid=NULL; SEC_ACL *dacl=NULL; int revision=1; while (next_token(&p, tok, "\t,\r\n", sizeof(tok))) { if (strncmp(tok,"REVISION:", 9) == 0) { revision = strtol(tok+9, NULL, 16); continue; } if (strncmp(tok,"OWNER:", 6) == 0) { 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; } continue; } if (strncmp(tok,"GROUP:", 6) == 0) { 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; } continue; } if (strncmp(tok,"ACL:", 4) == 0) { SEC_ACE ace; if (!parse_ace(&ace, tok+4)) { return NULL; } if(!add_ace(&dacl, &ace)) { printf("Failed to add ACL %s\n", tok); return NULL; } continue; } printf("Failed to parse token '%s' in security descriptor,\n", tok); return NULL; } ret = make_sec_desc(ctx,revision, SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL, dacl, &sd_size); SAFE_FREE(grp_sid); SAFE_FREE(owner_sid); return ret;}/* print a ascii version of a security descriptor on a FILE handle */static void sec_desc_print(FILE *f, SEC_DESC *sd){ fstring sidstr; uint32 i; fprintf(f, "REVISION:%d\n", sd->revision); /* Print owner and group sid */ if (sd->owner_sid) { SidToString(sidstr, sd->owner_sid); } else { fstrcpy(sidstr, ""); } fprintf(f, "OWNER:%s\n", sidstr); if (sd->grp_sid) { SidToString(sidstr, sd->grp_sid); } else { fstrcpy(sidstr, ""); } fprintf(f, "GROUP:%s\n", sidstr); /* Print aces */ for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) { SEC_ACE *ace = &sd->dacl->ace[i]; fprintf(f, "ACL:");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -