2 Unix SMB/Netbios implementation.
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:
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
70 /* ACE type conversions */
72 char *ace_type_to_str(uint ace_type)
77 case SEC_ACE_TYPE_ACCESS_DENIED:
79 case SEC_ACE_TYPE_ACCESS_ALLOWED:
83 slprintf(temp, sizeof(temp) - 1, "0x%02x", ace_type);
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;
98 /* ACE mask (permission) conversions */
100 char *ace_mask_to_str(uint32 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:
113 slprintf(temp, sizeof(temp) - 1, "0x%08x", ace_mask);
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;
131 /* ACE conversions */
133 char *ace_to_str(SEC_ACE *ace)
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);
147 void str_to_ace(SEC_ACE *ace, char *ace_str)
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;
170 /* Open tdb for reading */
172 slprintf(tdb_path, sizeof(tdb_path) - 1, "%s/ntdrivers.tdb",
175 tdb = tdb_open(tdb_path, 0, 0, O_RDONLY, 0600);
178 printf("psec: failed to open nt drivers database: %s\n",
183 /* Get security blob from tdb */
185 slprintf(keystr, sizeof(keystr) - 1, "SECDESC/%s", printer);
187 mem_ctx = talloc_init();
190 printf("memory allocation error\n");
195 if (tdb_prs_fetch(tdb, keystr, &ps, mem_ctx) != 0) {
196 printf("error fetching descriptor for printer %s\n",
202 /* Unpack into security descriptor buffer */
204 if (!sec_io_desc_buf("nt_printing_getsec", &secdesc_ctr, &ps, 1)) {
205 printf("error unpacking sec_desc_buf\n");
210 /* Print owner and group sid */
212 if (secdesc_ctr->sec->owner_sid) {
213 sid_to_string(sidstr, secdesc_ctr->sec->owner_sid);
218 printf("%s\n", sidstr);
220 if (secdesc_ctr->sec->grp_sid) {
221 sid_to_string(sidstr, secdesc_ctr->sec->grp_sid);
226 printf("%s\n", sidstr);
230 if (!secdesc_ctr->sec->dacl) {
235 for (i = 0; i < secdesc_ctr->sec->dacl->num_aces; i++) {
236 SEC_ACE *ace = &secdesc_ctr->sec->dacl->ace[i];
238 sid_to_string(sidstr, &ace->sid);
240 printf("%d %d 0x%08x %s\n", ace->type, ace->flags,
241 ace->info.mask, sidstr);
245 if (tdb) tdb_close(tdb);
246 if (mem_ctx) talloc_destroy(mem_ctx);
247 if (secdesc_ctr) free_sec_desc_buf(&secdesc_ctr);
253 /* Set a printer security descriptor */
255 int psec_setsec(char *printer)
257 DOM_SID user_sid, group_sid;
258 SEC_ACE *ace_list = NULL;
259 SEC_ACL *dacl = NULL;
261 SEC_DESC_BUF *sdb = NULL;
262 int result = 0, num_aces = 0;
263 fstring line, keystr, tdb_path;
266 TALLOC_CTX *mem_ctx = NULL;
267 BOOL has_user_sid = False, has_group_sid = False;
271 /* Open tdb for reading */
273 slprintf(tdb_path, sizeof(tdb_path) - 1, "%s/ntdrivers.tdb",
276 tdb = tdb_open(tdb_path, 0, 0, O_RDWR, 0600);
279 printf("psec: failed to open nt drivers database: %s\n",
285 /* Read owner and group sid */
287 fgets(line, sizeof(fstring), stdin);
288 if (line[0] != '\n') {
289 string_to_sid(&user_sid, line);
293 fgets(line, sizeof(fstring), stdin);
294 if (line[0] != '\n') {
295 string_to_sid(&group_sid, line);
296 has_group_sid = True;
299 /* Read ACEs from standard input for discretionary ACL */
301 while(fgets(line, sizeof(fstring), stdin)) {
302 int ace_type, ace_flags;
308 if (sscanf(line, "%d %d 0x%x %s", &ace_type, &ace_flags,
309 &ace_mask, sidstr) != 4) {
313 string_to_sid(&sid, sidstr);
315 ace_list = Realloc(ace_list, sizeof(SEC_ACE) *
318 init_sec_access(&sa, ace_mask);
319 init_sec_ace(&ace_list[num_aces], &sid, ace_type, sa,
325 dacl = make_sec_acl(ACL_REVISION, num_aces, ace_list);
328 /* Create security descriptor */
330 sd = make_sec_desc(SEC_DESC_REVISION,
331 has_user_sid ? &user_sid : NULL,
332 has_group_sid ? &group_sid : NULL,
333 NULL, /* System ACL */
334 dacl, /* Discretionary ACL */
339 sdb = make_sec_desc_buf(size, sd);
343 /* Write security descriptor to tdb */
345 mem_ctx = talloc_init();
348 printf("memory allocation error\n");
353 prs_init(&ps, (uint32)sec_desc_size(sdb->sec) +
354 sizeof(SEC_DESC_BUF), 4, mem_ctx, MARSHALL);
356 if (!sec_io_desc_buf("nt_printing_setsec", &sdb, &ps, 1)) {
357 printf("sec_io_desc_buf failed\n");
361 slprintf(keystr, sizeof(keystr) - 1, "SECDESC/%s", printer);
363 if (!tdb_prs_store(tdb, keystr, &ps)==0) {
364 printf("Failed to store secdesc for %s\n", printer);
369 if (tdb) tdb_close(tdb);
370 if (sdb) free_sec_desc_buf(&sdb);
371 if (mem_ctx) talloc_destroy(mem_ctx);
381 printf("Usage: psec getsec|setsec printername\n");
386 int main(int argc, char **argv)
388 pstring servicesf = CONFIGFILE;
397 /* Load smb.conf file */
399 charset_initialise();
401 if (!lp_load(servicesf,False,False,True)) {
402 fprintf(stderr, "Couldn't load confiuration file %s\n",
409 if (strcmp(argv[1], "setsec") == 0) {
416 return psec_setsec(argv[2]);
419 if (strcmp(argv[1], "getsec") == 0) {
426 return psec_getsec(argv[2]);
429 /* An unknown command */
431 printf("psec: unknown command %s\n", argv[1]);