Changes from APPLIANCE_HEAD (per Tim Potter):
[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         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         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                 fstring sidstr;
236
237                 sid_to_string(sidstr, &ace->sid);
238
239                 printf("%d %d 0x%08x %s\n", ace->type, ace->flags,
240                        ace->info.mask, sidstr);
241         }
242
243  done:
244         if (tdb) tdb_close(tdb);
245         if (mem_ctx) talloc_destroy(mem_ctx);
246         if (secdesc_ctr) free_sec_desc_buf(&secdesc_ctr);
247         prs_mem_free(&ps);
248
249         return result;
250 }
251
252 /* Set a printer security descriptor */
253
254 int psec_setsec(char *printer)
255 {
256         DOM_SID user_sid, group_sid;
257         SEC_ACE *ace_list = NULL;
258         SEC_ACL *dacl = NULL;
259         SEC_DESC *sd;
260         SEC_DESC_BUF *sdb = NULL;
261         int result = 0, num_aces = 0;
262         fstring line, keystr, tdb_path;
263         size_t size;
264         prs_struct ps;
265         TALLOC_CTX *mem_ctx = NULL;
266         BOOL has_user_sid = False, has_group_sid = False;
267
268         ZERO_STRUCT(ps);
269
270         /* Open tdb for reading */
271
272         slprintf(tdb_path, sizeof(tdb_path) - 1, "%s/ntdrivers.tdb", LOCKDIR);
273         tdb = tdb_open(tdb_path, 0, 0, O_RDWR, 0600);
274
275         if (!tdb) {
276                 printf("psec: failed to open nt drivers database: %s\n",
277                        sys_errlist[errno]);
278                 result = 1;
279                 goto done;
280         }
281
282         /* Read owner and group sid */
283
284         fgets(line, sizeof(fstring), stdin);
285         if (line[0] != '\n') {
286                 string_to_sid(&user_sid, line);
287                 has_user_sid = True;
288         }
289
290         fgets(line, sizeof(fstring), stdin);
291         if (line[0] != '\n') {
292                 string_to_sid(&group_sid, line);
293                 has_group_sid = True;
294         }
295
296         /* Read ACEs from standard input for discretionary ACL */
297
298         while(fgets(line, sizeof(fstring), stdin)) {
299                 int ace_type, ace_flags;
300                 uint32 ace_mask;
301                 fstring sidstr;
302                 DOM_SID sid;
303                 SEC_ACCESS sa;
304
305                 if (sscanf(line, "%d %d 0x%x %s", &ace_type, &ace_flags, 
306                            &ace_mask, sidstr) != 4) {
307                         continue;
308                 }
309
310                 string_to_sid(&sid, sidstr);
311                 
312                 ace_list = Realloc(ace_list, sizeof(SEC_ACE) * 
313                                    (num_aces + 1));
314                 
315                 init_sec_access(&sa, ace_mask);
316                 init_sec_ace(&ace_list[num_aces], &sid, ace_type, sa, 
317                              ace_flags);
318
319                 num_aces++;
320         }
321
322         dacl = make_sec_acl(ACL_REVISION, num_aces, ace_list);
323         free(ace_list);
324
325         /* Create security descriptor */
326
327         sd = make_sec_desc(SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE |
328                            SEC_DESC_DACL_PRESENT, 
329                            has_user_sid ? &user_sid : NULL, 
330                            has_group_sid ? &group_sid : NULL,
331                            NULL, /* System ACL */
332                            dacl, /* Discretionary ACL */
333                            &size);
334
335         free_sec_acl(&dacl);
336
337         sdb = make_sec_desc_buf(size, sd);
338
339         free_sec_desc(&sd);
340
341         /* Write security descriptor to tdb */
342
343         mem_ctx = talloc_init();
344
345         if (!mem_ctx) {
346                 printf("memory allocation error\n");
347                 result = 1;
348                 goto done;
349         }
350
351         prs_init(&ps, (uint32)sec_desc_size(sdb->sec) + 
352                  sizeof(SEC_DESC_BUF), 4, mem_ctx, MARSHALL);
353
354         if (!sec_io_desc_buf("nt_printing_setsec", &sdb, &ps, 1)) {
355                 printf("sec_io_desc_buf failed\n");
356                 goto done;
357         }
358
359         slprintf(keystr, sizeof(keystr) - 1, "SECDESC/%s", printer);
360
361         if (!tdb_prs_store(tdb, keystr, &ps)==0) {
362                 printf("Failed to store secdesc for %s\n", printer);
363                 goto done;
364         }
365
366  done:
367         if (tdb) tdb_close(tdb);
368         if (sdb) free_sec_desc_buf(&sdb);
369         if (mem_ctx) talloc_destroy(mem_ctx);
370         prs_mem_free(&ps);
371
372         return result;
373 }
374
375 /* Help */
376
377 void usage(void)
378 {
379         printf("Usage: psec getsec|setsec printername\n");
380 }
381
382 /* Main function */
383
384 int main(int argc, char **argv)
385 {
386         /* Argument check */
387
388         if (argc == 1) {
389                 usage();
390                 return 1;
391         }
392
393         /* Do commands */
394
395         if (strcmp(argv[1], "setsec") == 0) {
396
397                 if (argc != 3) {
398                         usage();
399                         return 1;
400                 }
401
402                 return psec_setsec(argv[2]);
403         }
404
405         if (strcmp(argv[1], "getsec") == 0) {
406
407                 if (argc != 3) {
408                         usage();
409                         return 1;
410                 }
411
412                 return psec_getsec(argv[2]);
413         }
414
415         /* An unknown command */
416
417         printf("psec: unknown command %s\n", argv[1]);
418         return 1;
419 }