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