r6303: Setting up for 3.0.15pre1
[Samba.git] / source / lib / privileges.c
blobe01561de06f4d2dea1dc96da2be2bfd0e8bfd556
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
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.
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.
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.
24 #include "includes.h"
26 #define PRIVPREFIX "PRIV_"
28 #define GENERATE_LUID_LOW(x) (x)+1;
30 static const SE_PRIV se_priv_all = SE_ALL_PRIVS;
31 static const SE_PRIV se_priv_end = SE_END;
33 /* Define variables for all privileges so we can use the
34 SE_PRIV* in the various se_priv_XXX() functions */
36 const SE_PRIV se_priv_none = SE_NONE;
37 const SE_PRIV se_machine_account = SE_MACHINE_ACCOUNT;
38 const SE_PRIV se_print_operator = SE_PRINT_OPERATOR;
39 const SE_PRIV se_add_users = SE_ADD_USERS;
40 const SE_PRIV se_disk_operators = SE_DISK_OPERATOR;
41 const SE_PRIV se_remote_shutdown = SE_REMOTE_SHUTDOWN;
43 /********************************************************************
44 This is a list of privileges reported by a WIndows 2000 SP4 AD DC
45 just for reference purposes:
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
77 ********************************************************************/
80 PRIVS 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 */
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"},
95 {SE_END, "", ""}
98 typedef struct {
99 int count;
100 DOM_SID *list;
101 } SID_LIST;
103 typedef struct {
104 SE_PRIV privilege;
105 SID_LIST sids;
106 } PRIV_SID_LIST;
109 /***************************************************************************
110 copy an SE_PRIV structure
111 ****************************************************************************/
113 BOOL se_priv_copy( SE_PRIV *dst, const SE_PRIV *src )
115 if ( !dst || !src )
116 return False;
118 memcpy( dst, src, sizeof(SE_PRIV) );
120 return True;
123 /***************************************************************************
124 combine 2 SE_PRIV structures and store the resulting set in mew_mask
125 ****************************************************************************/
127 void se_priv_add( SE_PRIV *mask, const SE_PRIV *addpriv )
129 int i;
131 for ( i=0; i<SE_PRIV_MASKSIZE; i++ ) {
132 mask->mask[i] |= addpriv->mask[i];
136 /***************************************************************************
137 remove one SE_PRIV sytucture from another and store the resulting set
138 in mew_mask
139 ****************************************************************************/
141 void se_priv_remove( SE_PRIV *mask, const SE_PRIV *removepriv )
143 int i;
145 for ( i=0; i<SE_PRIV_MASKSIZE; i++ ) {
146 mask->mask[i] &= ~removepriv->mask[i];
150 /***************************************************************************
151 invert a given SE_PRIV and store the set in new_mask
152 ****************************************************************************/
154 static void se_priv_invert( SE_PRIV *new_mask, const SE_PRIV *mask )
156 SE_PRIV allprivs;
158 se_priv_copy( &allprivs, &se_priv_all );
159 se_priv_remove( &allprivs, mask );
160 se_priv_copy( new_mask, &allprivs );
163 /***************************************************************************
164 check if 2 SE_PRIV structure are equal
165 ****************************************************************************/
167 static BOOL se_priv_equal( const SE_PRIV *mask1, const SE_PRIV *mask2 )
169 return ( memcmp(mask1, mask2, sizeof(SE_PRIV)) == 0 );
172 /***************************************************************************
173 check if a SE_PRIV has any assigned privileges
174 ****************************************************************************/
176 static BOOL se_priv_empty( const SE_PRIV *mask )
178 SE_PRIV p1;
179 int i;
181 se_priv_copy( &p1, mask );
183 for ( i=0; i<SE_PRIV_MASKSIZE; i++ ) {
184 p1.mask[i] &= se_priv_all.mask[i];
187 return se_priv_equal( &p1, &se_priv_none );
190 /*********************************************************************
191 Lookup the SE_PRIV value for a privilege name
192 *********************************************************************/
194 BOOL se_priv_from_name( const char *name, SE_PRIV *mask )
196 int i;
198 for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) {
199 if ( strequal( privs[i].name, name ) ) {
200 se_priv_copy( mask, &privs[i].se_priv );
201 return True;
205 return False;
208 /***************************************************************************
209 dump an SE_PRIV structure to the log files
210 ****************************************************************************/
212 void dump_se_priv( int dbg_cl, int dbg_lvl, const SE_PRIV *mask )
214 int i;
216 DEBUGADDC( dbg_cl, dbg_lvl,("SE_PRIV "));
218 for ( i=0; i<SE_PRIV_MASKSIZE; i++ ) {
219 DEBUGADDC( dbg_cl, dbg_lvl,(" 0x%x", mask->mask[i] ));
222 DEBUGADDC( dbg_cl, dbg_lvl, ("\n"));
225 /***************************************************************************
226 Retrieve the privilege mask (set) for a given SID
227 ****************************************************************************/
229 static BOOL get_privileges( const DOM_SID *sid, SE_PRIV *mask )
231 TDB_CONTEXT *tdb = get_account_pol_tdb();
232 fstring keystr;
233 TDB_DATA key, data;
235 /* Fail if the admin has not enable privileges */
237 if ( !lp_enable_privileges() ) {
238 return False;
241 if ( !tdb )
242 return False;
244 /* PRIV_<SID> (NULL terminated) as the key */
246 fstr_sprintf( keystr, "%s%s", PRIVPREFIX, sid_string_static(sid) );
247 key.dptr = keystr;
248 key.dsize = strlen(keystr) + 1;
250 data = tdb_fetch( tdb, key );
252 if ( !data.dptr ) {
253 DEBUG(3,("get_privileges: No privileges assigned to SID [%s]\n",
254 sid_string_static(sid)));
255 return False;
258 SMB_ASSERT( data.dsize == sizeof( SE_PRIV ) );
260 se_priv_copy( mask, (SE_PRIV*)data.dptr );
261 SAFE_FREE(data.dptr);
263 return True;
266 /***************************************************************************
267 Store the privilege mask (set) for a given SID
268 ****************************************************************************/
270 static BOOL set_privileges( const DOM_SID *sid, SE_PRIV *mask )
272 TDB_CONTEXT *tdb = get_account_pol_tdb();
273 fstring keystr;
274 TDB_DATA key, data;
276 if ( !lp_enable_privileges() )
277 return False;
279 if ( !tdb )
280 return False;
282 /* PRIV_<SID> (NULL terminated) as the key */
284 fstr_sprintf( keystr, "%s%s", PRIVPREFIX, sid_string_static(sid) );
285 key.dptr = keystr;
286 key.dsize = strlen(keystr) + 1;
288 /* no packing. static size structure, just write it out */
290 data.dptr = (char*)mask;
291 data.dsize = sizeof(SE_PRIV);
293 return ( tdb_store(tdb, key, data, TDB_REPLACE) != -1 );
296 /****************************************************************************
297 check if the privilege is in the privilege list
298 ****************************************************************************/
300 static BOOL is_privilege_assigned( SE_PRIV *privileges, const SE_PRIV *check )
302 SE_PRIV p1, p2;
304 if ( !privileges || !check )
305 return False;
307 /* everyone has privileges if you aren't checking for any */
309 if ( se_priv_empty( check ) ) {
310 DEBUG(1,("is_privilege_assigned: no privileges in check_mask!\n"));
311 return True;
314 se_priv_copy( &p1, check );
316 /* invert the SE_PRIV we want to check for and remove that from the
317 original set. If we are left with the SE_PRIV we are checking
318 for then return True */
320 se_priv_invert( &p1, check );
321 se_priv_copy( &p2, privileges );
322 se_priv_remove( &p2, &p1 );
324 return se_priv_equal( &p2, check );
327 /****************************************************************************
328 check if the privilege is in the privilege list
329 ****************************************************************************/
331 static BOOL is_any_privilege_assigned( SE_PRIV *privileges, const SE_PRIV *check )
333 SE_PRIV p1, p2;
335 if ( !privileges || !check )
336 return False;
338 /* everyone has privileges if you aren't checking for any */
340 if ( se_priv_empty( check ) ) {
341 DEBUG(1,("is_any_privilege_assigned: no privileges in check_mask!\n"));
342 return True;
345 se_priv_copy( &p1, check );
347 /* invert the SE_PRIV we want to check for and remove that from the
348 original set. If we are left with the SE_PRIV we are checking
349 for then return True */
351 se_priv_invert( &p1, check );
352 se_priv_copy( &p2, privileges );
353 se_priv_remove( &p2, &p1 );
355 /* see if we have any bits left */
357 return !se_priv_empty( &p2 );
360 /****************************************************************************
361 add a privilege to a privilege array
362 ****************************************************************************/
364 static BOOL privilege_set_add(PRIVILEGE_SET *priv_set, LUID_ATTR set)
366 LUID_ATTR *new_set;
368 /* we can allocate memory to add the new privilege */
370 new_set = TALLOC_REALLOC_ARRAY(priv_set->mem_ctx, priv_set->set, LUID_ATTR, priv_set->count + 1);
371 if ( !new_set ) {
372 DEBUG(0,("privilege_set_add: failed to allocate memory!\n"));
373 return False;
376 new_set[priv_set->count].luid.high = set.luid.high;
377 new_set[priv_set->count].luid.low = set.luid.low;
378 new_set[priv_set->count].attr = set.attr;
380 priv_set->count++;
381 priv_set->set = new_set;
383 return True;
386 /*********************************************************************
387 Generate the LUID_ATTR structure based on a bitmask
388 *********************************************************************/
390 LUID_ATTR get_privilege_luid( SE_PRIV *mask )
392 LUID_ATTR priv_luid;
393 int i;
395 priv_luid.attr = 0;
396 priv_luid.luid.high = 0;
398 for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) {
400 if ( se_priv_equal( &privs[i].se_priv, mask ) ) {
401 priv_luid.luid.low = GENERATE_LUID_LOW(i);
402 break;
406 return priv_luid;
409 /*********************************************************************
410 Generate the LUID_ATTR structure based on a bitmask
411 *********************************************************************/
413 const char* get_privilege_dispname( const char *name )
415 int i;
417 for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) {
419 if ( strequal( privs[i].name, name ) ) {
420 return privs[i].description;
424 return NULL;
427 /*********************************************************************
428 get a list of all privleges for all sids the in list
429 *********************************************************************/
431 BOOL get_privileges_for_sids(SE_PRIV *privileges, DOM_SID *slist, int scount)
433 SE_PRIV mask;
434 int i;
435 BOOL found = False;
437 se_priv_copy( privileges, &se_priv_none );
439 for ( i=0; i<scount; i++ ) {
440 /* don't add unless we actually have a privilege assigned */
442 if ( !get_privileges( &slist[i], &mask ) )
443 continue;
445 DEBUG(5,("get_privileges_for_sids: sid = %s\nPrivilege set:\n",
446 sid_string_static(&slist[i])));
447 dump_se_priv( DBGC_ALL, 5, &mask );
449 se_priv_add( privileges, &mask );
450 found = True;
453 return found;
457 /*********************************************************************
458 travseral functions for privilege_enumerate_accounts
459 *********************************************************************/
461 static int priv_traverse_fn(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
463 PRIV_SID_LIST *priv = state;
464 int prefixlen = strlen(PRIVPREFIX);
465 DOM_SID sid;
466 fstring sid_string;
468 /* easy check first */
470 if ( data.dsize != sizeof(SE_PRIV) )
471 return 0;
473 /* check we have a PRIV_+SID entry */
475 if ( strncmp(key.dptr, PRIVPREFIX, prefixlen) != 0)
476 return 0;
478 /* check to see if we are looking for a particular privilege */
480 if ( !se_priv_equal(&priv->privilege, &se_priv_none) ) {
481 SE_PRIV mask;
483 se_priv_copy( &mask, (SE_PRIV*)data.dptr );
485 /* if the SID does not have the specified privilege
486 then just return */
488 if ( !is_privilege_assigned( &mask, &priv->privilege) )
489 return 0;
492 fstrcpy( sid_string, &key.dptr[strlen(PRIVPREFIX)] );
494 if ( !string_to_sid(&sid, sid_string) ) {
495 DEBUG(0,("travsersal_fn_enum__acct: Could not convert SID [%s]\n",
496 sid_string));
497 return 0;
500 add_sid_to_array( NULL, &sid, &priv->sids.list, &priv->sids.count );
502 return 0;
505 /*********************************************************************
506 Retreive list of privileged SIDs (for _lsa_enumerate_accounts()
507 *********************************************************************/
509 NTSTATUS privilege_enumerate_accounts(DOM_SID **sids, int *num_sids)
511 TDB_CONTEXT *tdb = get_account_pol_tdb();
512 PRIV_SID_LIST priv;
514 ZERO_STRUCT(priv);
516 se_priv_copy( &priv.privilege, &se_priv_none );
518 tdb_traverse( tdb, priv_traverse_fn, &priv);
520 /* give the memory away; caller will free */
522 *sids = priv.sids.list;
523 *num_sids = priv.sids.count;
525 return NT_STATUS_OK;
528 /***************************************************************************
529 Add privilege to sid
530 ****************************************************************************/
532 BOOL grant_privilege(const DOM_SID *sid, const SE_PRIV *priv_mask)
534 SE_PRIV old_mask, new_mask;
536 if ( get_privileges( sid, &old_mask ) )
537 se_priv_copy( &new_mask, &old_mask );
538 else
539 se_priv_copy( &new_mask, &se_priv_none );
541 se_priv_add( &new_mask, priv_mask );
543 DEBUG(10,("grant_privilege: %s\n", sid_string_static(sid)));
545 DEBUGADD( 10, ("original privilege mask:\n"));
546 dump_se_priv( DBGC_ALL, 10, &old_mask );
548 DEBUGADD( 10, ("new privilege mask:\n"));
549 dump_se_priv( DBGC_ALL, 10, &new_mask );
551 return set_privileges( sid, &new_mask );
554 /*********************************************************************
555 Add a privilege based on its name
556 *********************************************************************/
558 BOOL grant_privilege_by_name(DOM_SID *sid, const char *name)
560 int i;
562 for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) {
563 if ( strequal(privs[i].name, name) ) {
564 return grant_privilege( sid, &privs[i].se_priv );
568 DEBUG(3, ("grant_privilege_by_name: No Such Privilege Found (%s)\n", name));
570 return False;
573 /***************************************************************************
574 Remove privilege from sid
575 ****************************************************************************/
577 BOOL revoke_privilege(const DOM_SID *sid, const SE_PRIV *priv_mask)
579 SE_PRIV mask;
581 /* if the user has no privileges, then we can't revoke any */
583 if ( !get_privileges( sid, &mask ) )
584 return True;
586 DEBUG(10,("revoke_privilege: %s\n", sid_string_static(sid)));
588 DEBUGADD( 10, ("original privilege mask:\n"));
589 dump_se_priv( DBGC_ALL, 10, &mask );
591 se_priv_remove( &mask, priv_mask );
593 DEBUGADD( 10, ("new privilege mask:\n"));
594 dump_se_priv( DBGC_ALL, 10, &mask );
596 return set_privileges( sid, &mask );
599 /*********************************************************************
600 Revoke all privileges
601 *********************************************************************/
603 BOOL revoke_all_privileges( DOM_SID *sid )
605 return revoke_privilege( sid, &se_priv_all );
608 /*********************************************************************
609 Add a privilege based on its name
610 *********************************************************************/
612 BOOL revoke_privilege_by_name(DOM_SID *sid, const char *name)
614 int i;
616 for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) {
617 if ( strequal(privs[i].name, name) ) {
618 return revoke_privilege( sid, &privs[i].se_priv );
622 DEBUG(3, ("revoke_privilege_by_name: No Such Privilege Found (%s)\n", name));
624 return False;
627 /***************************************************************************
628 Retrieve the SIDs assigned to a given privilege
629 ****************************************************************************/
631 NTSTATUS privilege_create_account(const DOM_SID *sid )
633 return ( grant_privilege(sid, &se_priv_none) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL);
636 /****************************************************************************
637 initialise a privilege list and set the talloc context
638 ****************************************************************************/
639 NTSTATUS privilege_set_init(PRIVILEGE_SET *priv_set)
641 TALLOC_CTX *mem_ctx;
643 ZERO_STRUCTP( priv_set );
645 mem_ctx = talloc_init("privilege set");
646 if ( !mem_ctx ) {
647 DEBUG(0,("privilege_set_init: failed to initialize talloc ctx!\n"));
648 return NT_STATUS_NO_MEMORY;
651 priv_set->mem_ctx = mem_ctx;
653 return NT_STATUS_OK;
656 /****************************************************************************
657 initialise a privilege list and with someone else's talloc context
658 ****************************************************************************/
660 NTSTATUS privilege_set_init_by_ctx(TALLOC_CTX *mem_ctx, PRIVILEGE_SET *priv_set)
662 ZERO_STRUCTP( priv_set );
664 priv_set->mem_ctx = mem_ctx;
665 priv_set->ext_ctx = True;
667 return NT_STATUS_OK;
670 /****************************************************************************
671 Free all memory used by a PRIVILEGE_SET
672 ****************************************************************************/
674 void privilege_set_free(PRIVILEGE_SET *priv_set)
676 if ( !priv_set )
677 return;
679 if ( !( priv_set->ext_ctx ) )
680 talloc_destroy( priv_set->mem_ctx );
682 ZERO_STRUCTP( priv_set );
685 /****************************************************************************
686 duplicate alloc luid_attr
687 ****************************************************************************/
689 NTSTATUS dup_luid_attr(TALLOC_CTX *mem_ctx, LUID_ATTR **new_la, LUID_ATTR *old_la, int count)
691 int i;
693 if ( !old_la )
694 return NT_STATUS_OK;
696 *new_la = TALLOC_ARRAY(mem_ctx, LUID_ATTR, count);
697 if ( !*new_la ) {
698 DEBUG(0,("dup_luid_attr: failed to alloc new LUID_ATTR array [%d]\n", count));
699 return NT_STATUS_NO_MEMORY;
702 for (i=0; i<count; i++) {
703 (*new_la)[i].luid.high = old_la[i].luid.high;
704 (*new_la)[i].luid.low = old_la[i].luid.low;
705 (*new_la)[i].attr = old_la[i].attr;
708 return NT_STATUS_OK;
711 /****************************************************************************
712 Does the user have the specified privilege ? We only deal with one privilege
713 at a time here.
714 *****************************************************************************/
716 BOOL user_has_privileges(NT_USER_TOKEN *token, const SE_PRIV *privilege)
718 if ( !token )
719 return False;
721 return is_privilege_assigned( &token->privileges, privilege );
724 /****************************************************************************
725 Does the user have any of the specified privileges ? We only deal with one privilege
726 at a time here.
727 *****************************************************************************/
729 BOOL user_has_any_privilege(NT_USER_TOKEN *token, const SE_PRIV *privilege)
731 if ( !token )
732 return False;
734 return is_any_privilege_assigned( &token->privileges, privilege );
737 /****************************************************************************
738 Convert a LUID to a named string
739 ****************************************************************************/
741 char* luid_to_privilege_name(const LUID *set)
743 static fstring name;
744 int max = count_all_privileges();
746 if (set->high != 0)
747 return NULL;
749 if ( set->low > max )
750 return NULL;
752 fstrcpy( name, privs[set->low - 1].name );
754 return name;
757 /*******************************************************************
758 return the number of elements in the privlege array
759 *******************************************************************/
761 int count_all_privileges( void )
763 static int count;
765 if ( count )
766 return count;
768 /* loop over the array and count it */
769 for ( count=0; !se_priv_equal(&privs[count].se_priv, &se_priv_end); count++ ) ;
771 return count;
774 /*******************************************************************
775 *******************************************************************/
777 BOOL se_priv_to_privilege_set( PRIVILEGE_SET *set, SE_PRIV *mask )
779 int i;
780 uint32 num_privs = count_all_privileges();
781 LUID_ATTR luid;
783 luid.attr = 0;
784 luid.luid.high = 0;
786 for ( i=0; i<num_privs; i++ ) {
787 if ( !is_privilege_assigned(mask, &privs[i].se_priv) )
788 continue;
790 luid.luid.low = GENERATE_LUID_LOW(i);
792 if ( !privilege_set_add( set, luid ) )
793 return False;
796 return True;
799 /*******************************************************************
800 *******************************************************************/
802 BOOL privilege_set_to_se_priv( SE_PRIV *mask, PRIVILEGE_SET *privset )
804 int i;
805 uint32 num_privs = count_all_privileges();
807 ZERO_STRUCTP( mask );
809 for ( i=0; i<privset->count; i++ ) {
810 SE_PRIV r;
812 /* sanity check for invalid privilege. we really
813 only care about the low 32 bits */
815 if ( privset->set[i].luid.high != 0 )
816 return False;
818 /* make sure :LUID.low is in range */
819 if ( privset->set[i].luid.low == 0 || privset->set[i].luid.low > num_privs )
820 return False;
822 r = privs[privset->set[i].luid.low - 1].se_priv;
823 se_priv_add( mask, &r );
826 return True;
829 /*******************************************************************
830 *******************************************************************/
832 BOOL is_privileged_sid( DOM_SID *sid )
834 SE_PRIV mask;
836 return get_privileges( sid, &mask );