Raft of changes to sync up with most things in appliance head.
[Samba.git] / testsuite / printing / psec.c
blob9b1fc7c46c471ae8e1ba1cf7fa4048fe0d4cde3d
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 2 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, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 /* This program can get or set NT printer security permissions from the
25 command line. Usage: psec getsec|setsec printername. You must have
26 write access to the ntdrivers.tdb file to set permissions and read
27 access to get permissions.
29 For this program to compile using the supplied Makefile.psec, Samba
30 must be configured with the --srcdir option
32 For getsec, output like the following is sent to standard output:
34 S-1-5-21-1067277791-1719175008-3000797951-500
36 1 9 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-501
37 1 2 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-501
38 0 9 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-500
39 0 2 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-500
40 0 9 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-513
41 0 2 0x00020000 S-1-5-21-1067277791-1719175008-3000797951-513
42 0 2 0xe0000000 S-1-1-0
44 The first two lines describe the owner user and owner group of the printer.
45 If either of these lines are blank then the respective owner property is
46 not set. The remaining lines list the printer permissions or ACE entries,
47 one per line. Each column describes a different property of the ACE:
49 Column Description
50 -------------------------------------------------------------------
51 1 ACE type (allow/deny etc) defined in rpc_secdes.h
52 2 ACE flags defined in rpc_secdes.h
53 3 ACE mask - printer ACE masks are defined in rpc_spoolss.h
54 4 SID the ACE applies to
56 The above example describes the following permissions in order:
58 - The guest user has No Access to the printer
59 - The domain administrator has Full Access
60 - Domain Users can Manage Documents
61 - Everyone has Print access
63 The setsec command takes the output format but sets the security descriptor
64 appropriately. */
66 #include "includes.h"
68 TDB_CONTEXT *tdb;
70 /* ACE type conversions */
72 char *ace_type_to_str(uint ace_type)
74 fstring temp;
76 switch(ace_type) {
77 case SEC_ACE_TYPE_ACCESS_DENIED:
78 return "DENY";
79 case SEC_ACE_TYPE_ACCESS_ALLOWED:
80 return "ALLOW";
83 slprintf(temp, sizeof(temp) - 1, "0x%02x", ace_type);
84 return temp;
87 uint str_to_ace_type(char *ace_type)
89 if (strcmp(ace_type, "ALLOWED") == 0)
90 return SEC_ACE_TYPE_ACCESS_ALLOWED;
92 if (strcmp(ace_type, "DENIED") == 0)
93 return SEC_ACE_TYPE_ACCESS_DENIED;
95 return -1;
98 /* ACE mask (permission) conversions */
100 char *ace_mask_to_str(uint32 ace_mask)
102 fstring temp;
104 switch (ace_mask) {
105 case PRINTER_ACE_FULL_CONTROL:
106 return "Full Control";
107 case PRINTER_ACE_MANAGE_DOCUMENTS:
108 return "Manage Documents";
109 case PRINTER_ACE_PRINT:
110 return "Print";
113 slprintf(temp, sizeof(temp) - 1, "0x%08x", ace_mask);
114 return temp;
117 uint32 str_to_ace_mask(char *ace_mask)
119 if (strcmp(ace_mask, "Full Control") == 0)
120 return PRINTER_ACE_FULL_CONTROL;
122 if (strcmp(ace_mask, "Manage Documents") == 0)
123 return PRINTER_ACE_MANAGE_DOCUMENTS;
125 if (strcmp(ace_mask, "Print") == 0)
126 return PRINTER_ACE_PRINT;
128 return -1;
131 /* ACE conversions */
133 char *ace_to_str(SEC_ACE *ace)
135 pstring temp;
136 fstring sidstr;
138 sid_to_string(sidstr, &ace->sid);
140 slprintf(temp, sizeof(temp) - 1, "%s %d %s %s",
141 ace_type_to_str(ace->type), ace->flags,
142 ace_mask_to_str(ace->info.mask), sidstr);
144 return temp;
147 int str_to_ace(SEC_ACE *ace, char *ace_str)
149 SEC_ACCESS sa;
150 DOM_SID sid;
151 uint32 mask;
152 uint8 type, flags;
154 init_sec_access(&sa, mask);
155 init_sec_ace(ace, &sid, type, sa, flags);
158 /* Get a printer security descriptor */
160 int psec_getsec(char *printer)
162 SEC_DESC_BUF *secdesc_ctr = NULL;
163 TALLOC_CTX *mem_ctx = NULL;
164 fstring keystr, sidstr, tdb_path;
165 prs_struct ps;
166 int result = 0, i;
168 ZERO_STRUCT(ps);
170 /* Open tdb for reading */
172 slprintf(tdb_path, sizeof(tdb_path) - 1, "%s/ntdrivers.tdb", LOCKDIR);
173 tdb = tdb_open(tdb_path, 0, 0, O_RDONLY, 0600);
175 if (!tdb) {
176 printf("psec: failed to open nt drivers database: %s\n",
177 sys_errlist[errno]);
178 return 1;
181 /* Get security blob from tdb */
183 slprintf(keystr, sizeof(keystr) - 1, "SECDESC/%s", printer);
185 mem_ctx = talloc_init();
187 if (!mem_ctx) {
188 printf("memory allocation error\n");
189 result = 1;
190 goto done;
193 if (tdb_prs_fetch(tdb, keystr, &ps, mem_ctx) != 0) {
194 printf("error fetching descriptor for printer %s\n",
195 printer);
196 result = 1;
197 goto done;
200 /* Unpack into security descriptor buffer */
202 if (!sec_io_desc_buf("nt_printing_getsec", &secdesc_ctr, &ps, 1)) {
203 printf("error unpacking sec_desc_buf\n");
204 result = 1;
205 goto done;
208 /* Print owner and group sid */
210 if (secdesc_ctr->sec->owner_sid) {
211 sid_to_string(sidstr, secdesc_ctr->sec->owner_sid);
212 } else {
213 fstrcpy(sidstr, "");
216 printf("%s\n", sidstr);
218 if (secdesc_ctr->sec->grp_sid) {
219 sid_to_string(sidstr, secdesc_ctr->sec->grp_sid);
220 } else {
221 fstrcpy(sidstr, "");
224 printf("%s\n", sidstr);
226 /* Print aces */
228 if (!secdesc_ctr->sec->dacl) {
229 result = 0;
230 goto done;
233 for (i = 0; i < secdesc_ctr->sec->dacl->num_aces; i++) {
234 SEC_ACE *ace = &secdesc_ctr->sec->dacl->ace[i];
235 fstring sidstr;
237 sid_to_string(sidstr, &ace->sid);
239 printf("%d %d 0x%08x %s\n", ace->type, ace->flags,
240 ace->info.mask, sidstr);
243 done:
244 if (tdb) tdb_close(tdb);
245 if (mem_ctx) talloc_destroy(mem_ctx);
246 if (secdesc_ctr) free_sec_desc_buf(&secdesc_ctr);
247 prs_mem_free(&ps);
249 return result;
252 /* Set a printer security descriptor */
254 int psec_setsec(char *printer)
256 DOM_SID user_sid, group_sid;
257 SEC_ACE *ace_list = NULL;
258 SEC_ACL *dacl = NULL;
259 SEC_DESC *sd;
260 SEC_DESC_BUF *sdb = NULL;
261 int result = 0, num_aces = 0;
262 fstring line, keystr, tdb_path;
263 size_t size;
264 prs_struct ps;
265 TALLOC_CTX *mem_ctx = NULL;
266 BOOL has_user_sid = False, has_group_sid = False;
268 ZERO_STRUCT(ps);
270 /* Open tdb for reading */
272 slprintf(tdb_path, sizeof(tdb_path) - 1, "%s/ntdrivers.tdb", LOCKDIR);
273 tdb = tdb_open(tdb_path, 0, 0, O_RDWR, 0600);
275 if (!tdb) {
276 printf("psec: failed to open nt drivers database: %s\n",
277 sys_errlist[errno]);
278 result = 1;
279 goto done;
282 /* Read owner and group sid */
284 fgets(line, sizeof(fstring), stdin);
285 if (line[0] != '\n') {
286 string_to_sid(&user_sid, line);
287 has_user_sid = True;
290 fgets(line, sizeof(fstring), stdin);
291 if (line[0] != '\n') {
292 string_to_sid(&group_sid, line);
293 has_group_sid = True;
296 /* Read ACEs from standard input for discretionary ACL */
298 while(fgets(line, sizeof(fstring), stdin)) {
299 int ace_type, ace_flags;
300 uint32 ace_mask;
301 fstring sidstr;
302 DOM_SID sid;
303 SEC_ACCESS sa;
305 if (sscanf(line, "%d %d 0x%x %s", &ace_type, &ace_flags,
306 &ace_mask, sidstr) != 4) {
307 continue;
310 string_to_sid(&sid, sidstr);
312 ace_list = Realloc(ace_list, sizeof(SEC_ACE) *
313 (num_aces + 1));
315 init_sec_access(&sa, ace_mask);
316 init_sec_ace(&ace_list[num_aces], &sid, ace_type, sa,
317 ace_flags);
319 num_aces++;
322 dacl = make_sec_acl(ACL_REVISION, num_aces, ace_list);
323 free(ace_list);
325 /* Create security descriptor */
327 sd = make_sec_desc(SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE |
328 SEC_DESC_DACL_PRESENT,
329 has_user_sid ? &user_sid : NULL,
330 has_group_sid ? &group_sid : NULL,
331 NULL, /* System ACL */
332 dacl, /* Discretionary ACL */
333 &size);
335 free_sec_acl(&dacl);
337 sdb = make_sec_desc_buf(size, sd);
339 free_sec_desc(&sd);
341 /* Write security descriptor to tdb */
343 mem_ctx = talloc_init();
345 if (!mem_ctx) {
346 printf("memory allocation error\n");
347 result = 1;
348 goto done;
351 prs_init(&ps, (uint32)sec_desc_size(sdb->sec) +
352 sizeof(SEC_DESC_BUF), 4, mem_ctx, MARSHALL);
354 if (!sec_io_desc_buf("nt_printing_setsec", &sdb, &ps, 1)) {
355 printf("sec_io_desc_buf failed\n");
356 goto done;
359 slprintf(keystr, sizeof(keystr) - 1, "SECDESC/%s", printer);
361 if (!tdb_prs_store(tdb, keystr, &ps)==0) {
362 printf("Failed to store secdesc for %s\n", printer);
363 goto done;
366 done:
367 if (tdb) tdb_close(tdb);
368 if (sdb) free_sec_desc_buf(&sdb);
369 if (mem_ctx) talloc_destroy(mem_ctx);
370 prs_mem_free(&ps);
372 return result;
375 /* Help */
377 void usage(void)
379 printf("Usage: psec getsec|setsec printername\n");
382 /* Main function */
384 int main(int argc, char **argv)
386 /* Argument check */
388 if (argc == 1) {
389 usage();
390 return 1;
393 /* Do commands */
395 if (strcmp(argv[1], "setsec") == 0) {
397 if (argc != 3) {
398 usage();
399 return 1;
402 return psec_setsec(argv[2]);
405 if (strcmp(argv[1], "getsec") == 0) {
407 if (argc != 3) {
408 usage();
409 return 1;
412 return psec_getsec(argv[2]);
415 /* An unknown command */
417 printf("psec: unknown command %s\n", argv[1]);
418 return 1;