source: branches/samba-3.0/source/utils/sharesec.c@ 372

Last change on this file since 372 was 1, checked in by Paul Smedley, 19 years ago

Initial code import

File size: 14.1 KB
Line 
1/*
2 * Unix SMB/Netbios implementation.
3 * Utility for managing share permissions
4 *
5 * Copyright (C) Tim Potter 2000
6 * Copyright (C) Jeremy Allison 2000
7 * Copyright (C) Jelmer Vernooij 2003
8 * Copyright (C) Gerald (Jerry) Carter 2005.
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 2 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, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25
26#include "includes.h"
27
28static TALLOC_CTX *ctx;
29
30enum acl_mode {SMB_ACL_DELETE, SMB_ACL_MODIFY, SMB_ACL_ADD, SMB_ACL_SET, SMB_ACL_VIEW };
31
32struct perm_value {
33 const char *perm;
34 uint32 mask;
35};
36
37/* These values discovered by inspection */
38
39static 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 },
47};
48
49#define SEC_RIGHTS_DIR_CHANGE ( SEC_RIGHTS_DIR_READ|SEC_STD_DELETE|SEC_RIGHTS_DIR_WRITE|SEC_DIR_TRAVERSE )
50
51static const struct perm_value standard_values[] = {
52 { "READ", SEC_RIGHTS_DIR_READ|SEC_DIR_TRAVERSE },
53 { "CHANGE", SEC_RIGHTS_DIR_CHANGE },
54 { "FULL", SEC_RIGHTS_DIR_ALL },
55 { NULL, 0 },
56};
57
58/********************************************************************
59 print an ACE on a FILE
60********************************************************************/
61
62static void print_ace(FILE *f, SEC_ACE *ace)
63{
64 const struct perm_value *v;
65 int do_print = 0;
66 uint32 got_mask;
67
68 fprintf(f, "%s:", sid_string_static(&ace->trustee));
69
70 /* Ace type */
71
72 if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED) {
73 fprintf(f, "ALLOWED");
74 } else if (ace->type == SEC_ACE_TYPE_ACCESS_DENIED) {
75 fprintf(f, "DENIED");
76 } else {
77 fprintf(f, "%d", ace->type);
78 }
79
80 /* Not sure what flags can be set in a file ACL */
81
82 fprintf(f, "/%d/", ace->flags);
83
84 /* Standard permissions */
85
86 for (v = standard_values; v->perm; v++) {
87 if (ace->access_mask == v->mask) {
88 fprintf(f, "%s", v->perm);
89 return;
90 }
91 }
92
93 /* Special permissions. Print out a hex value if we have
94 leftover bits in the mask. */
95
96 got_mask = ace->access_mask;
97
98 again:
99 for (v = special_values; v->perm; v++) {
100 if ((ace->access_mask & v->mask) == v->mask) {
101 if (do_print) {
102 fprintf(f, "%s", v->perm);
103 }
104 got_mask &= ~v->mask;
105 }
106 }
107
108 if (!do_print) {
109 if (got_mask != 0) {
110 fprintf(f, "0x%08x", ace->access_mask);
111 } else {
112 do_print = 1;
113 goto again;
114 }
115 }
116}
117
118/********************************************************************
119 print a ascii version of a security descriptor on a FILE handle
120********************************************************************/
121
122static void sec_desc_print(FILE *f, SEC_DESC *sd)
123{
124 uint32 i;
125
126 fprintf(f, "REVISION:%d\n", sd->revision);
127
128 /* Print owner and group sid */
129
130 fprintf(f, "OWNER:%s\n", sid_string_static(sd->owner_sid));
131
132 fprintf(f, "GROUP:%s\n", sid_string_static(sd->group_sid));
133
134 /* Print aces */
135 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
136 SEC_ACE *ace = &sd->dacl->aces[i];
137 fprintf(f, "ACL:");
138 print_ace(f, ace);
139 fprintf(f, "\n");
140 }
141
142}
143
144/********************************************************************
145 parse an ACE in the same format as print_ace()
146********************************************************************/
147
148static BOOL parse_ace(SEC_ACE *ace, const char *orig_str)
149{
150 char *p;
151 const char *cp;
152 fstring tok;
153 unsigned int atype = 0;
154 unsigned int aflags = 0;
155 unsigned int amask = 0;
156 DOM_SID sid;
157 SEC_ACCESS mask;
158 const struct perm_value *v;
159 char *str = SMB_STRDUP(orig_str);
160
161 if (!str) {
162 return False;
163 }
164
165 ZERO_STRUCTP(ace);
166 p = strchr_m(str,':');
167 if (!p) {
168 printf("ACE '%s': missing ':'.\n", orig_str);
169 SAFE_FREE(str);
170 return False;
171 }
172 *p = '\0';
173 p++;
174 /* Try to parse numeric form */
175
176 if (sscanf(p, "%i/%i/%i", &atype, &aflags, &amask) == 3 &&
177 string_to_sid(&sid, str)) {
178 goto done;
179 }
180
181 /* Try to parse text form */
182
183 if (!string_to_sid(&sid, str)) {
184 printf("ACE '%s': failed to convert '%s' to SID\n",
185 orig_str, str);
186 SAFE_FREE(str);
187 return False;
188 }
189
190 cp = p;
191 if (!next_token(&cp, tok, "/", sizeof(fstring))) {
192 printf("ACE '%s': failed to find '/' character.\n",
193 orig_str);
194 SAFE_FREE(str);
195 return False;
196 }
197
198 if (strncmp(tok, "ALLOWED", strlen("ALLOWED")) == 0) {
199 atype = SEC_ACE_TYPE_ACCESS_ALLOWED;
200 } else if (strncmp(tok, "DENIED", strlen("DENIED")) == 0) {
201 atype = SEC_ACE_TYPE_ACCESS_DENIED;
202 } else {
203 printf("ACE '%s': missing 'ALLOWED' or 'DENIED' entry at '%s'\n",
204 orig_str, tok);
205 SAFE_FREE(str);
206 return False;
207 }
208
209 /* Only numeric form accepted for flags at present */
210 /* no flags on share permissions */
211
212 if (!(next_token(&cp, tok, "/", sizeof(fstring)) &&
213 sscanf(tok, "%i", &aflags) && aflags == 0)) {
214 printf("ACE '%s': bad integer flags entry at '%s'\n",
215 orig_str, tok);
216 SAFE_FREE(str);
217 return False;
218 }
219
220 if (!next_token(&cp, tok, "/", sizeof(fstring))) {
221 printf("ACE '%s': missing / at '%s'\n",
222 orig_str, tok);
223 SAFE_FREE(str);
224 return False;
225 }
226
227 if (strncmp(tok, "0x", 2) == 0) {
228 if (sscanf(tok, "%i", &amask) != 1) {
229 printf("ACE '%s': bad hex number at '%s'\n",
230 orig_str, tok);
231 SAFE_FREE(str);
232 return False;
233 }
234 goto done;
235 }
236
237 for (v = standard_values; v->perm; v++) {
238 if (strcmp(tok, v->perm) == 0) {
239 amask = v->mask;
240 goto done;
241 }
242 }
243
244 p = tok;
245
246 while(*p) {
247 BOOL found = False;
248
249 for (v = special_values; v->perm; v++) {
250 if (v->perm[0] == *p) {
251 amask |= v->mask;
252 found = True;
253 }