r39: * importing .cvsignore files
[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         static 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         static 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         static 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 void 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         ZERO_STRUCT(ps);
169
170         /* Open tdb for reading */
171
172         slprintf(tdb_path, sizeof(tdb_path) - 1, "%s/ntdrivers.tdb", 
173                  lp_lockdir());
174
175         tdb = tdb_open(tdb_path, 0, 0, O_RDONLY, 0600);
176
177         if (!tdb) {
178                 printf("psec: failed to open nt drivers database: %s\n",
179                        sys_errlist[errno]);
180                 return 1;
181         }
182
183         /* Get security blob from tdb */
184
185         slprintf(keystr, sizeof(keystr) - 1, "SECDESC/%s", printer);
186
187         mem_ctx = talloc_init();
188
189         if (!mem_ctx) {
190                 printf("memory allocation error\n");
191                 result = 1;
192                 goto done;
193         }
194
195         if (tdb_prs_fetch(tdb, keystr, &ps, mem_ctx) != 0) {
196                 printf("error fetching descriptor for printer %s\n",
197                        printer);
198                 /* cannot do a prs_mem_free() when tdb_prs_fetch fails */
199                 /* as the prs structure has not been initialized */
200                 tdb_close(tdb);
201                 talloc_destroy(mem_ctx);
202                 return 1;
203         }
204
205         /* Unpack into security descriptor buffer */
206
207         if (!sec_io_desc_buf("nt_printing_getsec", &secdesc_ctr, &ps, 1)) {
208                 printf("error unpacking sec_desc_buf\n");
209                 result = 1;
210                 goto done;
211         }
212
213         /* Print owner and group sid */
214
215         if (secdesc_ctr->sec->owner_sid) {
216                 sid_to_string(sidstr, secdesc_ctr->sec->owner_sid);
217         } else {
218                 fstrcpy(sidstr, "");
219         }
220
221         printf("%s\n", sidstr);
222
223         if (secdesc_ctr->sec->grp_sid) {
224                 sid_to_string(sidstr, secdesc_ctr->sec->grp_sid);
225         } else {
226                 fstrcpy(sidstr, "");
227         }
228
229         printf("%s\n", sidstr);
230
231         /* Print aces */
232
233         if (!secdesc_ctr->sec->dacl) {
234                 result = 0;
235                 goto done;
236         }
237
238         for (i = 0; i < secdesc_ctr->sec->dacl->num_aces; i++) {
239                 SEC_ACE *ace = &secdesc_ctr->sec->dacl->ace[i];
240
241                 sid_to_string(sidstr, &ace->sid);
242
243                 printf("%d %d 0x%08x %s\n", ace->type, ace->flags,
244                        ace->info.mask, sidstr);
245         }
246
247  done:
248         if (tdb) tdb_close(tdb);
249         if (mem_ctx) talloc_destroy(mem_ctx);
250         if (secdesc_ctr) free_sec_desc_buf(&secdesc_ctr);
251         prs_mem_free(&ps);
252
253         return result;
254 }
255
256 /* Set a printer security descriptor */
257
258 int psec_setsec(char *printer)
259 {
260         DOM_SID user_sid, group_sid;
261         SEC_ACE *ace_list = NULL;
262         SEC_ACL *dacl = NULL;
263         SEC_DESC *sd;
264         SEC_DESC_BUF *sdb = NULL;
265         int result = 0, num_aces = 0;
266         fstring line, keystr, tdb_path;
267         size_t size;
268         prs_struct ps;
269         TALLOC_CTX *mem_ctx = NULL;
270         BOOL has_user_sid = False, has_group_sid = False;
271
272         ZERO_STRUCT(ps);
273
274         /* Open tdb for reading */
275
276         slprintf(tdb_path, sizeof(tdb_path) - 1, "%s/ntdrivers.tdb", 
277                  lp_lockdir());
278
279         tdb = tdb_open(tdb_path, 0, 0, O_RDWR, 0600);
280
281         if (!tdb) {
282                 printf("psec: failed to open nt drivers database: %s\n",
283                        sys_errlist[errno]);
284                 result = 1;
285                 goto done;
286         }
287
288         /* Read owner and group sid */
289
290         fgets(line, sizeof(fstring), stdin);
291         if (line[0] != '\n') {
292                 string_to_sid(&user_sid, line);
293                 has_user_sid = True;
294         }
295
296         fgets(line, sizeof(fstring), stdin);
297         if (line[0] != '\n') {
298                 string_to_sid(&group_sid, line);
299                 has_group_sid = True;
300         }
301
302         /* Read ACEs from standard input for discretionary ACL */
303
304         while(fgets(line, sizeof(fstring), stdin)) {
305                 int ace_type, ace_flags;
306                 uint32 ace_mask;
307                 fstring sidstr;
308                 DOM_SID sid;
309                 SEC_ACCESS sa;
310
311                 if (sscanf(line, "%d %d 0x%x %s", &ace_type, &ace_flags, 
312                            &ace_mask, sidstr) != 4) {
313                         continue;
314                 }
315
316                 string_to_sid(&sid, sidstr);
317                 
318                 ace_list = Realloc(ace_list, sizeof(SEC_ACE) * 
319                                    (num_aces + 1));
320                 
321                 init_sec_access(&sa, ace_mask);
322                 init_sec_ace(&ace_list[num_aces], &sid, ace_type, sa, 
323                              ace_flags);
324
325                 num_aces++;
326         }
327
328         dacl = make_sec_acl(ACL_REVISION, num_aces, ace_list);
329         free(ace_list);
330
331         /* Create security descriptor */
332
333         sd = make_sec_desc(SEC_DESC_REVISION,
334                            has_user_sid ? &user_sid : NULL, 
335                            has_group_sid ? &group_sid : NULL,
336                            NULL, /* System ACL */
337                            dacl, /* Discretionary ACL */
338                            &size);
339
340         free_sec_acl(&dacl);
341
342         sdb = make_sec_desc_buf(size, sd);
343
344         free_sec_desc(&sd);
345
346         /* Write security descriptor to tdb */
347
348         mem_ctx = talloc_init();
349
350         if (!mem_ctx) {
351                 printf("memory allocation error\n");
352                 result = 1;
353                 goto done;
354         }
355
356         prs_init(&ps, (uint32)sec_desc_size(sdb->sec) + 
357                  sizeof(SEC_DESC_BUF), 4, mem_ctx, MARSHALL);
358
359         if (!sec_io_desc_buf("nt_printing_setsec", &sdb, &ps, 1)) {
360                 printf("sec_io_desc_buf failed\n");
361                 goto done;
362         }
363
364         slprintf(keystr, sizeof(keystr) - 1, "SECDESC/%s", printer);
365
366         if (!tdb_prs_store(tdb, keystr, &ps)==0) {
367                 printf("Failed to store secdesc for %s\n", printer);
368                 goto done;
369         }
370
371  done:
372         if (tdb) tdb_close(tdb);
373         if (sdb) free_sec_desc_buf(&sdb);
374         if (mem_ctx) talloc_destroy(mem_ctx);
375         prs_mem_free(&ps);
376
377         return result;
378 }
379
380 /* Help */
381
382 void usage(void)
383 {
384         printf("Usage: psec getsec|setsec printername\n");
385 }
386
387 /* Main function */
388
389 int main(int argc, char **argv)
390 {
391         pstring servicesf = CONFIGFILE;
392
393         /* Argument check */
394
395         if (argc == 1) {
396                 usage();
397                 return 1;
398         }
399
400         /* Load smb.conf file */
401
402         charset_initialise();
403
404         if (!lp_load(servicesf,False,False,True)) {
405                 fprintf(stderr, "Couldn't load confiuration file %s\n",
406                         servicesf);
407                 return 1;
408         }
409
410         /* Do commands */
411
412         if (strcmp(argv[1], "setsec") == 0) {
413
414                 if (argc != 3) {
415                         usage();
416                         return 1;
417                 }
418
419                 return psec_setsec(argv[2]);
420         }
421
422         if (strcmp(argv[1], "getsec") == 0) {
423
424                 if (argc != 3) {
425                         usage();
426                         return 1;
427                 }
428
429                 return psec_getsec(argv[2]);
430         }
431
432         /* An unknown command */
433
434         printf("psec: unknown command %s\n", argv[1]);
435         return 1;
436 }