WHATSNEW: Update changes since 3.3.0pre2.
[Samba.git] / testsuite / printing / psec.c
blob33a45e89d03d097280f04212e77398ce4f2b1118
1 /*
2 Unix SMB/Netbios implementation.
3 Version 2.0
5 Printer security permission manipulation.
7 Copyright (C) Tim Potter 2000
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 /* This program can get or set NT printer security permissions from the
24 command line. Usage: psec getsec|setsec printername. You must have
25 write access to the ntdrivers.tdb file to set permissions and read
26 access to get permissions.
28 For this program to compile using the supplied Makefile.psec, Samba
29 must be configured with the --srcdir option
31 For getsec, output like the following is sent to standard output:
33 S-1-5-21-1067277791-1719175008-3000797951-500
35 1 9 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-501
36 1 2 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-501
37 0 9 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-500
38 0 2 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-500
39 0 9 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-513
40 0 2 0x00020000 S-1-5-21-1067277791-1719175008-3000797951-513
41 0 2 0xe0000000 S-1-1-0
43 The first two lines describe the owner user and owner group of the printer.
44 If either of these lines are blank then the respective owner property is
45 not set. The remaining lines list the printer permissions or ACE entries,
46 one per line. Each column describes a different property of the ACE:
48 Column Description
49 -------------------------------------------------------------------
50 1 ACE type (allow/deny etc) defined in rpc_secdes.h
51 2 ACE flags defined in rpc_secdes.h
52 3 ACE mask - printer ACE masks are defined in rpc_spoolss.h
53 4 SID the ACE applies to
55 The above example describes the following permissions in order:
57 - The guest user has No Access to the printer
58 - The domain administrator has Full Access
59 - Domain Users can Manage Documents
60 - Everyone has Print access
62 The setsec command takes the output format but sets the security descriptor
63 appropriately. */
65 #include "includes.h"
67 TDB_CONTEXT *tdb;
69 /* ACE type conversions */
71 char *ace_type_to_str(uint ace_type)
73 static fstring temp;
75 switch(ace_type) {
76 case SEC_ACE_TYPE_ACCESS_DENIED:
77 return "DENY";
78 case SEC_ACE_TYPE_ACCESS_ALLOWED:
79 return "ALLOW";
82 slprintf(temp, sizeof(temp) - 1, "0x%02x", ace_type);
83 return temp;
86 uint str_to_ace_type(char *ace_type)
88 if (strcmp(ace_type, "ALLOWED") == 0)
89 return SEC_ACE_TYPE_ACCESS_ALLOWED;
91 if (strcmp(ace_type, "DENIED") == 0)
92 return SEC_ACE_TYPE_ACCESS_DENIED;
94 return -1;
97 /* ACE mask (permission) conversions */
99 char *ace_mask_to_str(uint32 ace_mask)
101 static fstring temp;
103 switch (ace_mask) {
104 case PRINTER_ACE_FULL_CONTROL:
105 return "Full Control";
106 case PRINTER_ACE_MANAGE_DOCUMENTS:
107 return "Manage Documents";
108 case PRINTER_ACE_PRINT:
109 return "Print";
112 slprintf(temp, sizeof(temp) - 1, "0x%08x", ace_mask);
113 return temp;
116 uint32 str_to_ace_mask(char *ace_mask)
118 if (strcmp(ace_mask, "Full Control") == 0)
119 return PRINTER_ACE_FULL_CONTROL;
121 if (strcmp(ace_mask, "Manage Documents") == 0)
122 return PRINTER_ACE_MANAGE_DOCUMENTS;
124 if (strcmp(ace_mask, "Print") == 0)
125 return PRINTER_ACE_PRINT;
127 return -1;
130 /* ACE conversions */
132 char *ace_to_str(SEC_ACE *ace)
134 static pstring temp;
135 fstring sidstr;
137 sid_to_string(sidstr, &ace->sid);
139 slprintf(temp, sizeof(temp) - 1, "%s %d %s %s",
140 ace_type_to_str(ace->type), ace->flags,
141 ace_mask_to_str(ace->info.mask), sidstr);
143 return temp;
146 void str_to_ace(SEC_ACE *ace, char *ace_str)
148 SEC_ACCESS sa;
149 DOM_SID sid;
150 uint32 mask;
151 uint8 type, flags;
153 init_sec_access(&sa, mask);
154 init_sec_ace(ace, &sid, type, sa, flags);
157 /* Get a printer security descriptor */
159 int psec_getsec(char *printer)
161 SEC_DESC_BUF *secdesc_ctr = NULL;
162 TALLOC_CTX *mem_ctx = NULL;
163 fstring keystr, sidstr, tdb_path;
164 prs_struct ps;
165 int result = 0, i;
167 ZERO_STRUCT(ps);
169 /* Open tdb for reading */
171 slprintf(tdb_path, sizeof(tdb_path) - 1, "%s/ntdrivers.tdb",
172 lp_lockdir());
174 tdb = tdb_open(tdb_path, 0, 0, O_RDONLY, 0600);
176 if (!tdb) {
177 printf("psec: failed to open nt drivers database: %s\n",
178 sys_errlist[errno]);
179 return 1;
182 /* Get security blob from tdb */
184 slprintf(keystr, sizeof(keystr) - 1, "SECDESC/%s", printer);
186 mem_ctx = talloc_init();
188 if (!mem_ctx) {
189 printf("memory allocation error\n");
190 result = 1;
191 goto done;
194 if (tdb_prs_fetch(tdb, keystr, &ps, mem_ctx) != 0) {
195 printf("error fetching descriptor for printer %s\n",
196 printer);
197 /* cannot do a prs_mem_free() when tdb_prs_fetch fails */
198 /* as the prs structure has not been initialized */
199 tdb_close(tdb);
200 talloc_destroy(mem_ctx);
201 return 1;
204 /* Unpack into security descriptor buffer */
206 if (!sec_io_desc_buf("nt_printing_getsec", &secdesc_ctr, &ps, 1)) {
207 printf("error unpacking sec_desc_buf\n");
208 result = 1;
209 goto done;
212 /* Print owner and group sid */
214 if (secdesc_ctr->sec->owner_sid) {
215 sid_to_string(sidstr, secdesc_ctr->sec->owner_sid);
216 } else {
217 fstrcpy(sidstr, "");
220 printf("%s\n", sidstr);
222 if (secdesc_ctr->sec->grp_sid) {
223 sid_to_string(sidstr, secdesc_ctr->sec->grp_sid);
224 } else {
225 fstrcpy(sidstr, "");
228 printf("%s\n", sidstr);
230 /* Print aces */
232 if (!secdesc_ctr->sec->dacl) {
233 result = 0;
234 goto done;
237 for (i = 0; i < secdesc_ctr->sec->dacl->num_aces; i++) {
238 SEC_ACE *ace = &secdesc_ctr->sec->dacl->ace[i];
240 sid_to_string(sidstr, &ace->sid);
242 printf("%d %d 0x%08x %s\n", ace->type, ace->flags,
243 ace->info.mask, sidstr);
246 done:
247 if (tdb) tdb_close(tdb);
248 if (mem_ctx) talloc_destroy(mem_ctx);
249 if (secdesc_ctr) free_sec_desc_buf(&secdesc_ctr);
250 prs_mem_free(&ps);
252 return result;
255 /* Set a printer security descriptor */
257 int psec_setsec(char *printer)
259 DOM_SID user_sid, group_sid;
260 SEC_ACE *ace_list = NULL;
261 SEC_ACL *dacl = NULL;
262 SEC_DESC *sd;
263 SEC_DESC_BUF *sdb = NULL;
264 int result = 0, num_aces = 0;
265 fstring line, keystr, tdb_path;
266 size_t size;
267 prs_struct ps;
268 TALLOC_CTX *mem_ctx = NULL;
269 BOOL has_user_sid = False, has_group_sid = False;
271 ZERO_STRUCT(ps);
273 /* Open tdb for reading */
275 slprintf(tdb_path, sizeof(tdb_path) - 1, "%s/ntdrivers.tdb",
276 lp_lockdir());
278 tdb = tdb_open(tdb_path, 0, 0, O_RDWR, 0600);
280 if (!tdb) {
281 printf("psec: failed to open nt drivers database: %s\n",
282 sys_errlist[errno]);
283 result = 1;
284 goto done;
287 /* Read owner and group sid */
289 fgets(line, sizeof(fstring), stdin);
290 if (line[0] != '\n') {
291 string_to_sid(&user_sid, line);
292 has_user_sid = True;
295 fgets(line, sizeof(fstring), stdin);
296 if (line[0] != '\n') {
297 string_to_sid(&group_sid, line);
298 has_group_sid = True;
301 /* Read ACEs from standard input for discretionary ACL */
303 while(fgets(line, sizeof(fstring), stdin)) {
304 int ace_type, ace_flags;
305 uint32 ace_mask;
306 fstring sidstr;
307 DOM_SID sid;
308 SEC_ACCESS sa;
310 if (sscanf(line, "%d %d 0x%x %s", &ace_type, &ace_flags,
311 &ace_mask, sidstr) != 4) {
312 continue;
315 string_to_sid(&sid, sidstr);
317 ace_list = Realloc(ace_list, sizeof(SEC_ACE) *
318 (num_aces + 1));
320 init_sec_access(&sa, ace_mask);
321 init_sec_ace(&ace_list[num_aces], &sid, ace_type, sa,
322 ace_flags);
324 num_aces++;
327 dacl = make_sec_acl(ACL_REVISION, num_aces, ace_list);
328 free(ace_list);
330 /* Create security descriptor */
332 sd = make_sec_desc(SEC_DESC_REVISION,
333 has_user_sid ? &user_sid : NULL,
334 has_group_sid ? &group_sid : NULL,
335 NULL, /* System ACL */
336 dacl, /* Discretionary ACL */
337 &size);
339 free_sec_acl(&dacl);
341 sdb = make_sec_desc_buf(size, sd);
343 free_sec_desc(&sd);
345 /* Write security descriptor to tdb */
347 mem_ctx = talloc_init();
349 if (!mem_ctx) {
350 printf("memory allocation error\n");
351 result = 1;
352 goto done;
355 prs_init(&ps, (uint32)sec_desc_size(sdb->sec) +
356 sizeof(SEC_DESC_BUF), 4, mem_ctx, MARSHALL);
358 if (!sec_io_desc_buf("nt_printing_setsec", &sdb, &ps, 1)) {
359 printf("sec_io_desc_buf failed\n");
360 goto done;
363 slprintf(keystr, sizeof(keystr) - 1, "SECDESC/%s", printer);
365 if (!tdb_prs_store(tdb, keystr, &ps)==0) {
366 printf("Failed to store secdesc for %s\n", printer);
367 goto done;
370 done:
371 if (tdb) tdb_close(tdb);
372 if (sdb) free_sec_desc_buf(&sdb);
373 if (mem_ctx) talloc_destroy(mem_ctx);
374 prs_mem_free(&ps);
376 return result;
379 /* Help */
381 void usage(void)
383 printf("Usage: psec getsec|setsec printername\n");
386 /* Main function */
388 int main(int argc, char **argv)
390 pstring servicesf = CONFIGFILE;
392 /* Argument check */
394 if (argc == 1) {
395 usage();
396 return 1;
399 /* Load smb.conf file */
401 charset_initialise();
403 if (!lp_load(servicesf,False,False,True)) {
404 fprintf(stderr, "Couldn't load confiuration file %s\n",
405 servicesf);
406 return 1;
409 /* Do commands */
411 if (strcmp(argv[1], "setsec") == 0) {
413 if (argc != 3) {
414 usage();
415 return 1;
418 return psec_setsec(argv[2]);
421 if (strcmp(argv[1], "getsec") == 0) {
423 if (argc != 3) {
424 usage();
425 return 1;
428 return psec_getsec(argv[2]);
431 /* An unknown command */
433 printf("psec: unknown command %s\n", argv[1]);
434 return 1;