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