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 68TDB_CONTEXT *tdb; 69 70/* ACE type conversions */ 71 72char *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 87uint 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 100char *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 117uint32 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 133char *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 147void 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 160int 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 258int 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 382void usage(void) 383{ 384 printf("Usage: psec getsec|setsec printername\n"); 385} 386 387/* Main function */ 388 389int 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} 437