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 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:
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
69 /* ACE type conversions */
71 char *ace_type_to_str(uint ace_type
)
76 case SEC_ACE_TYPE_ACCESS_DENIED
:
78 case SEC_ACE_TYPE_ACCESS_ALLOWED
:
82 slprintf(temp
, sizeof(temp
) - 1, "0x%02x", ace_type
);
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
;
97 /* ACE mask (permission) conversions */
99 char *ace_mask_to_str(uint32 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
:
112 slprintf(temp
, sizeof(temp
) - 1, "0x%08x", ace_mask
);
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
;
130 /* ACE conversions */
132 char *ace_to_str(SEC_ACE
*ace
)
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
);
146 void str_to_ace(SEC_ACE
*ace
, char *ace_str
)
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
;
169 /* Open tdb for reading */
171 slprintf(tdb_path
, sizeof(tdb_path
) - 1, "%s/ntdrivers.tdb",
174 tdb
= tdb_open(tdb_path
, 0, 0, O_RDONLY
, 0600);
177 printf("psec: failed to open nt drivers database: %s\n",
182 /* Get security blob from tdb */
184 slprintf(keystr
, sizeof(keystr
) - 1, "SECDESC/%s", printer
);
186 mem_ctx
= talloc_init();
189 printf("memory allocation error\n");
194 if (tdb_prs_fetch(tdb
, keystr
, &ps
, mem_ctx
) != 0) {
195 printf("error fetching descriptor for printer %s\n",
197 /* cannot do a prs_mem_free() when tdb_prs_fetch fails */
198 /* as the prs structure has not been initialized */
200 talloc_destroy(mem_ctx
);
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");
212 /* Print owner and group sid */
214 if (secdesc_ctr
->sec
->owner_sid
) {
215 sid_to_string(sidstr
, secdesc_ctr
->sec
->owner_sid
);
220 printf("%s\n", sidstr
);
222 if (secdesc_ctr
->sec
->grp_sid
) {
223 sid_to_string(sidstr
, secdesc_ctr
->sec
->grp_sid
);
228 printf("%s\n", sidstr
);
232 if (!secdesc_ctr
->sec
->dacl
) {
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
);
247 if (tdb
) tdb_close(tdb
);
248 if (mem_ctx
) talloc_destroy(mem_ctx
);
249 if (secdesc_ctr
) free_sec_desc_buf(&secdesc_ctr
);
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
;
263 SEC_DESC_BUF
*sdb
= NULL
;
264 int result
= 0, num_aces
= 0;
265 fstring line
, keystr
, tdb_path
;
268 TALLOC_CTX
*mem_ctx
= NULL
;
269 BOOL has_user_sid
= False
, has_group_sid
= False
;
273 /* Open tdb for reading */
275 slprintf(tdb_path
, sizeof(tdb_path
) - 1, "%s/ntdrivers.tdb",
278 tdb
= tdb_open(tdb_path
, 0, 0, O_RDWR
, 0600);
281 printf("psec: failed to open nt drivers database: %s\n",
287 /* Read owner and group sid */
289 fgets(line
, sizeof(fstring
), stdin
);
290 if (line
[0] != '\n') {
291 string_to_sid(&user_sid
, line
);
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
;
310 if (sscanf(line
, "%d %d 0x%x %s", &ace_type
, &ace_flags
,
311 &ace_mask
, sidstr
) != 4) {
315 string_to_sid(&sid
, sidstr
);
317 ace_list
= Realloc(ace_list
, sizeof(SEC_ACE
) *
320 init_sec_access(&sa
, ace_mask
);
321 init_sec_ace(&ace_list
[num_aces
], &sid
, ace_type
, sa
,
327 dacl
= make_sec_acl(ACL_REVISION
, num_aces
, 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 */
341 sdb
= make_sec_desc_buf(size
, sd
);
345 /* Write security descriptor to tdb */
347 mem_ctx
= talloc_init();
350 printf("memory allocation error\n");
355 if (!prs_init(&ps
, (uint32
)sec_desc_size(sdb
->sec
) +
356 sizeof(SEC_DESC_BUF
), 4, mem_ctx
, MARSHALL
)) {
357 printf("prs_init() failed\n");
361 if (!sec_io_desc_buf("nt_printing_setsec", &sdb
, &ps
, 1)) {
362 printf("sec_io_desc_buf failed\n");
366 slprintf(keystr
, sizeof(keystr
) - 1, "SECDESC/%s", printer
);
368 if (!tdb_prs_store(tdb
, keystr
, &ps
)==0) {
369 printf("Failed to store secdesc for %s\n", printer
);
374 if (tdb
) tdb_close(tdb
);
375 if (sdb
) free_sec_desc_buf(&sdb
);
376 if (mem_ctx
) talloc_destroy(mem_ctx
);
386 printf("Usage: psec getsec|setsec printername\n");
391 int main(int argc
, char **argv
)
393 pstring servicesf
= CONFIGFILE
;
402 /* Load smb.conf file */
404 charset_initialise();
406 if (!lp_load(servicesf
,False
,False
,True
)) {
407 fprintf(stderr
, "Couldn't load confiuration file %s\n",
414 if (strcmp(argv
[1], "setsec") == 0) {
421 return psec_setsec(argv
[2]);
424 if (strcmp(argv
[1], "getsec") == 0) {
431 return psec_getsec(argv
[2]);
434 /* An unknown command */
436 printf("psec: unknown command %s\n", argv
[1]);