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