void SidToString(struct cli_state *cli, fstring str, const struct dom_sid *sid,
bool numeric);
bool StringToSid(struct cli_state *cli, struct dom_sid *sid, const char *str);
+void print_ace(struct cli_state *cli, FILE *f, struct security_ace *ace,
+ bool numeric);
+bool parse_ace(struct cli_state *cli, struct security_ace *ace,
+ const char *orig_str);
#endif
#include "rpc_client/cli_pipe.h"
#include "rpc_client/cli_lsarpc.h"
+/* These values discovered by inspection */
+
+struct perm_value {
+ const char *perm;
+ uint32 mask;
+};
+
+static const struct perm_value special_values[] = {
+ { "R", SEC_RIGHTS_FILE_READ },
+ { "W", SEC_RIGHTS_FILE_WRITE },
+ { "X", SEC_RIGHTS_FILE_EXECUTE },
+ { "D", SEC_STD_DELETE },
+ { "P", SEC_STD_WRITE_DAC },
+ { "O", SEC_STD_WRITE_OWNER },
+ { NULL, 0 },
+};
+
+static const struct perm_value standard_values[] = {
+ { "READ", SEC_RIGHTS_DIR_READ|SEC_DIR_TRAVERSE },
+ { "CHANGE", SEC_RIGHTS_DIR_READ|SEC_STD_DELETE|\
+ SEC_RIGHTS_DIR_WRITE|SEC_DIR_TRAVERSE },
+ { "FULL", SEC_RIGHTS_DIR_ALL },
+ { NULL, 0 },
+};
+
/* Open cli connection and policy handle */
static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli,
const struct dom_sid *sid,
return NT_STATUS_IS_OK(cli_lsa_lookup_name(cli, str, &type, sid));
}
+
+static void print_ace_flags(FILE *f, uint8_t flags)
+{
+ char *str = talloc_strdup(NULL, "");
+
+ if (!str) {
+ goto out;
+ }
+
+ if (flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
+ str = talloc_asprintf(str, "%s%s",
+ str, "OI|");
+ if (!str) {
+ goto out;
+ }
+ }
+ if (flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
+ str = talloc_asprintf(str, "%s%s",
+ str, "CI|");
+ if (!str) {
+ goto out;
+ }
+ }
+ if (flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
+ str = talloc_asprintf(str, "%s%s",
+ str, "NP|");
+ if (!str) {
+ goto out;
+ }
+ }
+ if (flags & SEC_ACE_FLAG_INHERIT_ONLY) {
+ str = talloc_asprintf(str, "%s%s",
+ str, "IO|");
+ if (!str) {
+ goto out;
+ }
+ }
+ if (flags & SEC_ACE_FLAG_INHERITED_ACE) {
+ str = talloc_asprintf(str, "%s%s",
+ str, "I|");
+ if (!str) {
+ goto out;
+ }
+ }
+ /* Ignore define SEC_ACE_FLAG_SUCCESSFUL_ACCESS ( 0x40 )
+ and SEC_ACE_FLAG_FAILED_ACCESS ( 0x80 ) as they're
+ audit ace flags. */
+
+ if (str[strlen(str)-1] == '|') {
+ str[strlen(str)-1] = '\0';
+ fprintf(f, "/%s/", str);
+ } else {
+ fprintf(f, "/0x%x/", flags);
+ }
+ TALLOC_FREE(str);
+ return;
+
+ out:
+ fprintf(f, "/0x%x/", flags);
+}
+
+/* print an ACE on a FILE, using either numeric or ascii representation */
+void print_ace(struct cli_state *cli, FILE *f, struct security_ace *ace,
+ bool numeric)
+{
+ const struct perm_value *v;
+ fstring sidstr;
+ int do_print = 0;
+ uint32 got_mask;
+
+ SidToString(cli, sidstr, &ace->trustee, numeric);
+
+ fprintf(f, "%s:", sidstr);
+
+ if (numeric) {
+ fprintf(f, "%d/0x%x/0x%08x",
+ ace->type, ace->flags, ace->access_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);
+ }
+
+ print_ace_flags(f, ace->flags);
+
+ /* Standard permissions */
+
+ for (v = standard_values; v->perm; v++) {
+ if (ace->access_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->access_mask;
+
+ again:
+ for (v = special_values; v->perm; v++) {
+ if ((ace->access_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->access_mask);
+ } else {
+ do_print = 1;
+ goto again;
+ }
+ }
+}
+
+static bool parse_ace_flags(const char *str, unsigned int *pflags)
+{
+ const char *p = str;
+ *pflags = 0;
+
+ while (*p) {
+ if (strnequal(p, "OI", 2)) {
+ *pflags |= SEC_ACE_FLAG_OBJECT_INHERIT;
+ p += 2;
+ } else if (strnequal(p, "CI", 2)) {
+ *pflags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
+ p += 2;
+ } else if (strnequal(p, "NP", 2)) {
+ *pflags |= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
+ p += 2;
+ } else if (strnequal(p, "IO", 2)) {
+ *pflags |= SEC_ACE_FLAG_INHERIT_ONLY;
+ p += 2;
+ } else if (*p == 'I') {
+ *pflags |= SEC_ACE_FLAG_INHERITED_ACE;
+ p += 1;
+ } else if (*p) {
+ return false;
+ }
+
+ switch (*p) {
+ case '|':
+ p++;
+ case '\0':
+ continue;
+ default:
+ return false;
+ }
+ }
+ return true;
+}
+
+/* parse an ACE in the same format as print_ace() */
+bool parse_ace(struct cli_state *cli, struct security_ace *ace,
+ const char *orig_str)
+{
+ char *p;
+ const char *cp;
+ char *tok;
+ unsigned int atype = 0;
+ unsigned int aflags = 0;
+ unsigned int amask = 0;
+ struct dom_sid sid;
+ uint32_t mask;
+ const struct perm_value *v;
+ char *str = SMB_STRDUP(orig_str);
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ if (!str) {
+ TALLOC_FREE(frame);
+ return False;
+ }
+
+ ZERO_STRUCTP(ace);
+ p = strchr_m(str,':');
+ if (!p) {
+ printf("ACE '%s': missing ':'.\n", orig_str);
+ SAFE_FREE(str);
+ TALLOC_FREE(frame);
+ return False;
+ }
+ *p = '\0';
+ p++;
+ /* Try to parse numeric form */
+
+ if (sscanf(p, "%u/%u/%u", &atype, &aflags, &amask) == 3 &&
+ StringToSid(cli, &sid, str)) {
+ goto done;
+ }
+
+ /* Try to parse text form */
+
+ if (!StringToSid(cli, &sid, str)) {
+ printf("ACE '%s': failed to convert '%s' to SID\n",
+ orig_str, str);
+ SAFE_FREE(str);
+ TALLOC_FREE(frame);
+ return False;
+ }
+
+ cp = p;
+ if (!next_token_talloc(frame, &cp, &tok, "/")) {
+ printf("ACE '%s': failed to find '/' character.\n",
+ orig_str);
+ SAFE_FREE(str);
+ TALLOC_FREE(frame);
+ 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);
+ TALLOC_FREE(frame);
+ return False;
+ }
+
+ /* Only numeric form accepted for flags at present */
+
+ if (!next_token_talloc(frame, &cp, &tok, "/")) {
+ printf("ACE '%s': bad flags entry at '%s'\n",
+ orig_str, tok);
+ SAFE_FREE(str);
+ TALLOC_FREE(frame);
+ return False;
+ }
+
+ if (tok[0] < '0' || tok[0] > '9') {
+ if (!parse_ace_flags(tok, &aflags)) {
+ printf("ACE '%s': bad named flags entry at '%s'\n",
+ orig_str, tok);
+ SAFE_FREE(str);
+ TALLOC_FREE(frame);
+ return False;
+ }
+ } else if (strnequal(tok, "0x", 2)) {
+ if (!sscanf(tok, "%x", &aflags)) {
+ printf("ACE '%s': bad hex flags entry at '%s'\n",
+ orig_str, tok);
+ SAFE_FREE(str);
+ TALLOC_FREE(frame);
+ return False;
+ }
+ } else {
+ if (!sscanf(tok, "%u", &aflags)) {
+ printf("ACE '%s': bad integer flags entry at '%s'\n",
+ orig_str, tok);
+ SAFE_FREE(str);
+ TALLOC_FREE(frame);
+ return False;
+ }
+ }
+
+ if (!next_token_talloc(frame, &cp, &tok, "/")) {
+ printf("ACE '%s': missing / at '%s'\n",
+ orig_str, tok);
+ SAFE_FREE(str);
+ TALLOC_FREE(frame);
+ return False;
+ }
+
+ if (strncmp(tok, "0x", 2) == 0) {
+ if (sscanf(tok, "%u", &amask) != 1) {
+ printf("ACE '%s': bad hex number at '%s'\n",
+ orig_str, tok);
+ SAFE_FREE(str);
+ TALLOC_FREE(frame);
+ 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);
+ TALLOC_FREE(frame);
+ return False;
+ }
+ p++;
+ }
+
+ if (*p) {
+ TALLOC_FREE(frame);
+ SAFE_FREE(str);
+ return False;
+ }
+
+ done:
+ mask = amask;
+ init_sec_ace(ace, &sid, atype, mask, aflags);
+ TALLOC_FREE(frame);
+ SAFE_FREE(str);
+ return True;
+}
enum chown_mode {REQUEST_NONE, REQUEST_CHOWN, REQUEST_CHGRP, REQUEST_INHERIT};
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", SEC_RIGHTS_FILE_READ },
- { "W", SEC_RIGHTS_FILE_WRITE },
- { "X", SEC_RIGHTS_FILE_EXECUTE },
- { "D", SEC_STD_DELETE },
- { "P", SEC_STD_WRITE_DAC },
- { "O", SEC_STD_WRITE_OWNER },
- { NULL, 0 },
-};
-
-static const struct perm_value standard_values[] = {
- { "READ", SEC_RIGHTS_DIR_READ|SEC_DIR_TRAVERSE },
- { "CHANGE", SEC_RIGHTS_DIR_READ|SEC_STD_DELETE|\
- SEC_RIGHTS_DIR_WRITE|SEC_DIR_TRAVERSE },
- { "FULL", SEC_RIGHTS_DIR_ALL },
- { NULL, 0 },
-};
-
static NTSTATUS cli_lsa_lookup_domain_sid(struct cli_state *cli,
struct dom_sid *sid)
{
return sid;
}
-static void print_ace_flags(FILE *f, uint8_t flags)
-{
- char *str = talloc_strdup(NULL, "");
-
- if (!str) {
- goto out;
- }
-
- if (flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
- str = talloc_asprintf(str, "%s%s",
- str, "OI|");
- if (!str) {
- goto out;
- }
- }
- if (flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
- str = talloc_asprintf(str, "%s%s",
- str, "CI|");
- if (!str) {
- goto out;
- }
- }
- if (flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
- str = talloc_asprintf(str, "%s%s",
- str, "NP|");
- if (!str) {
- goto out;
- }
- }
- if (flags & SEC_ACE_FLAG_INHERIT_ONLY) {
- str = talloc_asprintf(str, "%s%s",
- str, "IO|");
- if (!str) {
- goto out;
- }
- }
- if (flags & SEC_ACE_FLAG_INHERITED_ACE) {
- str = talloc_asprintf(str, "%s%s",
- str, "I|");
- if (!str) {
- goto out;
- }
- }
- /* Ignore define SEC_ACE_FLAG_SUCCESSFUL_ACCESS ( 0x40 )
- and SEC_ACE_FLAG_FAILED_ACCESS ( 0x80 ) as they're
- audit ace flags. */
-
- if (str[strlen(str)-1] == '|') {
- str[strlen(str)-1] = '\0';
- fprintf(f, "/%s/", str);
- } else {
- fprintf(f, "/0x%x/", flags);
- }
- TALLOC_FREE(str);
- return;
-
- out:
- fprintf(f, "/0x%x/", flags);
-}
-
-/* print an ACE on a FILE, using either numeric or ascii representation */
-static void print_ace(struct cli_state *cli, FILE *f, struct security_ace *ace,
- bool numeric)
-{
- const struct perm_value *v;
- fstring sidstr;
- int do_print = 0;
- uint32 got_mask;
-
- SidToString(cli, sidstr, &ace->trustee, numeric);
-
- fprintf(f, "%s:", sidstr);
-
- if (numeric) {
- fprintf(f, "%d/0x%x/0x%08x",
- ace->type, ace->flags, ace->access_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);
- }
-
- print_ace_flags(f, ace->flags);
-
- /* Standard permissions */
-
- for (v = standard_values; v->perm; v++) {
- if (ace->access_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->access_mask;
-
- again:
- for (v = special_values; v->perm; v++) {
- if ((ace->access_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->access_mask);
- } else {
- do_print = 1;
- goto again;
- }
- }
-}
-
-static bool parse_ace_flags(const char *str, unsigned int *pflags)
-{
- const char *p = str;
- *pflags = 0;
-
- while (*p) {
- if (strnequal(p, "OI", 2)) {
- *pflags |= SEC_ACE_FLAG_OBJECT_INHERIT;
- p += 2;
- } else if (strnequal(p, "CI", 2)) {
- *pflags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
- p += 2;
- } else if (strnequal(p, "NP", 2)) {
- *pflags |= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
- p += 2;
- } else if (strnequal(p, "IO", 2)) {
- *pflags |= SEC_ACE_FLAG_INHERIT_ONLY;
- p += 2;
- } else if (*p == 'I') {
- *pflags |= SEC_ACE_FLAG_INHERITED_ACE;
- p += 1;
- } else if (*p) {
- return false;
- }
-
- switch (*p) {
- case '|':
- p++;
- case '\0':
- continue;
- default:
- return false;
- }
- }
- return true;
-}
-
-/* parse an ACE in the same format as print_ace() */
-static bool parse_ace(struct cli_state *cli, struct security_ace *ace,
- const char *orig_str)
-{
- char *p;
- const char *cp;
- char *tok;
- unsigned int atype = 0;
- unsigned int aflags = 0;
- unsigned int amask = 0;
- struct dom_sid sid;
- uint32_t mask;
- const struct perm_value *v;
- char *str = SMB_STRDUP(orig_str);
- TALLOC_CTX *frame = talloc_stackframe();
-
- if (!str) {
- TALLOC_FREE(frame);
- return False;
- }
-
- ZERO_STRUCTP(ace);
- p = strchr_m(str,':');
- if (!p) {
- printf("ACE '%s': missing ':'.\n", orig_str);
- SAFE_FREE(str);
- TALLOC_FREE(frame);
- return False;
- }
- *p = '\0';
- p++;
- /* Try to parse numeric form */
-
- if (sscanf(p, "%u/%u/%u", &atype, &aflags, &amask) == 3 &&
- StringToSid(cli, &sid, str)) {
- goto done;
- }
-
- /* Try to parse text form */
-
- if (!StringToSid(cli, &sid, str)) {
- printf("ACE '%s': failed to convert '%s' to SID\n",
- orig_str, str);
- SAFE_FREE(str);
- TALLOC_FREE(frame);
- return False;
- }
-
- cp = p;
- if (!next_token_talloc(frame, &cp, &tok, "/")) {
- printf("ACE '%s': failed to find '/' character.\n",
- orig_str);
- SAFE_FREE(str);
- TALLOC_FREE(frame);
- 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);
- TALLOC_FREE(frame);
- return False;
- }
-
- /* Only numeric form accepted for flags at present */
-
- if (!next_token_talloc(frame, &cp, &tok, "/")) {
- printf("ACE '%s': bad flags entry at '%s'\n",
- orig_str, tok);
- SAFE_FREE(str);
- TALLOC_FREE(frame);
- return False;
- }
-
- if (tok[0] < '0' || tok[0] > '9') {
- if (!parse_ace_flags(tok, &aflags)) {
- printf("ACE '%s': bad named flags entry at '%s'\n",
- orig_str, tok);
- SAFE_FREE(str);
- TALLOC_FREE(frame);
- return False;
- }
- } else if (strnequal(tok, "0x", 2)) {
- if (!sscanf(tok, "%x", &aflags)) {
- printf("ACE '%s': bad hex flags entry at '%s'\n",
- orig_str, tok);
- SAFE_FREE(str);
- TALLOC_FREE(frame);
- return False;
- }
- } else {
- if (!sscanf(tok, "%u", &aflags)) {
- printf("ACE '%s': bad integer flags entry at '%s'\n",
- orig_str, tok);
- SAFE_FREE(str);
- TALLOC_FREE(frame);
- return False;
- }
- }
-
- if (!next_token_talloc(frame, &cp, &tok, "/")) {
- printf("ACE '%s': missing / at '%s'\n",
- orig_str, tok);
- SAFE_FREE(str);
- TALLOC_FREE(frame);
- return False;
- }
-
- if (strncmp(tok, "0x", 2) == 0) {
- if (sscanf(tok, "%u", &amask) != 1) {
- printf("ACE '%s': bad hex number at '%s'\n",
- orig_str, tok);
- SAFE_FREE(str);
- TALLOC_FREE(frame);
- 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);
- TALLOC_FREE(frame);
- return False;
- }
- p++;
- }
-
- if (*p) {
- TALLOC_FREE(frame);
- SAFE_FREE(str);
- return False;
- }
-
- done:
- mask = amask;
- init_sec_ace(ace, &sid, atype, mask, aflags);
- TALLOC_FREE(frame);
- SAFE_FREE(str);
- return True;
-}
-
/* add an ACE to a list of ACEs in a struct security_acl */
static bool add_ace(struct security_acl **the_acl, struct security_ace *ace)
{