r23785: use the GPLv3 boilerplate as recommended by the FSF and the license text
[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 3 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, see <http://www.gnu.org/licenses/>.
21 */
22
23 /* This program can get or set NT printer security permissions from the 
24    command line.  Usage: psec getsec|setsec printername.  You must have
25    write access to the ntdrivers.tdb file to set permissions and read
26    access to get permissions.
27
28    For this program to compile using the supplied Makefile.psec, Samba
29    must be configured with the --srcdir option
30
31    For getsec, output like the following is sent to standard output:
32
33        S-1-5-21-1067277791-1719175008-3000797951-500
34
35        1 9 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-501
36        1 2 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-501
37        0 9 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-500
38        0 2 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-500
39        0 9 0x10000000 S-1-5-21-1067277791-1719175008-3000797951-513
40        0 2 0x00020000 S-1-5-21-1067277791-1719175008-3000797951-513
41        0 2 0xe0000000 S-1-1-0
42
43    The first two lines describe the owner user and owner group of the printer.
44    If either of these lines are blank then the respective owner property is 
45    not set.  The remaining lines list the printer permissions or ACE entries, 
46    one per line.  Each column describes a different property of the ACE:
47
48        Column    Description
49        -------------------------------------------------------------------
50          1       ACE type (allow/deny etc) defined in rpc_secdes.h
51          2       ACE flags defined in rpc_secdes.h
52          3       ACE mask - printer ACE masks are defined in rpc_spoolss.h
53          4       SID the ACE applies to
54
55    The above example describes the following permissions in order:
56  
57        - The guest user has No Access to the printer
58        - The domain administrator has Full Access
59        - Domain Users can Manage Documents
60        - Everyone has Print access
61
62    The setsec command takes the output format but sets the security descriptor
63    appropriately. */
64
65 #include "includes.h"
66
67 TDB_CONTEXT *tdb;
68
69 /* ACE type conversions */
70
71 char *ace_type_to_str(uint ace_type)
72 {
73         static fstring temp;
74
75         switch(ace_type) {
76         case SEC_ACE_TYPE_ACCESS_DENIED:
77                 return "DENY";
78         case SEC_ACE_TYPE_ACCESS_ALLOWED:
79                 return "ALLOW";
80         }
81
82         slprintf(temp, sizeof(temp) - 1, "0x%02x", ace_type);
83         return temp;
84 }
85
86 uint str_to_ace_type(char *ace_type)
87 {
88         if (strcmp(ace_type, "ALLOWED") == 0) 
89                 return SEC_ACE_TYPE_ACCESS_ALLOWED;
90
91         if (strcmp(ace_type, "DENIED") == 0)
92                 return SEC_ACE_TYPE_ACCESS_DENIED;
93
94         return -1;
95 }               
96
97 /* ACE mask (permission) conversions */
98
99 char *ace_mask_to_str(uint32 ace_mask)
100 {
101         static fstring temp;
102
103         switch (ace_mask) {
104         case PRINTER_ACE_FULL_CONTROL:
105                 return "Full Control";
106         case PRINTER_ACE_MANAGE_DOCUMENTS:
107                 return "Manage Documents";
108         case PRINTER_ACE_PRINT:
109                 return "Print";
110         }
111
112         slprintf(temp, sizeof(temp) - 1, "0x%08x", ace_mask);
113         return temp;
114 }
115
116 uint32 str_to_ace_mask(char *ace_mask)
117 {
118         if (strcmp(ace_mask, "Full Control") == 0) 
119                 return PRINTER_ACE_FULL_CONTROL;
120
121         if (strcmp(ace_mask, "Manage Documents") == 0)
122                 return PRINTER_ACE_MANAGE_DOCUMENTS;
123
124         if (strcmp(ace_mask, "Print") == 0)
125                 return PRINTER_ACE_PRINT;
126
127         return -1;
128 }
129
130 /* ACE conversions */
131
132 char *ace_to_str(SEC_ACE *ace)
133 {
134         static pstring temp;
135         fstring sidstr;
136
137         sid_to_string(sidstr, &ace->sid);
138
139         slprintf(temp, sizeof(temp) - 1, "%s %d %s %s", 
140                  ace_type_to_str(ace->type), ace->flags,
141                  ace_mask_to_str(ace->info.mask), sidstr);
142
143         return temp;
144 }
145
146 void str_to_ace(SEC_ACE *ace, char *ace_str)
147 {
148         SEC_ACCESS sa;
149         DOM_SID sid;
150         uint32 mask;
151         uint8 type, flags;
152
153         init_sec_access(&sa, mask);
154         init_sec_ace(ace, &sid, type, sa, flags);
155 }
156
157 /* Get a printer security descriptor */
158
159 int psec_getsec(char *printer)
160 {
161         SEC_DESC_BUF *secdesc_ctr = NULL;
162         TALLOC_CTX *mem_ctx = NULL;
163         fstring keystr, sidstr, tdb_path;
164         prs_struct ps;
165         int result = 0, i;
166
167         ZERO_STRUCT(ps);
168
169         /* Open tdb for reading */
170
171         slprintf(tdb_path, sizeof(tdb_path) - 1, "%s/ntdrivers.tdb", 
172                  lp_lockdir());
173
174         tdb = tdb_open(tdb_path, 0, 0, O_RDONLY, 0600);
175
176         if (!tdb) {
177                 printf("psec: failed to open nt drivers database: %s\n",
178                        sys_errlist[errno]);
179                 return 1;
180         }
181
182         /* Get security blob from tdb */
183
184         slprintf(keystr, sizeof(keystr) - 1, "SECDESC/%s", printer);
185
186         mem_ctx = talloc_init();
187
188         if (!mem_ctx) {
189                 printf("memory allocation error\n");
190                 result = 1;
191                 goto done;
192         }
193
194         if (tdb_prs_fetch(tdb, keystr, &ps, mem_ctx) != 0) {
195                 printf("error fetching descriptor for printer %s\n",
196                        printer);
197                 /* cannot do a prs_mem_free() when tdb_prs_fetch fails */
198                 /* as the prs structure has not been initialized */
199                 tdb_close(tdb);
200                 talloc_destroy(mem_ctx);
201                 return 1;
202         }
203
204         /* Unpack into security descriptor buffer */
205
206         if (!sec_io_desc_buf("nt_printing_getsec", &secdesc_ctr, &ps, 1)) {
207                 printf("error unpacking sec_desc_buf\n");
208                 result = 1;
209                 goto done;
210         }
211
212         /* Print owner and group sid */
213
214         if (secdesc_ctr->sec->owner_sid) {
215                 sid_to_string(sidstr, secdesc_ctr->sec->owner_sid);
216         } else {
217                 fstrcpy(sidstr, "");
218         }
219
220         printf("%s\n", sidstr);
221
222         if (secdesc_ctr->sec->grp_sid) {
223                 sid_to_string(sidstr, secdesc_ctr->sec->grp_sid);
224         } else {
225                 fstrcpy(sidstr, "");
226         }
227
228         printf("%s\n", sidstr);
229
230         /* Print aces */
231
232         if (!secdesc_ctr->sec->dacl) {
233                 result = 0;
234                 goto done;
235         }
236
237         for (i = 0; i < secdesc_ctr->sec->dacl->num_aces; i++) {
238                 SEC_ACE *ace = &secdesc_ctr->sec->dacl->ace[i];
239
240                 sid_to_string(sidstr, &ace->sid);
241
242                 printf("%d %d 0x%08x %s\n", ace->type, ace->flags,
243                        ace->info.mask, sidstr);
244         }
245
246  done:
247         if (tdb) tdb_close(tdb);
248         if (mem_ctx) talloc_destroy(mem_ctx);
249         if (secdesc_ctr) free_sec_desc_buf(&secdesc_ctr);
250         prs_mem_free(&ps);
251
252         return result;
253 }
254
255 /* Set a printer security descriptor */
256
257 int psec_setsec(char *printer)
258 {
259         DOM_SID user_sid, group_sid;
260         SEC_ACE *ace_list = NULL;
261         SEC_ACL *dacl = NULL;
262         SEC_DESC *sd;
263         SEC_DESC_BUF *sdb = NULL;
264         int result = 0, num_aces = 0;
265         fstring line, keystr, tdb_path;
266         size_t size;
267         prs_struct ps;
268         TALLOC_CTX *mem_ctx = NULL;
269         BOOL has_user_sid = False, has_group_sid = False;
270
271         ZERO_STRUCT(ps);
272
273         /* Open tdb for reading */
274
275         slprintf(tdb_path, sizeof(tdb_path) - 1, "%s/ntdrivers.tdb", 
276                  lp_lockdir());
277
278         tdb = tdb_open(tdb_path, 0, 0, O_RDWR, 0600);
279
280         if (!tdb) {
281                 printf("psec: failed to open nt drivers database: %s\n",
282                        sys_errlist[errno]);
283                 result = 1;
284                 goto done;
285         }
286
287         /* Read owner and group sid */
288
289         fgets(line, sizeof(fstring), stdin);
290         if (line[0] != '\n') {
291                 string_to_sid(&user_sid, line);
292                 has_user_sid = True;
293         }
294
295         fgets(line, sizeof(fstring), stdin);
296         if (line[0] != '\n') {
297                 string_to_sid(&group_sid, line);
298                 has_group_sid = True;
299         }
300
301         /* Read ACEs from standard input for discretionary ACL */
302
303         while(fgets(line, sizeof(fstring), stdin)) {
304                 int ace_type, ace_flags;
305                 uint32 ace_mask;
306                 fstring sidstr;
307                 DOM_SID sid;
308                 SEC_ACCESS sa;
309
310                 if (sscanf(line, "%d %d 0x%x %s", &ace_type, &ace_flags, 
311                            &ace_mask, sidstr) != 4) {
312                         continue;
313                 }
314
315                 string_to_sid(&sid, sidstr);
316                 
317                 ace_list = Realloc(ace_list, sizeof(SEC_ACE) * 
318                                    (num_aces + 1));
319                 
320                 init_sec_access(&sa, ace_mask);
321                 init_sec_ace(&ace_list[num_aces], &sid, ace_type, sa, 
322                              ace_flags);
323
324                 num_aces++;
325         }
326
327         dacl = make_sec_acl(ACL_REVISION, num_aces, ace_list);
328         free(ace_list);
329
330         /* Create security descriptor */
331
332         sd = make_sec_desc(SEC_DESC_REVISION,
333                            has_user_sid ? &user_sid : NULL, 
334                            has_group_sid ? &group_sid : NULL,
335                            NULL, /* System ACL */
336                            dacl, /* Discretionary ACL */
337                            &size);
338
339         free_sec_acl(&dacl);
340
341         sdb = make_sec_desc_buf(size, sd);
342
343         free_sec_desc(&sd);
344
345         /* Write security descriptor to tdb */
346
347         mem_ctx = talloc_init();
348
349         if (!mem_ctx) {
350                 printf("memory allocation error\n");
351                 result = 1;
352                 goto done;
353         }
354
355         prs_init(&ps, (uint32)sec_desc_size(sdb->sec) + 
356                  sizeof(SEC_DESC_BUF), 4, mem_ctx, MARSHALL);
357
358         if (!sec_io_desc_buf("nt_printing_setsec", &sdb, &ps, 1)) {
359                 printf("sec_io_desc_buf failed\n");
360                 goto done;
361         }
362
363         slprintf(keystr, sizeof(keystr) - 1, "SECDESC/%s", printer);
364
365         if (!tdb_prs_store(tdb, keystr, &ps)==0) {
366                 printf("Failed to store secdesc for %s\n", printer);
367                 goto done;
368         }
369
370  done:
371         if (tdb) tdb_close(tdb);
372         if (sdb) free_sec_desc_buf(&sdb);
373         if (mem_ctx) talloc_destroy(mem_ctx);
374         prs_mem_free(&ps);
375
376         return result;
377 }
378
379 /* Help */
380
381 void usage(void)
382 {
383         printf("Usage: psec getsec|setsec printername\n");
384 }
385
386 /* Main function */
387
388 int main(int argc, char **argv)
389 {
390         pstring servicesf = CONFIGFILE;
391
392         /* Argument check */
393
394         if (argc == 1) {
395                 usage();
396                 return 1;
397         }
398
399         /* Load smb.conf file */
400
401         charset_initialise();
402
403         if (!lp_load(servicesf,False,False,True)) {
404                 fprintf(stderr, "Couldn't load confiuration file %s\n",
405                         servicesf);
406                 return 1;
407         }
408
409         /* Do commands */
410
411         if (strcmp(argv[1], "setsec") == 0) {
412
413                 if (argc != 3) {
414                         usage();
415                         return 1;
416                 }
417
418                 return psec_setsec(argv[2]);
419         }
420
421         if (strcmp(argv[1], "getsec") == 0) {
422
423                 if (argc != 3) {
424                         usage();
425                         return 1;
426                 }
427
428                 return psec_getsec(argv[2]);
429         }
430
431         /* An unknown command */
432
433         printf("psec: unknown command %s\n", argv[1]);
434         return 1;
435 }