Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Security Descriptor (SD) helper functions
4 :
5 : Copyright (C) Andrew Tridgell 2000
6 : Copyright (C) Tim Potter 2000
7 : Copyright (C) Jeremy Allison 2000
8 : Copyright (C) Jelmer Vernooij 2003
9 :
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.
14 :
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.
19 :
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/>.
22 : */
23 :
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"
31 : #include "lib/util/string_wrappers.h"
32 :
33 : /* These values discovered by inspection */
34 :
35 : struct perm_value {
36 : const char *perm;
37 : uint32_t mask;
38 : };
39 :
40 : static const struct perm_value special_values[] = {
41 : { "R", SEC_RIGHTS_FILE_READ },
42 : { "W", SEC_RIGHTS_FILE_WRITE },
43 : { "X", SEC_RIGHTS_FILE_EXECUTE },
44 : { "D", SEC_STD_DELETE },
45 : { "P", SEC_STD_WRITE_DAC },
46 : { "O", SEC_STD_WRITE_OWNER },
47 : { NULL, 0 },
48 : };
49 :
50 : static const struct perm_value standard_values[] = {
51 : { "READ", SEC_RIGHTS_DIR_READ|SEC_DIR_TRAVERSE },
52 : { "CHANGE", SEC_RIGHTS_DIR_READ|SEC_STD_DELETE|\
53 : SEC_RIGHTS_DIR_WRITE|SEC_DIR_TRAVERSE },
54 : { "FULL", SEC_RIGHTS_DIR_ALL },
55 : { NULL, 0 },
56 : };
57 :
58 : static const struct {
59 : uint16_t mask;
60 : const char *str;
61 : const char *desc;
62 : } sec_desc_ctrl_bits[] = {
63 : {SEC_DESC_OWNER_DEFAULTED, "OD", "Owner Defaulted"},
64 : {SEC_DESC_GROUP_DEFAULTED, "GD", "Group Defaulted"},
65 : {SEC_DESC_DACL_PRESENT, "DP", "DACL Present"},
66 : {SEC_DESC_DACL_DEFAULTED, "DD", "DACL Defaulted"},
67 : {SEC_DESC_SACL_PRESENT, "SP", "SACL Present"},
68 : {SEC_DESC_SACL_DEFAULTED, "SD", "SACL Defaulted"},
69 : {SEC_DESC_DACL_TRUSTED, "DT", "DACL Trusted"},
70 : {SEC_DESC_SERVER_SECURITY, "SS", "Server Security"},
71 : {SEC_DESC_DACL_AUTO_INHERIT_REQ, "DR", "DACL Inheritance Required"},
72 : {SEC_DESC_SACL_AUTO_INHERIT_REQ, "SR", "SACL Inheritance Required"},
73 : {SEC_DESC_DACL_AUTO_INHERITED, "DI", "DACL Auto Inherited"},
74 : {SEC_DESC_SACL_AUTO_INHERITED, "SI", "SACL Auto Inherited"},
75 : {SEC_DESC_DACL_PROTECTED, "PD", "DACL Protected"},
76 : {SEC_DESC_SACL_PROTECTED, "PS", "SACL Protected"},
77 : {SEC_DESC_RM_CONTROL_VALID, "RM", "RM Control Valid"},
78 : {SEC_DESC_SELF_RELATIVE , "SR", "Self Relative"},
79 : };
80 :
81 : /* Open cli connection and policy handle */
82 5714 : static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli,
83 : const struct dom_sid *sid,
84 : TALLOC_CTX *mem_ctx,
85 : enum lsa_SidType *type,
86 : char **domain, char **name)
87 : {
88 5714 : struct smbXcli_tcon *orig_tcon = NULL;
89 5714 : struct rpc_pipe_client *p = NULL;
90 : struct policy_handle handle;
91 : NTSTATUS status;
92 5714 : TALLOC_CTX *frame = talloc_stackframe();
93 : enum lsa_SidType *types;
94 : char **domains;
95 : char **names;
96 :
97 5714 : if (cli_state_has_tcon(cli)) {
98 5714 : orig_tcon = cli_state_save_tcon(cli);
99 5714 : if (orig_tcon == NULL) {
100 0 : status = NT_STATUS_NO_MEMORY;
101 0 : goto tcon_fail;
102 : }
103 : }
104 :
105 5714 : status = cli_tree_connect(cli, "IPC$", "?????", NULL);
106 5714 : if (!NT_STATUS_IS_OK(status)) {
107 0 : goto tcon_fail;
108 : }
109 :
110 5714 : status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
111 : &p);
112 5714 : if (!NT_STATUS_IS_OK(status)) {
113 0 : goto fail;
114 : }
115 :
116 5714 : status = rpccli_lsa_open_policy(p, talloc_tos(), True,
117 : GENERIC_EXECUTE_ACCESS, &handle);
118 5714 : if (!NT_STATUS_IS_OK(status)) {
119 0 : goto fail;
120 : }
121 :
122 5714 : status = rpccli_lsa_lookup_sids(p, talloc_tos(), &handle, 1, sid,
123 : &domains, &names, &types);
124 5714 : if (!NT_STATUS_IS_OK(status)) {
125 0 : goto fail;
126 : }
127 :
128 5714 : *type = types[0];
129 5714 : *domain = talloc_move(mem_ctx, &domains[0]);
130 5714 : *name = talloc_move(mem_ctx, &names[0]);
131 :
132 5714 : status = NT_STATUS_OK;
133 5714 : fail:
134 5714 : TALLOC_FREE(p);
135 5714 : cli_tdis(cli);
136 5714 : tcon_fail:
137 5714 : cli_state_restore_tcon(cli, orig_tcon);
138 5714 : TALLOC_FREE(frame);
139 5714 : return status;
140 : }
141 :
142 : /* convert a SID to a string, either numeric or username/group */
143 5836 : void SidToString(struct cli_state *cli, fstring str, const struct dom_sid *sid,
144 : bool numeric)
145 : {
146 5836 : char *domain = NULL;
147 5836 : char *name = NULL;
148 : enum lsa_SidType type;
149 : NTSTATUS status;
150 :
151 5836 : sid_to_fstring(str, sid);
152 :
153 5836 : if (numeric || cli == NULL) {
154 244 : return;
155 : }
156 :
157 5714 : status = cli_lsa_lookup_sid(cli, sid, talloc_tos(), &type,
158 : &domain, &name);
159 :
160 5714 : if (!NT_STATUS_IS_OK(status)) {
161 0 : return;
162 : }
163 :
164 5714 : if (*domain) {
165 2580 : slprintf(str, sizeof(fstring) - 1, "%s%s%s",
166 : domain, lp_winbind_separator(), name);
167 : } else {
168 3134 : fstrcpy(str, name);
169 : }
170 : }
171 :
172 1304 : static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli,
173 : const char *name,
174 : enum lsa_SidType *type,
175 : struct dom_sid *sid)
176 : {
177 1304 : struct smbXcli_tcon *orig_tcon = NULL;
178 1304 : struct rpc_pipe_client *p = NULL;
179 : struct policy_handle handle;
180 : NTSTATUS status;
181 1304 : TALLOC_CTX *frame = talloc_stackframe();
182 : struct dom_sid *sids;
183 : enum lsa_SidType *types;
184 :
185 1304 : if (cli_state_has_tcon(cli)) {
186 1304 : orig_tcon = cli_state_save_tcon(cli);
187 1304 : if (orig_tcon == NULL) {
188 0 : status = NT_STATUS_NO_MEMORY;
189 0 : goto tcon_fail;
190 : }
191 : }
192 :
193 1304 : status = cli_tree_connect(cli, "IPC$", "?????", NULL);
194 1304 : if (!NT_STATUS_IS_OK(status)) {
195 0 : goto tcon_fail;
196 : }
197 :
198 1304 : status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
199 : &p);
200 1304 : if (!NT_STATUS_IS_OK(status)) {
201 0 : goto fail;
202 : }
203 :
204 1304 : status = rpccli_lsa_open_policy(p, talloc_tos(), True,
205 : GENERIC_EXECUTE_ACCESS, &handle);
206 1304 : if (!NT_STATUS_IS_OK(status)) {
207 0 : goto fail;
208 : }
209 :
210 1304 : status = rpccli_lsa_lookup_names(p, talloc_tos(), &handle, 1, &name,
211 : NULL, 1, &sids, &types);
212 1304 : if (!NT_STATUS_IS_OK(status)) {
213 0 : goto fail;
214 : }
215 :
216 1304 : *type = types[0];
217 1304 : *sid = sids[0];
218 :
219 1304 : status = NT_STATUS_OK;
220 1304 : fail:
221 1304 : TALLOC_FREE(p);
222 1304 : cli_tdis(cli);
223 1304 : tcon_fail:
224 1304 : cli_state_restore_tcon(cli, orig_tcon);
225 1304 : TALLOC_FREE(frame);
226 1304 : return status;
227 : }
228 :
229 : /* convert a string to a SID, either numeric or username/group */
230 1328 : bool StringToSid(struct cli_state *cli, struct dom_sid *sid, const char *str)
231 : {
232 : enum lsa_SidType type;
233 :
234 1328 : if (string_to_sid(sid, str)) {
235 24 : return true;
236 : }
237 :
238 1304 : if (cli == NULL) {
239 0 : return false;
240 : }
241 :
242 1304 : return NT_STATUS_IS_OK(cli_lsa_lookup_name(cli, str, &type, sid));
243 : }
244 :
245 4568 : static void print_ace_flags(FILE *f, uint8_t flags)
246 : {
247 4568 : char *str = talloc_strdup(NULL, "");
248 :
249 4568 : if (!str) {
250 0 : goto out;
251 : }
252 :
253 4568 : if (flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
254 1824 : str = talloc_asprintf(str, "%s%s",
255 : str, "OI|");
256 1824 : if (!str) {
257 0 : goto out;
258 : }
259 : }
260 4568 : if (flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
261 1848 : str = talloc_asprintf(str, "%s%s",
262 : str, "CI|");
263 1848 : if (!str) {
264 0 : goto out;
265 : }
266 : }
267 4568 : if (flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
268 18 : str = talloc_asprintf(str, "%s%s",
269 : str, "NP|");
270 18 : if (!str) {
271 0 : goto out;
272 : }
273 : }
274 4568 : if (flags & SEC_ACE_FLAG_INHERIT_ONLY) {
275 1044 : str = talloc_asprintf(str, "%s%s",
276 : str, "IO|");
277 1044 : if (!str) {
278 0 : goto out;
279 : }
280 : }
281 4568 : if (flags & SEC_ACE_FLAG_INHERITED_ACE) {
282 2562 : str = talloc_asprintf(str, "%s%s",
283 : str, "I|");
284 2562 : if (!str) {
285 0 : goto out;
286 : }
287 : }
288 : /* Ignore define SEC_ACE_FLAG_SUCCESSFUL_ACCESS ( 0x40 )
289 : and SEC_ACE_FLAG_FAILED_ACCESS ( 0x80 ) as they're
290 : audit ace flags. */
291 :
292 4568 : if (str[strlen(str)-1] == '|') {
293 3498 : str[strlen(str)-1] = '\0';
294 3498 : fprintf(f, "/%s/", str);
295 : } else {
296 1070 : fprintf(f, "/0x%x/", flags);
297 : }
298 4568 : TALLOC_FREE(str);
299 4568 : return;
300 :
301 0 : out:
302 0 : fprintf(f, "/0x%x/", flags);
303 : }
304 :
305 : /* print an ACE on a FILE, using either numeric or ascii representation */
306 4568 : void print_ace(struct cli_state *cli, FILE *f, struct security_ace *ace,
307 : bool numeric)
308 : {
309 : const struct perm_value *v;
310 : fstring sidstr;
311 4568 : int do_print = 0;
312 : uint32_t got_mask;
313 :
314 4568 : SidToString(cli, sidstr, &ace->trustee, numeric);
315 :
316 4568 : fprintf(f, "%s:", sidstr);
317 :
318 4568 : if (numeric) {
319 0 : fprintf(f, "%d/0x%x/0x%08x",
320 0 : ace->type, ace->flags, ace->access_mask);
321 0 : return;
322 : }
323 :
324 : /* Ace type */
325 :
326 4568 : if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED) {
327 4536 : fprintf(f, "ALLOWED");
328 32 : } else if (ace->type == SEC_ACE_TYPE_ACCESS_DENIED) {
329 32 : fprintf(f, "DENIED");
330 : } else {
331 0 : fprintf(f, "%d", ace->type);
332 : }
333 :
334 4568 : print_ace_flags(f, ace->flags);
335 :
336 : /* Standard permissions */
337 :
338 7970 : for (v = standard_values; v->perm; v++) {
339 7874 : if (ace->access_mask == v->mask) {
340 4472 : fprintf(f, "%s", v->perm);
341 4472 : return;
342 : }
343 : }
344 :
345 : /* Special permissions. Print out a hex value if we have
346 : leftover bits in the mask. */
347 :
348 96 : got_mask = ace->access_mask;
349 :
350 192 : again:
351 1344 : for (v = special_values; v->perm; v++) {
352 1152 : if ((ace->access_mask & v->mask) == v->mask) {
353 600 : if (do_print) {
354 300 : fprintf(f, "%s", v->perm);
355 : }
356 600 : got_mask &= ~v->mask;
357 : }
358 : }
359 :
360 192 : if (!do_print) {
361 96 : if (got_mask != 0) {
362 0 : fprintf(f, "0x%08x", ace->access_mask);
363 : } else {
364 96 : do_print = 1;
365 96 : goto again;
366 : }
367 : }
368 : }
369 :
370 1110 : static bool parse_ace_flags(const char *str, unsigned int *pflags)
371 : {
372 1110 : const char *p = str;
373 1110 : *pflags = 0;
374 :
375 4332 : while (*p) {
376 2112 : if (strnequal(p, "OI", 2)) {
377 594 : *pflags |= SEC_ACE_FLAG_OBJECT_INHERIT;
378 594 : p += 2;
379 1518 : } else if (strnequal(p, "CI", 2)) {
380 618 : *pflags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
381 618 : p += 2;
382 900 : } else if (strnequal(p, "NP", 2)) {
383 54 : *pflags |= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
384 54 : p += 2;
385 846 : } else if (strnequal(p, "IO", 2)) {
386 12 : *pflags |= SEC_ACE_FLAG_INHERIT_ONLY;
387 12 : p += 2;
388 834 : } else if (*p == 'I') {
389 834 : *pflags |= SEC_ACE_FLAG_INHERITED_ACE;
390 834 : p += 1;
391 0 : } else if (*p) {
392 0 : return false;
393 : }
394 :
395 2112 : switch (*p) {
396 1002 : case '|':
397 1002 : p++;
398 :
399 : FALL_THROUGH;
400 2112 : case '\0':
401 2112 : continue;
402 0 : default:
403 0 : return false;
404 : }
405 : }
406 1110 : return true;
407 : }
408 :
409 : /* parse an ACE in the same format as print_ace() */
410 1266 : bool parse_ace(struct cli_state *cli, struct security_ace *ace,
411 : const char *orig_str)
412 : {
413 : char *p;
414 : const char *cp;
415 : char *tok;
416 1266 : unsigned int atype = 0;
417 1266 : unsigned int aflags = 0;
418 1266 : unsigned int amask = 0;
419 : struct dom_sid sid;
420 : uint32_t mask;
421 : const struct perm_value *v;
422 1266 : char *str = SMB_STRDUP(orig_str);
423 1266 : TALLOC_CTX *frame = talloc_stackframe();
424 :
425 1266 : if (!str) {
426 0 : TALLOC_FREE(frame);
427 0 : return False;
428 : }
429 :
430 1266 : ZERO_STRUCTP(ace);
431 1266 : p = strchr_m(str,':');
432 1266 : if (!p) {
433 0 : printf("ACE '%s': missing ':'.\n", orig_str);
434 0 : SAFE_FREE(str);
435 0 : TALLOC_FREE(frame);
436 0 : return False;
437 : }
438 1266 : *p = '\0';
439 1266 : p++;
440 :
441 1266 : if (!StringToSid(cli, &sid, str)) {
442 0 : printf("ACE '%s': failed to convert '%s' to SID\n",
443 : orig_str, str);
444 0 : SAFE_FREE(str);
445 0 : TALLOC_FREE(frame);
446 0 : return False;
447 : }
448 :
449 1266 : cp = p;
450 1266 : if (!next_token_talloc(frame, &cp, &tok, "/")) {
451 0 : printf("ACE '%s': failed to find '/' character.\n",
452 : orig_str);
453 0 : SAFE_FREE(str);
454 0 : TALLOC_FREE(frame);
455 0 : return False;
456 : }
457 :
458 1266 : if (strncmp(tok, "ALLOWED", strlen("ALLOWED")) == 0) {
459 1252 : atype = SEC_ACE_TYPE_ACCESS_ALLOWED;
460 14 : } else if (strncmp(tok, "DENIED", strlen("DENIED")) == 0) {
461 10 : atype = SEC_ACE_TYPE_ACCESS_DENIED;
462 :
463 4 : } else if (strnequal(tok, "0x", 2)) {
464 : int result;
465 :
466 2 : result = sscanf(tok, "%x", &atype);
467 4 : if (result == 0 ||
468 4 : (atype != SEC_ACE_TYPE_ACCESS_ALLOWED &&
469 2 : atype != SEC_ACE_TYPE_ACCESS_DENIED)) {
470 0 : printf("ACE '%s': bad hex value for type at '%s'\n",
471 : orig_str, tok);
472 0 : SAFE_FREE(str);
473 0 : TALLOC_FREE(frame);
474 0 : return false;
475 : }
476 4 : } else if(tok[0] >= '0' && tok[0] <= '9') {
477 : int result;
478 :
479 2 : result = sscanf(tok, "%u", &atype);
480 4 : if (result == 0 ||
481 4 : (atype != SEC_ACE_TYPE_ACCESS_ALLOWED &&
482 2 : atype != SEC_ACE_TYPE_ACCESS_DENIED)) {
483 0 : printf("ACE '%s': bad integer value for type at '%s'\n",
484 : orig_str, tok);
485 0 : SAFE_FREE(str);
486 0 : TALLOC_FREE(frame);
487 0 : return false;
488 : }
489 : } else {
490 0 : printf("ACE '%s': missing 'ALLOWED' or 'DENIED' entry at '%s'\n",
491 : orig_str, tok);
492 0 : SAFE_FREE(str);
493 0 : TALLOC_FREE(frame);
494 0 : return False;
495 : }
496 :
497 1266 : if (!next_token_talloc(frame, &cp, &tok, "/")) {
498 0 : printf("ACE '%s': bad flags entry at '%s'\n",
499 : orig_str, tok);
500 0 : SAFE_FREE(str);
501 0 : TALLOC_FREE(frame);
502 0 : return False;
503 : }
504 :
505 1266 : if (tok[0] < '0' || tok[0] > '9') {
506 2220 : if (!parse_ace_flags(tok, &aflags)) {
507 0 : printf("ACE '%s': bad named flags entry at '%s'\n",
508 : orig_str, tok);
509 0 : SAFE_FREE(str);
510 0 : TALLOC_FREE(frame);
511 0 : return False;
512 : }
513 156 : } else if (strnequal(tok, "0x", 2)) {
514 154 : if (!sscanf(tok, "%x", &aflags)) {
515 0 : printf("ACE '%s': bad hex flags entry at '%s'\n",
516 : orig_str, tok);
517 0 : SAFE_FREE(str);
518 0 : TALLOC_FREE(frame);
519 0 : return False;
520 : }
521 : } else {
522 2 : if (!sscanf(tok, "%u", &aflags)) {
523 0 : printf("ACE '%s': bad integer flags entry at '%s'\n",
524 : orig_str, tok);
525 0 : SAFE_FREE(str);
526 0 : TALLOC_FREE(frame);
527 0 : return False;
528 : }
529 : }
530 :
531 1266 : if (!next_token_talloc(frame, &cp, &tok, "/")) {
532 0 : printf("ACE '%s': missing / at '%s'\n",
533 : orig_str, tok);
534 0 : SAFE_FREE(str);
535 0 : TALLOC_FREE(frame);
536 0 : return False;
537 : }
538 :
539 1266 : if (strncmp(tok, "0x", 2) == 0) {
540 4 : if (sscanf(tok, "%x", &amask) != 1) {
541 0 : printf("ACE '%s': bad hex number at '%s'\n",
542 : orig_str, tok);
543 0 : SAFE_FREE(str);
544 0 : TALLOC_FREE(frame);
545 0 : return False;
546 : }
547 4 : goto done;
548 : }
549 :
550 3470 : for (v = standard_values; v->perm; v++) {
551 3340 : if (strcmp(tok, v->perm) == 0) {
552 1132 : amask = v->mask;
553 1132 : goto done;
554 : }
555 : }
556 :
557 130 : p = tok;
558 :
559 574 : while(*p) {
560 314 : bool found = False;
561 :
562 2198 : for (v = special_values; v->perm; v++) {
563 1884 : if (v->perm[0] == *p) {
564 314 : amask |= v->mask;
565 314 : found = True;
566 : }
567 : }
568 :
569 314 : if (!found) {
570 0 : printf("ACE '%s': bad permission value at '%s'\n",
571 : orig_str, p);
572 0 : SAFE_FREE(str);
573 0 : TALLOC_FREE(frame);
574 0 : return False;
575 : }
576 314 : p++;
577 : }
578 :
579 130 : if (*p) {
580 0 : TALLOC_FREE(frame);
581 0 : SAFE_FREE(str);
582 0 : return False;
583 : }
584 :
585 130 : done:
586 1266 : mask = amask;
587 1266 : init_sec_ace(ace, &sid, atype, mask, aflags);
588 1266 : TALLOC_FREE(frame);
589 1266 : SAFE_FREE(str);
590 1266 : return True;
591 : }
592 :
593 688 : static void print_acl_ctrl(FILE *file, uint16_t ctrl, bool numeric)
594 : {
595 : int i;
596 688 : const char* separator = "";
597 :
598 688 : fprintf(file, "CONTROL:");
599 688 : if (numeric) {
600 0 : fprintf(file, "0x%x\n", ctrl);
601 0 : return;
602 : }
603 :
604 11696 : for (i = ARRAY_SIZE(sec_desc_ctrl_bits) - 1; i >= 0; i--) {
605 11008 : if (ctrl & sec_desc_ctrl_bits[i].mask) {
606 1382 : fprintf(file, "%s%s",
607 0 : separator, sec_desc_ctrl_bits[i].str);
608 1382 : separator = "|";
609 : }
610 : }
611 688 : fputc('\n', file);
612 : }
613 :
614 : /* print a ascii version of a security descriptor on a FILE handle */
615 688 : void sec_desc_print(struct cli_state *cli, FILE *f,
616 : struct security_descriptor *sd, bool numeric)
617 : {
618 : fstring sidstr;
619 : uint32_t i;
620 :
621 688 : fprintf(f, "REVISION:%d\n", sd->revision);
622 688 : print_acl_ctrl(f, sd->type, numeric);
623 :
624 : /* Print owner and group sid */
625 :
626 688 : if (sd->owner_sid) {
627 634 : SidToString(cli, sidstr, sd->owner_sid, numeric);
628 : } else {
629 54 : fstrcpy(sidstr, "");
630 : }
631 :
632 688 : fprintf(f, "OWNER:%s\n", sidstr);
633 :
634 688 : if (sd->group_sid) {
635 634 : SidToString(cli, sidstr, sd->group_sid, numeric);
636 : } else {
637 54 : fstrcpy(sidstr, "");
638 : }
639 :
640 688 : fprintf(f, "GROUP:%s\n", sidstr);
641 :
642 : /* Print aces */
643 5230 : for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
644 4542 : struct security_ace *ace = &sd->dacl->aces[i];
645 4542 : fprintf(f, "ACL:");
646 4542 : print_ace(cli, f, ace, numeric);
647 4542 : fprintf(f, "\n");
648 : }
649 :
650 688 : }
|