1/* 2 Unix SMB/CIFS implementation. 3 Privileges handling functions 4 Copyright (C) Jean Fran��ois Micouleau 1998-2001 5 Copyright (C) Simo Sorce 2002-2003 6 Copyright (C) Gerald (Jerry) Carter 2005 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21*/ 22 23 24#include "includes.h" 25 26#define PRIVPREFIX "PRIV_" 27 28static const SE_PRIV se_priv_all = SE_ALL_PRIVS; 29static const SE_PRIV se_priv_end = SE_END; 30 31/* Define variables for all privileges so we can use the 32 SE_PRIV* in the various se_priv_XXX() functions */ 33 34const SE_PRIV se_priv_none = SE_NONE; 35const SE_PRIV se_machine_account = SE_MACHINE_ACCOUNT; 36const SE_PRIV se_print_operator = SE_PRINT_OPERATOR; 37const SE_PRIV se_add_users = SE_ADD_USERS; 38const SE_PRIV se_disk_operators = SE_DISK_OPERATOR; 39const SE_PRIV se_remote_shutdown = SE_REMOTE_SHUTDOWN; 40const SE_PRIV se_restore = SE_RESTORE; 41const SE_PRIV se_take_ownership = SE_TAKE_OWNERSHIP; 42 43/******************************************************************** 44 This is a list of privileges reported by a WIndows 2000 SP4 AD DC 45 just for reference purposes (and I know the LUID is not guaranteed 46 across reboots): 47 48 SeCreateTokenPrivilege Create a token object ( 0x0, 0x2 ) 49 SeAssignPrimaryTokenPrivilege Replace a process level token ( 0x0, 0x3 ) 50 SeLockMemoryPrivilege Lock pages in memory ( 0x0, 0x4 ) 51 SeIncreaseQuotaPrivilege Increase quotas ( 0x0, 0x5 ) 52 SeMachineAccountPrivilege Add workstations to domain ( 0x0, 0x6 ) 53 SeTcbPrivilege Act as part of the operating system ( 0x0, 0x7 ) 54 SeSecurityPrivilege Manage auditing and security log ( 0x0, 0x8 ) 55 SeTakeOwnershipPrivilege Take ownership of files or other objects ( 0x0, 0x9 ) 56 SeLoadDriverPrivilege Load and unload device drivers ( 0x0, 0xa ) 57 SeSystemProfilePrivilege Profile system performance ( 0x0, 0xb ) 58 SeSystemtimePrivilege Change the system time ( 0x0, 0xc ) 59 SeProfileSingleProcessPrivilege Profile single process ( 0x0, 0xd ) 60 SeIncreaseBasePriorityPrivilege Increase scheduling priority ( 0x0, 0xe ) 61 SeCreatePagefilePrivilege Create a pagefile ( 0x0, 0xf ) 62 SeCreatePermanentPrivilege Create permanent shared objects ( 0x0, 0x10 ) 63 SeBackupPrivilege Back up files and directories ( 0x0, 0x11 ) 64 SeRestorePrivilege Restore files and directories ( 0x0, 0x12 ) 65 SeShutdownPrivilege Shut down the system ( 0x0, 0x13 ) 66 SeDebugPrivilege Debug programs ( 0x0, 0x14 ) 67 SeAuditPrivilege Generate security audits ( 0x0, 0x15 ) 68 SeSystemEnvironmentPrivilege Modify firmware environment values ( 0x0, 0x16 ) 69 SeChangeNotifyPrivilege Bypass traverse checking ( 0x0, 0x17 ) 70 SeRemoteShutdownPrivilege Force shutdown from a remote system ( 0x0, 0x18 ) 71 SeUndockPrivilege Remove computer from docking station ( 0x0, 0x19 ) 72 SeSyncAgentPrivilege Synchronize directory service data ( 0x0, 0x1a ) 73 SeEnableDelegationPrivilege Enable computer and user accounts to be trusted for delegation ( 0x0, 0x1b ) 74 SeManageVolumePrivilege Perform volume maintenance tasks ( 0x0, 0x1c ) 75 SeImpersonatePrivilege Impersonate a client after authentication ( 0x0, 0x1d ) 76 SeCreateGlobalPrivilege Create global objects ( 0x0, 0x1e ) 77 78 ********************************************************************/ 79 80/* we have to define the LUID here due to a horrible check by printmig.exe 81 that requires the SeBackupPrivilege match what is in Windows. So match 82 those that we implement and start Samba privileges at 0x1001 */ 83 84PRIVS privs[] = { 85#if 0 /* usrmgr will display these twice if you include them. We don't 86 use them but we'll keep the bitmasks reserved in privileges.h anyways */ 87 88 {SE_NETWORK_LOGON, "SeNetworkLogonRight", "Access this computer from network", { 0x0, 0x0 }}, 89 {SE_INTERACTIVE_LOGON, "SeInteractiveLogonRight", "Log on locally", { 0x0, 0x0 }}, 90 {SE_BATCH_LOGON, "SeBatchLogonRight", "Log on as a batch job", { 0x0, 0x0 }}, 91 {SE_SERVICE_LOGON, "SeServiceLogonRight", "Log on as a service", { 0x0, 0x0 }}, 92#endif 93 {SE_MACHINE_ACCOUNT, "SeMachineAccountPrivilege", "Add machines to domain", { 0x0, 0x0006 }}, 94 {SE_TAKE_OWNERSHIP, "SeTakeOwnershipPrivilege", "Take ownership of files or other objects",{ 0x0, 0x0009 }}, 95 {SE_BACKUP, "SeBackupPrivilege", "Back up files and directories", { 0x0, 0x0011 }}, 96 {SE_RESTORE, "SeRestorePrivilege", "Restore files and directories", { 0x0, 0x0012 }}, 97 {SE_REMOTE_SHUTDOWN, "SeRemoteShutdownPrivilege", "Force shutdown from a remote system", { 0x0, 0x0018 }}, 98 99 {SE_PRINT_OPERATOR, "SePrintOperatorPrivilege", "Manage printers", { 0x0, 0x1001 }}, 100 {SE_ADD_USERS, "SeAddUsersPrivilege", "Add users and groups to the domain", { 0x0, 0x1002 }}, 101 {SE_DISK_OPERATOR, "SeDiskOperatorPrivilege", "Manage disk shares", { 0x0, 0x1003 }}, 102 103 {SE_END, "", "", { 0x0, 0x0 }} 104}; 105 106typedef struct { 107 size_t count; 108 DOM_SID *list; 109} SID_LIST; 110 111typedef struct { 112 SE_PRIV privilege; 113 SID_LIST sids; 114} PRIV_SID_LIST; 115 116/*************************************************************************** 117 copy an SE_PRIV structure 118****************************************************************************/ 119 120BOOL se_priv_copy( SE_PRIV *dst, const SE_PRIV *src ) 121{ 122 if ( !dst || !src ) 123 return False; 124 125 memcpy( dst, src, sizeof(SE_PRIV) ); 126 127 return True; 128} 129 130/*************************************************************************** 131 combine 2 SE_PRIV structures and store the resulting set in mew_mask 132****************************************************************************/ 133 134void se_priv_add( SE_PRIV *mask, const SE_PRIV *addpriv ) 135{ 136 int i; 137 138 for ( i=0; i<SE_PRIV_MASKSIZE; i++ ) { 139 mask->mask[i] |= addpriv->mask[i]; 140 } 141} 142 143/*************************************************************************** 144 remove one SE_PRIV sytucture from another and store the resulting set 145 in mew_mask 146****************************************************************************/ 147 148void se_priv_remove( SE_PRIV *mask, const SE_PRIV *removepriv ) 149{ 150 int i; 151 152 for ( i=0; i<SE_PRIV_MASKSIZE; i++ ) { 153 mask->mask[i] &= ~removepriv->mask[i]; 154 } 155} 156 157/*************************************************************************** 158 invert a given SE_PRIV and store the set in new_mask 159****************************************************************************/ 160 161static void se_priv_invert( SE_PRIV *new_mask, const SE_PRIV *mask ) 162{ 163 SE_PRIV allprivs; 164 165 se_priv_copy( &allprivs, &se_priv_all ); 166 se_priv_remove( &allprivs, mask ); 167 se_priv_copy( new_mask, &allprivs ); 168} 169 170/*************************************************************************** 171 check if 2 SE_PRIV structure are equal 172****************************************************************************/ 173 174static BOOL se_priv_equal( const SE_PRIV *mask1, const SE_PRIV *mask2 ) 175{ 176 return ( memcmp(mask1, mask2, sizeof(SE_PRIV)) == 0 ); 177} 178 179/*************************************************************************** 180 check if a SE_PRIV has any assigned privileges 181****************************************************************************/ 182 183static BOOL se_priv_empty( const SE_PRIV *mask ) 184{ 185 SE_PRIV p1; 186 int i; 187 188 se_priv_copy( &p1, mask ); 189 190 for ( i=0; i<SE_PRIV_MASKSIZE; i++ ) { 191 p1.mask[i] &= se_priv_all.mask[i]; 192 } 193 194 return se_priv_equal( &p1, &se_priv_none ); 195} 196 197/********************************************************************* 198 Lookup the SE_PRIV value for a privilege name 199*********************************************************************/ 200 201BOOL se_priv_from_name( const char *name, SE_PRIV *mask ) 202{ 203 int i; 204 205 for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) { 206 if ( strequal( privs[i].name, name ) ) { 207 se_priv_copy( mask, &privs[i].se_priv ); 208 return True; 209 } 210 } 211 212 return False; 213} 214 215/*************************************************************************** 216 dump an SE_PRIV structure to the log files 217****************************************************************************/ 218 219void dump_se_priv( int dbg_cl, int dbg_lvl, const SE_PRIV *mask ) 220{ 221 int i; 222 223 DEBUGADDC( dbg_cl, dbg_lvl,("SE_PRIV ")); 224 225 for ( i=0; i<SE_PRIV_MASKSIZE; i++ ) { 226 DEBUGADDC( dbg_cl, dbg_lvl,(" 0x%x", mask->mask[i] )); 227 } 228 229 DEBUGADDC( dbg_cl, dbg_lvl, ("\n")); 230} 231 232/*************************************************************************** 233 Retrieve the privilege mask (set) for a given SID 234****************************************************************************/ 235 236static BOOL get_privileges( const DOM_SID *sid, SE_PRIV *mask ) 237{ 238 TDB_CONTEXT *tdb = get_account_pol_tdb(); 239 fstring keystr; 240 TDB_DATA key, data; 241 242 /* Fail if the admin has not enable privileges */ 243 244 if ( !lp_enable_privileges() ) { 245 return False; 246 } 247 248 if ( !tdb ) 249 return False; 250 251 /* PRIV_<SID> (NULL terminated) as the key */ 252 253 fstr_sprintf( keystr, "%s%s", PRIVPREFIX, sid_string_static(sid) ); 254 key.dptr = keystr; 255 key.dsize = strlen(keystr) + 1; 256 257 data = tdb_fetch( tdb, key ); 258 259 if ( !data.dptr ) { 260 DEBUG(3,("get_privileges: No privileges assigned to SID [%s]\n", 261 sid_string_static(sid))); 262 return False; 263 } 264 265 SMB_ASSERT( data.dsize == sizeof( SE_PRIV ) ); 266 267 se_priv_copy( mask, (SE_PRIV*)data.dptr ); 268 SAFE_FREE(data.dptr); 269 270 return True; 271} 272 273/*************************************************************************** 274 Store the privilege mask (set) for a given SID 275****************************************************************************/ 276 277static BOOL set_privileges( const DOM_SID *sid, SE_PRIV *mask ) 278{ 279 TDB_CONTEXT *tdb = get_account_pol_tdb(); 280 fstring keystr; 281 TDB_DATA key, data; 282 283 if ( !lp_enable_privileges() ) 284 return False; 285 286 if ( !tdb ) 287 return False; 288 289 if ( !sid || (sid->num_auths == 0) ) { 290 DEBUG(0,("set_privileges: Refusing to store empty SID!\n")); 291 return False; 292 } 293 294 /* PRIV_<SID> (NULL terminated) as the key */ 295 296 fstr_sprintf( keystr, "%s%s", PRIVPREFIX, sid_string_static(sid) ); 297 key.dptr = keystr; 298 key.dsize = strlen(keystr) + 1; 299 300 /* no packing. static size structure, just write it out */ 301 302 data.dptr = (char*)mask; 303 data.dsize = sizeof(SE_PRIV); 304 305 return ( tdb_store(tdb, key, data, TDB_REPLACE) != -1 ); 306} 307 308/**************************************************************************** 309 check if the privilege is in the privilege list 310****************************************************************************/ 311 312static BOOL is_privilege_assigned( const SE_PRIV *privileges, 313 const SE_PRIV *check ) 314{ 315 SE_PRIV p1, p2; 316 317 if ( !privileges || !check ) 318 return False; 319 320 /* everyone has privileges if you aren't checking for any */ 321 322 if ( se_priv_empty( check ) ) { 323 DEBUG(1,("is_privilege_assigned: no privileges in check_mask!\n")); 324 return True; 325 } 326 327 se_priv_copy( &p1, check ); 328 329 /* invert the SE_PRIV we want to check for and remove that from the 330 original set. If we are left with the SE_PRIV we are checking 331 for then return True */ 332 333 se_priv_invert( &p1, check ); 334 se_priv_copy( &p2, privileges ); 335 se_priv_remove( &p2, &p1 ); 336 337 return se_priv_equal( &p2, check ); 338} 339 340/**************************************************************************** 341 check if the privilege is in the privilege list 342****************************************************************************/ 343 344static BOOL is_any_privilege_assigned( SE_PRIV *privileges, const SE_PRIV *check ) 345{ 346 SE_PRIV p1, p2; 347 348 if ( !privileges || !check ) 349 return False; 350 351 /* everyone has privileges if you aren't checking for any */ 352 353 if ( se_priv_empty( check ) ) { 354 DEBUG(1,("is_any_privilege_assigned: no privileges in check_mask!\n")); 355 return True; 356 } 357 358 se_priv_copy( &p1, check ); 359 360 /* invert the SE_PRIV we want to check for and remove that from the 361 original set. If we are left with the SE_PRIV we are checking 362 for then return True */ 363 364 se_priv_invert( &p1, check ); 365 se_priv_copy( &p2, privileges ); 366 se_priv_remove( &p2, &p1 ); 367 368 /* see if we have any bits left */ 369 370 return !se_priv_empty( &p2 ); 371} 372 373/**************************************************************************** 374 add a privilege to a privilege array 375 ****************************************************************************/ 376 377static BOOL privilege_set_add(PRIVILEGE_SET *priv_set, LUID_ATTR set) 378{ 379 LUID_ATTR *new_set; 380 381 /* we can allocate memory to add the new privilege */ 382 383 new_set = TALLOC_REALLOC_ARRAY(priv_set->mem_ctx, priv_set->set, LUID_ATTR, priv_set->count + 1); 384 if ( !new_set ) { 385 DEBUG(0,("privilege_set_add: failed to allocate memory!\n")); 386 return False; 387 } 388 389 new_set[priv_set->count].luid.high = set.luid.high; 390 new_set[priv_set->count].luid.low = set.luid.low; 391 new_set[priv_set->count].attr = set.attr; 392 393 priv_set->count++; 394 priv_set->set = new_set; 395 396 return True; 397} 398 399/********************************************************************* 400 Generate the LUID_ATTR structure based on a bitmask 401 The assumption here is that the privilege has already been validated 402 so we are guaranteed to find it in the list. 403*********************************************************************/ 404 405LUID_ATTR get_privilege_luid( SE_PRIV *mask ) 406{ 407 LUID_ATTR priv_luid; 408 int i; 409 410 ZERO_STRUCT( priv_luid ); 411 412 for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) { 413 414 if ( se_priv_equal( &privs[i].se_priv, mask ) ) { 415 priv_luid.luid = privs[i].luid; 416 break; 417 } 418 } 419 420 return priv_luid; 421} 422 423/********************************************************************* 424 Generate the LUID_ATTR structure based on a bitmask 425*********************************************************************/ 426 427const char* get_privilege_dispname( const char *name ) 428{ 429 int i; 430 431 for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) { 432 433 if ( strequal( privs[i].name, name ) ) { 434 return privs[i].description; 435 } 436 } 437 438 return NULL; 439} 440 441/********************************************************************* 442 get a list of all privleges for all sids the in list 443*********************************************************************/ 444 445BOOL get_privileges_for_sids(SE_PRIV *privileges, DOM_SID *slist, int scount) 446{ 447 SE_PRIV mask; 448 int i; 449 BOOL found = False; 450 451 se_priv_copy( privileges, &se_priv_none ); 452 453 for ( i=0; i<scount; i++ ) { 454 /* don't add unless we actually have a privilege assigned */ 455 456 if ( !get_privileges( &slist[i], &mask ) ) 457 continue; 458 459 DEBUG(5,("get_privileges_for_sids: sid = %s\nPrivilege set:\n", 460 sid_string_static(&slist[i]))); 461 dump_se_priv( DBGC_ALL, 5, &mask ); 462 463 se_priv_add( privileges, &mask ); 464 found = True; 465 } 466 467 return found; 468} 469 470 471/********************************************************************* 472 travseral functions for privilege_enumerate_accounts 473*********************************************************************/ 474 475static int priv_traverse_fn(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state) 476{ 477 PRIV_SID_LIST *priv = (PRIV_SID_LIST *)state; 478 int prefixlen = strlen(PRIVPREFIX); 479 DOM_SID sid; 480 fstring sid_string; 481 482 /* easy check first */ 483 484 if ( data.dsize != sizeof(SE_PRIV) ) 485 return 0; 486 487 /* check we have a PRIV_+SID entry */ 488 489 if ( strncmp(key.dptr, PRIVPREFIX, prefixlen) != 0) 490 return 0; 491 492 /* check to see if we are looking for a particular privilege */ 493 494 if ( !se_priv_equal(&priv->privilege, &se_priv_none) ) { 495 SE_PRIV mask; 496 497 se_priv_copy( &mask, (SE_PRIV*)data.dptr ); 498 499 /* if the SID does not have the specified privilege 500 then just return */ 501 502 if ( !is_privilege_assigned( &mask, &priv->privilege) ) 503 return 0; 504 } 505 506 fstrcpy( sid_string, &key.dptr[strlen(PRIVPREFIX)] ); 507 508 /* this is a last ditch safety check to preventing returning 509 and invalid SID (i've somehow run into this on development branches) */ 510 511 if ( strcmp( "S-0-0", sid_string ) == 0 ) 512 return 0; 513 514 if ( !string_to_sid(&sid, sid_string) ) { 515 DEBUG(0,("travsersal_fn_enum__acct: Could not convert SID [%s]\n", 516 sid_string)); 517 return 0; 518 } 519 520 if (!add_sid_to_array( NULL, &sid, &priv->sids.list, &priv->sids.count )) { 521 return 0; 522 } 523 524 return 0; 525} 526 527/********************************************************************* 528 Retreive list of privileged SIDs (for _lsa_enumerate_accounts() 529*********************************************************************/ 530 531NTSTATUS privilege_enumerate_accounts(DOM_SID **sids, int *num_sids) 532{ 533 TDB_CONTEXT *tdb = get_account_pol_tdb(); 534 PRIV_SID_LIST priv; 535 536 if (!tdb) { 537 return NT_STATUS_ACCESS_DENIED; 538 } 539 540 ZERO_STRUCT(priv); 541 542 se_priv_copy( &priv.privilege, &se_priv_none ); 543 544 tdb_traverse( tdb, priv_traverse_fn, &priv); 545 546 /* give the memory away; caller will free */ 547 548 *sids = priv.sids.list; 549 *num_sids = priv.sids.count; 550 551 return NT_STATUS_OK; 552} 553 554/*************************************************************************** 555 Add privilege to sid 556****************************************************************************/ 557 558BOOL grant_privilege(const DOM_SID *sid, const SE_PRIV *priv_mask) 559{ 560 SE_PRIV old_mask, new_mask; 561 562 ZERO_STRUCT( old_mask ); 563 ZERO_STRUCT( new_mask ); 564 565 if ( get_privileges( sid, &old_mask ) ) 566 se_priv_copy( &new_mask, &old_mask ); 567 else 568 se_priv_copy( &new_mask, &se_priv_none ); 569 570 se_priv_add( &new_mask, priv_mask ); 571 572 DEBUG(10,("grant_privilege: %s\n", sid_string_static(sid))); 573 574 DEBUGADD( 10, ("original privilege mask:\n")); 575 dump_se_priv( DBGC_ALL, 10, &old_mask ); 576 577 DEBUGADD( 10, ("new privilege mask:\n")); 578 dump_se_priv( DBGC_ALL, 10, &new_mask ); 579 580 return set_privileges( sid, &new_mask ); 581} 582 583/********************************************************************* 584 Add a privilege based on its name 585*********************************************************************/ 586 587BOOL grant_privilege_by_name(DOM_SID *sid, const char *name) 588{ 589 int i; 590 591 for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) { 592 if ( strequal(privs[i].name, name) ) { 593 return grant_privilege( sid, &privs[i].se_priv ); 594 } 595 } 596 597 DEBUG(3, ("grant_privilege_by_name: No Such Privilege Found (%s)\n", name)); 598 599 return False; 600} 601 602/*************************************************************************** 603 Remove privilege from sid 604****************************************************************************/ 605 606BOOL revoke_privilege(const DOM_SID *sid, const SE_PRIV *priv_mask) 607{ 608 SE_PRIV mask; 609 610 /* if the user has no privileges, then we can't revoke any */ 611 612 if ( !get_privileges( sid, &mask ) ) 613 return True; 614 615 DEBUG(10,("revoke_privilege: %s\n", sid_string_static(sid))); 616 617 DEBUGADD( 10, ("original privilege mask:\n")); 618 dump_se_priv( DBGC_ALL, 10, &mask ); 619 620 se_priv_remove( &mask, priv_mask ); 621 622 DEBUGADD( 10, ("new privilege mask:\n")); 623 dump_se_priv( DBGC_ALL, 10, &mask ); 624 625 return set_privileges( sid, &mask ); 626} 627 628/********************************************************************* 629 Revoke all privileges 630*********************************************************************/ 631 632BOOL revoke_all_privileges( DOM_SID *sid ) 633{ 634 return revoke_privilege( sid, &se_priv_all ); 635} 636 637/********************************************************************* 638 Add a privilege based on its name 639*********************************************************************/ 640 641BOOL revoke_privilege_by_name(DOM_SID *sid, const char *name) 642{ 643 int i; 644 645 for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) { 646 if ( strequal(privs[i].name, name) ) { 647 return revoke_privilege( sid, &privs[i].se_priv ); 648 } 649 } 650 651 DEBUG(3, ("revoke_privilege_by_name: No Such Privilege Found (%s)\n", name)); 652 653 return False; 654} 655 656/*************************************************************************** 657 Retrieve the SIDs assigned to a given privilege 658****************************************************************************/ 659 660NTSTATUS privilege_create_account(const DOM_SID *sid ) 661{ 662 return ( grant_privilege(sid, &se_priv_none) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL); 663} 664 665/**************************************************************************** 666 initialise a privilege list and set the talloc context 667 ****************************************************************************/ 668 669NTSTATUS privilege_set_init(PRIVILEGE_SET *priv_set) 670{ 671 TALLOC_CTX *mem_ctx; 672 673 ZERO_STRUCTP( priv_set ); 674 675 mem_ctx = talloc_init("privilege set"); 676 if ( !mem_ctx ) { 677 DEBUG(0,("privilege_set_init: failed to initialize talloc ctx!\n")); 678 return NT_STATUS_NO_MEMORY; 679 } 680 681 priv_set->mem_ctx = mem_ctx; 682 683 return NT_STATUS_OK; 684} 685 686/**************************************************************************** 687 initialise a privilege list and with someone else's talloc context 688****************************************************************************/ 689 690NTSTATUS privilege_set_init_by_ctx(TALLOC_CTX *mem_ctx, PRIVILEGE_SET *priv_set) 691{ 692 ZERO_STRUCTP( priv_set ); 693 694 priv_set->mem_ctx = mem_ctx; 695 priv_set->ext_ctx = True; 696 697 return NT_STATUS_OK; 698} 699 700/**************************************************************************** 701 Free all memory used by a PRIVILEGE_SET 702****************************************************************************/ 703 704void privilege_set_free(PRIVILEGE_SET *priv_set) 705{ 706 if ( !priv_set ) 707 return; 708 709 if ( !( priv_set->ext_ctx ) ) 710 talloc_destroy( priv_set->mem_ctx ); 711 712 ZERO_STRUCTP( priv_set ); 713} 714 715/**************************************************************************** 716 duplicate alloc luid_attr 717 ****************************************************************************/ 718 719NTSTATUS dup_luid_attr(TALLOC_CTX *mem_ctx, LUID_ATTR **new_la, LUID_ATTR *old_la, int count) 720{ 721 int i; 722 723 if ( !old_la ) 724 return NT_STATUS_OK; 725 726 if (count) { 727 *new_la = TALLOC_ARRAY(mem_ctx, LUID_ATTR, count); 728 if ( !*new_la ) { 729 DEBUG(0,("dup_luid_attr: failed to alloc new LUID_ATTR array [%d]\n", count)); 730 return NT_STATUS_NO_MEMORY; 731 } 732 } else { 733 *new_la = NULL; 734 } 735 736 for (i=0; i<count; i++) { 737 (*new_la)[i].luid.high = old_la[i].luid.high; 738 (*new_la)[i].luid.low = old_la[i].luid.low; 739 (*new_la)[i].attr = old_la[i].attr; 740 } 741 742 return NT_STATUS_OK; 743} 744 745/**************************************************************************** 746 Does the user have the specified privilege ? We only deal with one privilege 747 at a time here. 748*****************************************************************************/ 749 750BOOL user_has_privileges(const NT_USER_TOKEN *token, const SE_PRIV *privilege) 751{ 752 if ( !token ) 753 return False; 754 755 return is_privilege_assigned( &token->privileges, privilege ); 756} 757 758/**************************************************************************** 759 Does the user have any of the specified privileges ? We only deal with one privilege 760 at a time here. 761*****************************************************************************/ 762 763BOOL user_has_any_privilege(NT_USER_TOKEN *token, const SE_PRIV *privilege) 764{ 765 if ( !token ) 766 return False; 767 768 return is_any_privilege_assigned( &token->privileges, privilege ); 769} 770 771/**************************************************************************** 772 Convert a LUID to a named string 773****************************************************************************/ 774 775char* luid_to_privilege_name(const LUID *set) 776{ 777 static fstring name; 778 int i; 779 780 if (set->high != 0) 781 return NULL; 782 783 for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) { 784 if ( set->low == privs[i].luid.low ) { 785 fstrcpy( name, privs[i].name ); 786 return name; 787 } 788 } 789 790 return NULL; 791} 792 793/******************************************************************* 794 return the number of elements in the privlege array 795*******************************************************************/ 796 797int count_all_privileges( void ) 798{ 799 static int count; 800 801 if ( count ) 802 return count; 803 804 /* loop over the array and count it */ 805 for ( count=0; !se_priv_equal(&privs[count].se_priv, &se_priv_end); count++ ) ; 806 807 return count; 808} 809 810/******************************************************************* 811*******************************************************************/ 812 813BOOL se_priv_to_privilege_set( PRIVILEGE_SET *set, SE_PRIV *mask ) 814{ 815 int i; 816 uint32 num_privs = count_all_privileges(); 817 LUID_ATTR luid; 818 819 luid.attr = 0; 820 luid.luid.high = 0; 821 822 for ( i=0; i<num_privs; i++ ) { 823 if ( !is_privilege_assigned(mask, &privs[i].se_priv) ) 824 continue; 825 826 luid.luid = privs[i].luid; 827 828 if ( !privilege_set_add( set, luid ) ) 829 return False; 830 } 831 832 return True; 833} 834 835/******************************************************************* 836*******************************************************************/ 837 838static BOOL luid_to_se_priv( LUID *luid, SE_PRIV *mask ) 839{ 840 int i; 841 uint32 num_privs = count_all_privileges(); 842 843 for ( i=0; i<num_privs; i++ ) { 844 if ( luid->low == privs[i].luid.low ) { 845 se_priv_copy( mask, &privs[i].se_priv ); 846 return True; 847 } 848 } 849 850 return False; 851} 852 853/******************************************************************* 854*******************************************************************/ 855 856BOOL privilege_set_to_se_priv( SE_PRIV *mask, PRIVILEGE_SET *privset ) 857{ 858 int i; 859 860 ZERO_STRUCTP( mask ); 861 862 for ( i=0; i<privset->count; i++ ) { 863 SE_PRIV r; 864 865 /* sanity check for invalid privilege. we really 866 only care about the low 32 bits */ 867 868 if ( privset->set[i].luid.high != 0 ) 869 return False; 870 871 if ( luid_to_se_priv( &privset->set[i].luid, &r ) ) 872 se_priv_add( mask, &r ); 873 } 874 875 return True; 876} 877 878/******************************************************************* 879*******************************************************************/ 880 881BOOL is_privileged_sid( const DOM_SID *sid ) 882{ 883 SE_PRIV mask; 884 885 return get_privileges( sid, &mask ); 886} 887 888/******************************************************************* 889*******************************************************************/ 890 891BOOL grant_all_privileges( const DOM_SID *sid ) 892{ 893 int i; 894 SE_PRIV mask; 895 uint32 num_privs = count_all_privileges(); 896 897 se_priv_copy( &mask, &se_priv_none ); 898 899 for ( i=0; i<num_privs; i++ ) { 900 se_priv_add(&mask, &privs[i].se_priv); 901 } 902 903 return grant_privilege( sid, &mask ); 904} 905