s3:trusts_util: pass dcname to trust_pw_change()
[Samba.git] / source3 / lib / util_sd.c
blobaa6d4809fc8b7ed5ee98a439e39f2236cc13e7d2
1 /*
2 Unix SMB/CIFS implementation.
3 Security Descriptor (SD) helper functions
5 Copyright (C) Andrew Tridgell 2000
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Jeremy Allison 2000
8 Copyright (C) Jelmer Vernooij 2003
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "libsmb/libsmb.h"
26 #include "util_sd.h"
27 #include "librpc/gen_ndr/ndr_lsa.h"
28 #include "../libcli/security/security.h"
29 #include "rpc_client/cli_pipe.h"
30 #include "rpc_client/cli_lsarpc.h"
32 /* These values discovered by inspection */
34 struct perm_value {
35 const char *perm;
36 uint32_t mask;
39 static const struct perm_value special_values[] = {
40 { "R", SEC_RIGHTS_FILE_READ },
41 { "W", SEC_RIGHTS_FILE_WRITE },
42 { "X", SEC_RIGHTS_FILE_EXECUTE },
43 { "D", SEC_STD_DELETE },
44 { "P", SEC_STD_WRITE_DAC },
45 { "O", SEC_STD_WRITE_OWNER },
46 { NULL, 0 },
49 static const struct perm_value standard_values[] = {
50 { "READ", SEC_RIGHTS_DIR_READ|SEC_DIR_TRAVERSE },
51 { "CHANGE", SEC_RIGHTS_DIR_READ|SEC_STD_DELETE|\
52 SEC_RIGHTS_DIR_WRITE|SEC_DIR_TRAVERSE },
53 { "FULL", SEC_RIGHTS_DIR_ALL },
54 { NULL, 0 },
57 static const struct {
58 uint16_t mask;
59 const char *str;
60 const char *desc;
61 } sec_desc_ctrl_bits[] = {
62 {SEC_DESC_OWNER_DEFAULTED, "OD", "Owner Defaulted"},
63 {SEC_DESC_GROUP_DEFAULTED, "GD", "Group Defaulted"},
64 {SEC_DESC_DACL_PRESENT, "DP", "DACL Present"},
65 {SEC_DESC_DACL_DEFAULTED, "DD", "DACL Defaulted"},
66 {SEC_DESC_SACL_PRESENT, "SP", "SACL Present"},
67 {SEC_DESC_SACL_DEFAULTED, "SD", "SACL Defaulted"},
68 {SEC_DESC_DACL_TRUSTED, "DT", "DACL Trusted"},
69 {SEC_DESC_SERVER_SECURITY, "SS", "Server Security"},
70 {SEC_DESC_DACL_AUTO_INHERIT_REQ, "DR", "DACL Inheritance Required"},
71 {SEC_DESC_SACL_AUTO_INHERIT_REQ, "SR", "SACL Inheritance Required"},
72 {SEC_DESC_DACL_AUTO_INHERITED, "DI", "DACL Auto Inherited"},
73 {SEC_DESC_SACL_AUTO_INHERITED, "SI", "SACL Auto Inherited"},
74 {SEC_DESC_DACL_PROTECTED, "PD", "DACL Protected"},
75 {SEC_DESC_SACL_PROTECTED, "PS", "SACL Protected"},
76 {SEC_DESC_RM_CONTROL_VALID, "RM", "RM Control Valid"},
77 {SEC_DESC_SELF_RELATIVE , "SR", "Self Relative"},
80 /* Open cli connection and policy handle */
81 static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli,
82 const struct dom_sid *sid,
83 TALLOC_CTX *mem_ctx,
84 enum lsa_SidType *type,
85 char **domain, char **name)
87 struct smbXcli_tcon *orig_tcon = NULL;
88 struct rpc_pipe_client *p = NULL;
89 struct policy_handle handle;
90 NTSTATUS status;
91 TALLOC_CTX *frame = talloc_stackframe();
92 enum lsa_SidType *types;
93 char **domains;
94 char **names;
96 if (cli_state_has_tcon(cli)) {
97 orig_tcon = cli_state_save_tcon(cli);
98 if (orig_tcon == NULL) {
99 status = NT_STATUS_NO_MEMORY;
100 goto tcon_fail;
104 status = cli_tree_connect(cli, "IPC$", "?????", NULL);
105 if (!NT_STATUS_IS_OK(status)) {
106 goto tcon_fail;
109 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
110 &p);
111 if (!NT_STATUS_IS_OK(status)) {
112 goto fail;
115 status = rpccli_lsa_open_policy(p, talloc_tos(), True,
116 GENERIC_EXECUTE_ACCESS, &handle);
117 if (!NT_STATUS_IS_OK(status)) {
118 goto fail;
121 status = rpccli_lsa_lookup_sids(p, talloc_tos(), &handle, 1, sid,
122 &domains, &names, &types);
123 if (!NT_STATUS_IS_OK(status)) {
124 goto fail;
127 *type = types[0];
128 *domain = talloc_move(mem_ctx, &domains[0]);
129 *name = talloc_move(mem_ctx, &names[0]);
131 status = NT_STATUS_OK;
132 fail:
133 TALLOC_FREE(p);
134 cli_tdis(cli);
135 tcon_fail:
136 cli_state_restore_tcon(cli, orig_tcon);
137 TALLOC_FREE(frame);
138 return status;
141 /* convert a SID to a string, either numeric or username/group */
142 void SidToString(struct cli_state *cli, fstring str, const struct dom_sid *sid,
143 bool numeric)
145 char *domain = NULL;
146 char *name = NULL;
147 enum lsa_SidType type;
148 NTSTATUS status;
150 sid_to_fstring(str, sid);
152 if (numeric || cli == NULL) {
153 return;
156 status = cli_lsa_lookup_sid(cli, sid, talloc_tos(), &type,
157 &domain, &name);
159 if (!NT_STATUS_IS_OK(status)) {
160 return;
163 if (*domain) {
164 slprintf(str, sizeof(fstring) - 1, "%s%s%s",
165 domain, lp_winbind_separator(), name);
166 } else {
167 fstrcpy(str, name);
171 static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli,
172 const char *name,
173 enum lsa_SidType *type,
174 struct dom_sid *sid)
176 struct smbXcli_tcon *orig_tcon = NULL;
177 struct rpc_pipe_client *p;
178 struct policy_handle handle;
179 NTSTATUS status;
180 TALLOC_CTX *frame = talloc_stackframe();
181 struct dom_sid *sids;
182 enum lsa_SidType *types;
184 if (cli_state_has_tcon(cli)) {
185 orig_tcon = cli_state_save_tcon(cli);
186 if (orig_tcon == NULL) {
187 status = NT_STATUS_NO_MEMORY;
188 goto tcon_fail;
192 status = cli_tree_connect(cli, "IPC$", "?????", NULL);
193 if (!NT_STATUS_IS_OK(status)) {
194 goto tcon_fail;
197 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
198 &p);
199 if (!NT_STATUS_IS_OK(status)) {
200 goto fail;
203 status = rpccli_lsa_open_policy(p, talloc_tos(), True,
204 GENERIC_EXECUTE_ACCESS, &handle);
205 if (!NT_STATUS_IS_OK(status)) {
206 goto fail;
209 status = rpccli_lsa_lookup_names(p, talloc_tos(), &handle, 1, &name,
210 NULL, 1, &sids, &types);
211 if (!NT_STATUS_IS_OK(status)) {
212 goto fail;
215 *type = types[0];
216 *sid = sids[0];
218 status = NT_STATUS_OK;
219 fail:
220 TALLOC_FREE(p);
221 cli_tdis(cli);
222 tcon_fail:
223 cli_state_restore_tcon(cli, orig_tcon);
224 TALLOC_FREE(frame);
225 return status;
228 /* convert a string to a SID, either numeric or username/group */
229 bool StringToSid(struct cli_state *cli, struct dom_sid *sid, const char *str)
231 enum lsa_SidType type;
233 if (string_to_sid(sid, str)) {
234 return true;
237 if (cli == NULL) {
238 return false;
241 return NT_STATUS_IS_OK(cli_lsa_lookup_name(cli, str, &type, sid));
244 static void print_ace_flags(FILE *f, uint8_t flags)
246 char *str = talloc_strdup(NULL, "");
248 if (!str) {
249 goto out;
252 if (flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
253 str = talloc_asprintf(str, "%s%s",
254 str, "OI|");
255 if (!str) {
256 goto out;
259 if (flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
260 str = talloc_asprintf(str, "%s%s",
261 str, "CI|");
262 if (!str) {
263 goto out;
266 if (flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
267 str = talloc_asprintf(str, "%s%s",
268 str, "NP|");
269 if (!str) {
270 goto out;
273 if (flags & SEC_ACE_FLAG_INHERIT_ONLY) {
274 str = talloc_asprintf(str, "%s%s",
275 str, "IO|");
276 if (!str) {
277 goto out;
280 if (flags & SEC_ACE_FLAG_INHERITED_ACE) {
281 str = talloc_asprintf(str, "%s%s",
282 str, "I|");
283 if (!str) {
284 goto out;
287 /* Ignore define SEC_ACE_FLAG_SUCCESSFUL_ACCESS ( 0x40 )
288 and SEC_ACE_FLAG_FAILED_ACCESS ( 0x80 ) as they're
289 audit ace flags. */
291 if (str[strlen(str)-1] == '|') {
292 str[strlen(str)-1] = '\0';
293 fprintf(f, "/%s/", str);
294 } else {
295 fprintf(f, "/0x%x/", flags);
297 TALLOC_FREE(str);
298 return;
300 out:
301 fprintf(f, "/0x%x/", flags);
304 /* print an ACE on a FILE, using either numeric or ascii representation */
305 void print_ace(struct cli_state *cli, FILE *f, struct security_ace *ace,
306 bool numeric)
308 const struct perm_value *v;
309 fstring sidstr;
310 int do_print = 0;
311 uint32_t got_mask;
313 SidToString(cli, sidstr, &ace->trustee, numeric);
315 fprintf(f, "%s:", sidstr);
317 if (numeric) {
318 fprintf(f, "%d/0x%x/0x%08x",
319 ace->type, ace->flags, ace->access_mask);
320 return;
323 /* Ace type */
325 if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED) {
326 fprintf(f, "ALLOWED");
327 } else if (ace->type == SEC_ACE_TYPE_ACCESS_DENIED) {
328 fprintf(f, "DENIED");
329 } else {
330 fprintf(f, "%d", ace->type);
333 print_ace_flags(f, ace->flags);
335 /* Standard permissions */
337 for (v = standard_values; v->perm; v++) {
338 if (ace->access_mask == v->mask) {
339 fprintf(f, "%s", v->perm);
340 return;
344 /* Special permissions. Print out a hex value if we have
345 leftover bits in the mask. */
347 got_mask = ace->access_mask;
349 again:
350 for (v = special_values; v->perm; v++) {
351 if ((ace->access_mask & v->mask) == v->mask) {
352 if (do_print) {
353 fprintf(f, "%s", v->perm);
355 got_mask &= ~v->mask;
359 if (!do_print) {
360 if (got_mask != 0) {
361 fprintf(f, "0x%08x", ace->access_mask);
362 } else {
363 do_print = 1;
364 goto again;
369 static bool parse_ace_flags(const char *str, unsigned int *pflags)
371 const char *p = str;
372 *pflags = 0;
374 while (*p) {
375 if (strnequal(p, "OI", 2)) {
376 *pflags |= SEC_ACE_FLAG_OBJECT_INHERIT;
377 p += 2;
378 } else if (strnequal(p, "CI", 2)) {
379 *pflags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
380 p += 2;
381 } else if (strnequal(p, "NP", 2)) {
382 *pflags |= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
383 p += 2;
384 } else if (strnequal(p, "IO", 2)) {
385 *pflags |= SEC_ACE_FLAG_INHERIT_ONLY;
386 p += 2;
387 } else if (*p == 'I') {
388 *pflags |= SEC_ACE_FLAG_INHERITED_ACE;
389 p += 1;
390 } else if (*p) {
391 return false;
394 switch (*p) {
395 case '|':
396 p++;
397 case '\0':
398 continue;
399 default:
400 return false;
403 return true;
406 /* parse an ACE in the same format as print_ace() */
407 bool parse_ace(struct cli_state *cli, struct security_ace *ace,
408 const char *orig_str)
410 char *p;
411 const char *cp;
412 char *tok;
413 unsigned int atype = 0;
414 unsigned int aflags = 0;
415 unsigned int amask = 0;
416 struct dom_sid sid;
417 uint32_t mask;
418 const struct perm_value *v;
419 char *str = SMB_STRDUP(orig_str);
420 TALLOC_CTX *frame = talloc_stackframe();
422 if (!str) {
423 TALLOC_FREE(frame);
424 return False;
427 ZERO_STRUCTP(ace);
428 p = strchr_m(str,':');
429 if (!p) {
430 printf("ACE '%s': missing ':'.\n", orig_str);
431 SAFE_FREE(str);
432 TALLOC_FREE(frame);
433 return False;
435 *p = '\0';
436 p++;
438 if (!StringToSid(cli, &sid, str)) {
439 printf("ACE '%s': failed to convert '%s' to SID\n",
440 orig_str, str);
441 SAFE_FREE(str);
442 TALLOC_FREE(frame);
443 return False;
446 cp = p;
447 if (!next_token_talloc(frame, &cp, &tok, "/")) {
448 printf("ACE '%s': failed to find '/' character.\n",
449 orig_str);
450 SAFE_FREE(str);
451 TALLOC_FREE(frame);
452 return False;
455 if (strncmp(tok, "ALLOWED", strlen("ALLOWED")) == 0) {
456 atype = SEC_ACE_TYPE_ACCESS_ALLOWED;
457 } else if (strncmp(tok, "DENIED", strlen("DENIED")) == 0) {
458 atype = SEC_ACE_TYPE_ACCESS_DENIED;
460 } else if (strnequal(tok, "0x", 2)) {
461 int result;
463 result = sscanf(tok, "%x", &atype);
464 if (result == 0 ||
465 (atype != SEC_ACE_TYPE_ACCESS_ALLOWED &&
466 atype != SEC_ACE_TYPE_ACCESS_DENIED)) {
467 printf("ACE '%s': bad hex value for type at '%s'\n",
468 orig_str, tok);
469 SAFE_FREE(str);
470 TALLOC_FREE(frame);
471 return false;
473 } else if(tok[0] >= '0' && tok[0] <= '9') {
474 int result;
476 result = sscanf(tok, "%u", &atype);
477 if (result == 0 ||
478 (atype != SEC_ACE_TYPE_ACCESS_ALLOWED &&
479 atype != SEC_ACE_TYPE_ACCESS_DENIED)) {
480 printf("ACE '%s': bad integer value for type at '%s'\n",
481 orig_str, tok);
482 SAFE_FREE(str);
483 TALLOC_FREE(frame);
484 return false;
486 } else {
487 printf("ACE '%s': missing 'ALLOWED' or 'DENIED' entry at '%s'\n",
488 orig_str, tok);
489 SAFE_FREE(str);
490 TALLOC_FREE(frame);
491 return False;
494 if (!next_token_talloc(frame, &cp, &tok, "/")) {
495 printf("ACE '%s': bad flags entry at '%s'\n",
496 orig_str, tok);
497 SAFE_FREE(str);
498 TALLOC_FREE(frame);
499 return False;
502 if (tok[0] < '0' || tok[0] > '9') {
503 if (!parse_ace_flags(tok, &aflags)) {
504 printf("ACE '%s': bad named flags entry at '%s'\n",
505 orig_str, tok);
506 SAFE_FREE(str);
507 TALLOC_FREE(frame);
508 return False;
510 } else if (strnequal(tok, "0x", 2)) {
511 if (!sscanf(tok, "%x", &aflags)) {
512 printf("ACE '%s': bad hex flags entry at '%s'\n",
513 orig_str, tok);
514 SAFE_FREE(str);
515 TALLOC_FREE(frame);
516 return False;
518 } else {
519 if (!sscanf(tok, "%u", &aflags)) {
520 printf("ACE '%s': bad integer flags entry at '%s'\n",
521 orig_str, tok);
522 SAFE_FREE(str);
523 TALLOC_FREE(frame);
524 return False;
528 if (!next_token_talloc(frame, &cp, &tok, "/")) {
529 printf("ACE '%s': missing / at '%s'\n",
530 orig_str, tok);
531 SAFE_FREE(str);
532 TALLOC_FREE(frame);
533 return False;
536 if (strncmp(tok, "0x", 2) == 0) {
537 if (sscanf(tok, "%x", &amask) != 1) {
538 printf("ACE '%s': bad hex number at '%s'\n",
539 orig_str, tok);
540 SAFE_FREE(str);
541 TALLOC_FREE(frame);
542 return False;
544 goto done;
547 for (v = standard_values; v->perm; v++) {
548 if (strcmp(tok, v->perm) == 0) {
549 amask = v->mask;
550 goto done;
554 p = tok;
556 while(*p) {
557 bool found = False;
559 for (v = special_values; v->perm; v++) {
560 if (v->perm[0] == *p) {
561 amask |= v->mask;
562 found = True;
566 if (!found) {
567 printf("ACE '%s': bad permission value at '%s'\n",
568 orig_str, p);
569 SAFE_FREE(str);
570 TALLOC_FREE(frame);
571 return False;
573 p++;
576 if (*p) {
577 TALLOC_FREE(frame);
578 SAFE_FREE(str);
579 return False;
582 done:
583 mask = amask;
584 init_sec_ace(ace, &sid, atype, mask, aflags);
585 TALLOC_FREE(frame);
586 SAFE_FREE(str);
587 return True;
590 static void print_acl_ctrl(FILE *file, uint16_t ctrl, bool numeric)
592 int i;
593 const char* separator = "";
595 fprintf(file, "CONTROL:");
596 if (numeric) {
597 fprintf(file, "0x%x\n", ctrl);
598 return;
601 for (i = ARRAY_SIZE(sec_desc_ctrl_bits) - 1; i >= 0; i--) {
602 if (ctrl & sec_desc_ctrl_bits[i].mask) {
603 fprintf(file, "%s%s",
604 separator, sec_desc_ctrl_bits[i].str);
605 separator = "|";
608 fputc('\n', file);
611 /* print a ascii version of a security descriptor on a FILE handle */
612 void sec_desc_print(struct cli_state *cli, FILE *f,
613 struct security_descriptor *sd, bool numeric)
615 fstring sidstr;
616 uint32_t i;
618 fprintf(f, "REVISION:%d\n", sd->revision);
619 print_acl_ctrl(f, sd->type, numeric);
621 /* Print owner and group sid */
623 if (sd->owner_sid) {
624 SidToString(cli, sidstr, sd->owner_sid, numeric);
625 } else {
626 fstrcpy(sidstr, "");
629 fprintf(f, "OWNER:%s\n", sidstr);
631 if (sd->group_sid) {
632 SidToString(cli, sidstr, sd->group_sid, numeric);
633 } else {
634 fstrcpy(sidstr, "");
637 fprintf(f, "GROUP:%s\n", sidstr);
639 /* Print aces */
640 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
641 struct security_ace *ace = &sd->dacl->aces[i];
642 fprintf(f, "ACL:");
643 print_ace(cli, f, ace, numeric);
644 fprintf(f, "\n");