e3490de7598e4df220021530ccd3a25b2fe838cb
[amitay/samba.git] / testsuite / printing / psec.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 2.0
4
5    Printer security permission manipulation.
6
7    Copyright (C) Tim Potter 2000
8    
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.
13    
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.
18    
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.
22 */
23
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.
28
29    For this program to compile using the supplied Makefile.psec, Samba
30    must be configured with the --srcdir option
31
32    For getsec, output like the following is sent to standard output:
33
34        S-1-5-21-1067277791-1719175008-3000797951-500
35
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
43
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:
48
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
55
56    The above example describes the following permissions in order:
57  
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
62
63    The setsec command takes the output format but sets the security descriptor
64    appropriately. */
65
66 #include "includes.h"
67
68 TDB_CONTEXT *tdb;
69
70 /* ACE type conversions */
71
72 char *ace_type_to_str(uint ace_type)
73 {
74         fstring temp;
75
76         switch(ace_type) {
77         case SEC_ACE_TYPE_ACCESS_DENIED:
78                 return "DENY";
79         case SEC_ACE_TYPE_ACCESS_ALLOWED:
80                 return "ALLOW";
81         }
82
83         slprintf(temp, sizeof(temp) - 1, "0x%02x", ace_type);
84         return temp;
85 }
86
87 uint str_to_ace_type(char *ace_type)
88 {
89         if (strcmp(ace_type, "ALLOWED") == 0) 
90                 return SEC_ACE_TYPE_ACCESS_ALLOWED;
91
92         if (strcmp(ace_type, "DENIED") == 0)
93                 return SEC_ACE_TYPE_ACCESS_DENIED;
94
95         return -1;
96 }               
97
98 /* ACE mask (permission) conversions */
99
100 char *ace_mask_to_str(uint32 ace_mask)
101 {
102         fstring temp;
103
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";
111         }
112
113         slprintf(temp, sizeof(temp) - 1, "0x%08x", ace_mask);
114         return temp;
115 }
116
117 uint32 str_to_ace_mask(char *ace_mask)
118 {
119         if (strcmp(ace_mask, "Full Control") == 0) 
120                 return PRINTER_ACE_FULL_CONTROL;
121
122         if (strcmp(ace_mask, "Manage Documents") == 0)
123                 return PRINTER_ACE_MANAGE_DOCUMENTS;
124
125         if (strcmp(ace_mask, "Print") == 0)
126                 return PRINTER_ACE_PRINT;
127
128         return -1;
129 }
130
131 /* ACE conversions */
132
133 char *ace_to_str(SEC_ACE *ace)
134 {
135         pstring temp;
136         fstring sidstr;
137
138         sid_to_string(sidstr, &ace->sid);
139
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);
143
144         return temp;
145 }
146
147 int str_to_ace(SEC_ACE *ace, char *ace_str)
148 {
149         SEC_ACCESS sa;
150         DOM_SID sid;
151         uint32 mask;
152         uint8 type, flags;
153
154         init_sec_access(&sa, mask);
155         init_sec_ace(ace, &sid, type, sa, flags);
156 }
157
158 /* Get a printer security descriptor */
159
160 int psec_getsec(char *printer)
161 {
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;
167
168         /* Open tdb for reading */
169
170         slprintf(tdb_path, "%s/ntdrivers.tdb", LOCKDIR);
171         tdb = tdb_open(tdb_path, 0, 0, O_RDONLY, 0600);
172
173         if (!tdb) {
174                 printf("psec: failed to open nt drivers database: %s\n",
175                        sys_errlist[errno]);
176                 return 1;
177         }
178
179         /* Get security blob from tdb */
180
181         slprintf(keystr, sizeof(keystr) - 1, "SECDESC/%s", printer);
182
183         mem_ctx = talloc_init();
184
185         if (!mem_ctx) {
186                 printf("memory allocation error\n");
187                 result = 1;
188                 goto done;
189         }
190
191         if (tdb_prs_fetch(tdb, keystr, &ps, mem_ctx) != 0) {
192                 printf("error fetching descriptor for printer %s\n",
193                        printer);
194                 result = 1;
195                 goto done;
196         }
197
198         /* Unpack into security descriptor buffer */
199
200         if (!sec_io_desc_buf("nt_printing_getsec", &secdesc_ctr, &ps, 1)) {
201                 printf("error unpacking sec_desc_buf\n");
202                 result = 1;
203                 goto done;
204         }
205
206         /* Print owner and group sid */
207
208         if (secdesc_ctr->sec->owner_sid) {
209                 sid_to_string(sidstr, secdesc_ctr->sec->owner_sid);
210         } else {
211                 fstrcpy(sidstr, "");
212         }
213
214         printf("%s\n", sidstr);
215
216         if (secdesc_ctr->sec->grp_sid) {
217                 sid_to_string(sidstr, secdesc_ctr->sec->grp_sid);
218         } else {
219                 fstrcpy(sidstr, "");
220         }
221
222         printf("%s\n", sidstr);
223
224         /* Print aces */
225
226         if (!secdesc_ctr->sec->dacl) {
227                 result = 0;
228                 goto done;
229         }
230
231         for (i = 0; i < secdesc_ctr->sec->dacl->num_aces; i++) {
232                 SEC_ACE *ace = &secdesc_ctr->sec->dacl->ace[i];
233                 fstring sidstr;
234
235                 sid_to_string(sidstr, &ace->sid);
236
237                 printf("%d %d 0x%08x %s\n", ace->type, ace->flags,
238                        ace->info.mask, sidstr);
239         }
240
241  done:
242         if (tdb) tdb_close(tdb);
243         if (mem_ctx) talloc_destroy(mem_ctx);
244         if (secdesc_ctr) free_sec_desc_buf(&secdesc_ctr);
245
246         return result;
247 }
248
249 /* Set a printer security descriptor */
250
251 int psec_setsec(char *printer)
252 {
253         DOM_SID user_sid, group_sid;
254         SEC_ACE *ace_list = NULL;
255         SEC_ACL *dacl;
256         SEC_DESC *sd;
257         SEC_DESC_BUF *sdb = NULL;
258         int result = 0, num_aces = 0;
259         fstring line, keystr, tdb_path;
260         size_t size;
261         prs_struct ps;
262         TALLOC_CTX *mem_ctx = NULL;
263         BOOL has_user_sid = False, has_group_sid = False;
264
265         /* Open tdb for reading */
266
267         slprintf(tdb_path, "%s/ntdrivers.tdb", LOCKDIR);
268         tdb = tdb_open(tdb_path, 0, 0, O_RDWR, 0600);
269
270         if (!tdb) {
271                 printf("psec: failed to open nt drivers database: %s\n",
272                        sys_errlist[errno]);
273                 result = 1;
274                 goto done;
275         }
276
277         /* Read owner and group sid */
278
279         fgets(line, sizeof(fstring), stdin);
280         if (line[0] != '\n') {
281                 string_to_sid(&user_sid, line);
282                 has_user_sid = True;
283         }
284
285         fgets(line, sizeof(fstring), stdin);
286         if (line[0] != '\n') {
287                 string_to_sid(&group_sid, line);
288                 has_group_sid = True;
289         }
290
291         /* Read ACEs from standard input for discretionary ACL */
292
293         while(fgets(line, sizeof(fstring), stdin)) {
294                 int ace_type, ace_flags;
295                 uint32 ace_mask;
296                 fstring sidstr;
297                 DOM_SID sid;
298                 SEC_ACCESS sa;
299
300                 if (sscanf(line, "%d %d 0x%x %s", &ace_type, &ace_flags, 
301                            &ace_mask, sidstr) != 4) {
302                         continue;
303                 }
304
305                 string_to_sid(&sid, sidstr);
306                 
307                 ace_list = Realloc(ace_list, sizeof(SEC_ACE) * 
308                                    (num_aces + 1));
309                 
310                 init_sec_access(&sa, ace_mask);
311                 init_sec_ace(&ace_list[num_aces], &sid, ace_type, sa, 
312                              ace_flags);
313
314                 num_aces++;
315         }
316
317         dacl = make_sec_acl(ACL_REVISION, num_aces, ace_list);
318         free(ace_list);
319
320         /* Create security descriptor */
321
322         sd = make_sec_desc(SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE |
323                            SEC_DESC_DACL_PRESENT, 
324                            has_user_sid ? &user_sid : NULL, 
325                            has_group_sid ? &group_sid : NULL,
326                            NULL, /* System ACL */
327                            dacl, /* Discretionary ACL */
328                            &size);
329
330         sdb = make_sec_desc_buf(size, sd);
331
332         free_sec_desc(&sd);
333
334         /* Write security descriptor to tdb */
335
336         mem_ctx = talloc_init();
337
338         if (!mem_ctx) {
339                 printf("memory allocation error\n");
340                 result = 1;
341                 goto done;
342         }
343
344         prs_init(&ps, (uint32)sec_desc_size(sdb->sec) + 
345                  sizeof(SEC_DESC_BUF), 4, mem_ctx, MARSHALL);
346
347         if (!sec_io_desc_buf("nt_printing_setsec", &sdb, &ps, 1)) {
348                 printf("sec_io_desc_buf failed\n");
349                 goto done;
350         }
351
352         slprintf(keystr, sizeof(keystr) - 1, "SECDESC/%s", printer);
353
354         if (!tdb_prs_store(tdb, keystr, &ps)==0) {
355                 printf("Failed to store secdesc for %s\n", printer);
356                 goto done;
357         }
358
359  done:
360         if (tdb) tdb_close(tdb);
361         if (sdb) free_sec_desc_buf(&sdb);
362         if (mem_ctx) talloc_destroy(mem_ctx);
363
364         return result;
365 }
366
367 /* Help */
368
369 void usage(void)
370 {
371         printf("Usage: psec getsec|setsec printername\n");
372 }
373
374 /* Main function */
375
376 int main(int argc, char **argv)
377 {
378         /* Argument check */
379
380         if (argc == 1) {
381                 usage();
382                 return 1;
383         }
384
385         /* Do commands */
386
387         if (strcmp(argv[1], "setsec") == 0) {
388
389                 if (argc != 3) {
390                         usage();
391                         return 1;
392                 }
393
394                 return psec_setsec(argv[2]);
395         }
396
397         if (strcmp(argv[1], "getsec") == 0) {
398
399                 if (argc != 3) {
400                         usage();
401                         return 1;
402                 }
403
404                 return psec_getsec(argv[2]);
405         }
406
407         /* An unknown command */
408
409         printf("psec: unknown command %s\n", argv[1]);
410         return 1;
411 }