From: Gerald Carter Date: Mon, 17 Jan 2005 15:23:11 +0000 (+0000) Subject: r4805: Last planned change to the privileges infrastructure: X-Git-Tag: samba-4.0.0alpha6~801^2~10835 X-Git-Url: http://git.samba.org/?p=samba.git;a=commitdiff_plain;h=46e5effea948931509283cb84b27007d34b521c8 r4805: Last planned change to the privileges infrastructure: * rewrote the tdb layout of privilege records in account_pol.tdb (allow for 128 bits instead of 32 bit flags) * migrated to using SE_PRIV structure instead of the PRIVILEGE_SET structure. The latter is now used for parsing routines mainly. Still need to incorporate some client support into 'net' so for setting privileges. And make use of the SeAddUserPrivilege right. (This used to be commit 41dc7f7573c6d637e19a01e7ed0e716ac0f1fb15) --- diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index e4793c3df39..4a23ec8adc5 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -494,10 +494,7 @@ void debug_nt_user_token(int dbg_class, int dbg_lev, NT_USER_TOKEN *token) DEBUGADDC(dbg_class, dbg_lev, ("SID[%3lu]: %s\n", (unsigned long)i, sid_to_string(sid_str, &token->user_sids[i]))); - DEBUGADDC(dbg_class, dbg_lev, ("Privileges: [%d]\n", token->privileges.count)); - for ( i=0; iprivileges.count; i++ ) { - DEBUGADDC(dbg_class, dbg_lev, ("\t%s\n", luid_to_privilege_name(&token->privileges.set[i].luid) )); - } + dump_se_priv( dbg_class, dbg_lev, &token->privileges ); } /**************************************************************************** @@ -591,10 +588,7 @@ static NTSTATUS create_nt_user_token(const DOM_SID *user_sid, const DOM_SID *gro /* add privileges assigned to this user */ - privilege_set_init( &ptoken->privileges ); - get_privileges_for_sids( &ptoken->privileges, ptoken->user_sids, ptoken->num_sids ); - debug_nt_user_token(DBGC_AUTH, 10, ptoken); @@ -1426,8 +1420,6 @@ void delete_nt_token(NT_USER_TOKEN **pptoken) NT_USER_TOKEN *ptoken = *pptoken; SAFE_FREE( ptoken->user_sids ); - privilege_set_free( &ptoken->privileges ); - ZERO_STRUCTP(ptoken); } SAFE_FREE(*pptoken); @@ -1460,9 +1452,8 @@ NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken) /* copy the privileges; don't consider failure to be critical here */ - privilege_set_init( &token->privileges); - if ( !dup_privilege_set( &token->privileges, &ptoken->privileges ) ) { - DEBUG(0,("dup_nt_token: Failure to copy PRIVILEGE_SET!. Continuing with 0 privileges assigned.\n")); + if ( !se_priv_copy( &token->privileges, &ptoken->privileges ) ) { + DEBUG(0,("dup_nt_token: Failure to copy SE_PRIV!. Continuing with 0 privileges assigned.\n")); } return token; diff --git a/source3/include/privileges.h b/source3/include/privileges.h index cdf62b7f858..b4972c7a602 100644 --- a/source3/include/privileges.h +++ b/source3/include/privileges.h @@ -27,24 +27,24 @@ /* common privilege defines */ -#define SE_END 0x00000000 -#define SE_NONE 0x00000000 -#define SE_ALL_PRIVS 0xFFFFFFFF +#define SE_END { { 0x00000000, 0x00000000, 0x00000000, 0x00000000 } } +#define SE_NONE { { 0x00000000, 0x00000000, 0x00000000, 0x00000000 } } +#define SE_ALL_PRIVS { { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF } } /* * We will use our own set of privileges since it makes no sense * to implement all of the Windows set when only a portion will - * be used. + * be used. Use 128-bit mask to give room to grow. */ -#define SE_NETWORK_LOGON 0x00000001 -#define SE_INTERACTIVE_LOGON 0x00000002 -#define SE_BATCH_LOGON 0x00000004 -#define SE_SERVICE_LOGON 0x00000008 -#define SE_MACHINE_ACCOUNT 0x00000010 -#define SE_PRINT_OPERATOR 0x00000020 -#define SE_ADD_USERS 0x00000040 +#define SE_NETWORK_LOGON { { 0x00000001, 0x00000000, 0x00000000, 0x00000000 } } +#define SE_INTERACTIVE_LOGON { { 0x00000002, 0x00000000, 0x00000000, 0x00000000 } } +#define SE_BATCH_LOGON { { 0x00000004, 0x00000000, 0x00000000, 0x00000000 } } +#define SE_SERVICE_LOGON { { 0x00000008, 0x00000000, 0x00000000, 0x00000000 } } +#define SE_MACHINE_ACCOUNT { { 0x00000010, 0x00000000, 0x00000000, 0x00000000 } } +#define SE_PRINT_OPERATOR { { 0x00000020, 0x00000000, 0x00000000, 0x00000000 } } +#define SE_ADD_USERS { { 0x00000040, 0x00000000, 0x00000000, 0x00000000 } } #if 0 /* not needed currently */ @@ -113,8 +113,14 @@ typedef struct privilege_set LUID_ATTR *set; } PRIVILEGE_SET; +#define SE_PRIV_MASKSIZE 4 + +typedef struct { + uint32 mask[SE_PRIV_MASKSIZE]; +} SE_PRIV; + typedef struct _PRIVS { - uint32 se_priv; + SE_PRIV se_priv; const char *name; const char *description; } PRIVS; diff --git a/source3/include/smb.h b/source3/include/smb.h index 1cf5aac0c50..913061014db 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -302,7 +302,7 @@ typedef struct sid_list { typedef struct _nt_user_token { size_t num_sids; DOM_SID *user_sids; - PRIVILEGE_SET privileges; + SE_PRIV privileges; } NT_USER_TOKEN; /*** query a local group, get a list of these: shows who is in that group ***/ diff --git a/source3/lib/privileges.c b/source3/lib/privileges.c index 09a868fc277..973e9acc65f 100644 --- a/source3/lib/privileges.c +++ b/source3/lib/privileges.c @@ -25,6 +25,13 @@ #define PRIVPREFIX "PRIV_" +#define GENERATE_LUID_LOW(x) (x)+1; + +static SE_PRIV se_priv_all = SE_ALL_PRIVS; +static SE_PRIV se_priv_end = SE_END; +static SE_PRIV se_priv_none = SE_NONE; + + #define ALLOC_CHECK(ptr, err, label, str) do { if ((ptr) == NULL) \ { DEBUG(0, ("%s: out of memory!\n", str)); err = NT_STATUS_NO_MEMORY; goto label; } } while(0) @@ -79,32 +86,123 @@ PRIVS privs[] = { #endif typedef struct priv_sid_list { - uint32 se_priv; + SE_PRIV privilege; SID_LIST sids; } PRIV_SID_LIST; + +/*************************************************************************** + copy an SE_PRIV structure +****************************************************************************/ + +BOOL se_priv_copy( SE_PRIV *dst, SE_PRIV *src ) +{ + if ( !dst || !src ) + return False; + + memcpy( dst, src, sizeof(SE_PRIV) ); + + return True; +} + +/*************************************************************************** + combine 2 SE_PRIV structures and store the resulting set in mew_mask +****************************************************************************/ + +static void se_priv_add( SE_PRIV *mask, SE_PRIV *addpriv ) +{ + int i; + + for ( i=0; imask[i] |= addpriv->mask[i]; + } +} + +/*************************************************************************** + remove one SE_PRIV sytucture from another and store the resulting set + in mew_mask +****************************************************************************/ + +static void se_priv_remove( SE_PRIV *mask, SE_PRIV *removepriv ) +{ + int i; + + for ( i=0; imask[i] &= ~removepriv->mask[i]; + } +} + +/*************************************************************************** + invert a given SE_PRIV and store the set in new_mask +****************************************************************************/ + +static void se_priv_invert( SE_PRIV *new_mask, SE_PRIV *mask ) +{ + SE_PRIV allprivs; + + se_priv_copy( &allprivs, &se_priv_all ); + se_priv_remove( &allprivs, mask ); + se_priv_copy( new_mask, &allprivs ); +} + +/*************************************************************************** + check if 2 SE_PRIV structure are equal +****************************************************************************/ + +static BOOL se_priv_equal( SE_PRIV *mask1, SE_PRIV *mask2 ) +{ + return ( memcmp(mask1, mask2, sizeof(SE_PRIV)) == 0 ); +} + + +/*************************************************************************** + dump an SE_PRIV structure to the log files +****************************************************************************/ + +void dump_se_priv( int dbg_cl, int dbg_lvl, SE_PRIV *mask ) +{ + int i; + + DEBUGADDC( dbg_cl, dbg_lvl,("SE_PRIV ")); + + for ( i=0; imask[i] )); + } + + DEBUGADDC( dbg_cl, dbg_lvl, ("\n")); +} + /*************************************************************************** Retrieve the privilege mask (set) for a given SID ****************************************************************************/ -static uint32 get_privileges( const DOM_SID *sid, uint32 *mask ) +static BOOL get_privileges( const DOM_SID *sid, SE_PRIV *mask ) { TDB_CONTEXT *tdb = get_account_pol_tdb(); fstring keystr; - uint32 priv_mask; + TDB_DATA key, data; if ( !tdb ) return False; + /* PRIV_ (NULL terminated) as the key */ + fstr_sprintf( keystr, "%s%s", PRIVPREFIX, sid_string_static(sid) ); + key.dptr = keystr; + key.dsize = strlen(keystr) + 1; - if ( !tdb_fetch_uint32( tdb, keystr, &priv_mask ) ) { + data = tdb_fetch( tdb, key ); + + if ( !data.dptr ) { DEBUG(3,("get_privileges: No privileges assigned to SID [%s]\n", sid_string_static(sid))); return False; } - *mask = priv_mask; + SMB_ASSERT( data.dsize == sizeof( SE_PRIV ) ); + + se_priv_copy( mask, (SE_PRIV*)data.dptr ); + return True; } @@ -112,66 +210,68 @@ static uint32 get_privileges( const DOM_SID *sid, uint32 *mask ) Store the privilege mask (set) for a given SID ****************************************************************************/ -static BOOL set_privileges( const DOM_SID *sid, uint32 mask ) +static BOOL set_privileges( const DOM_SID *sid, SE_PRIV *mask ) { TDB_CONTEXT *tdb = get_account_pol_tdb(); fstring keystr; + TDB_DATA key, data; if ( !tdb ) return False; + /* PRIV_ (NULL terminated) as the key */ + fstr_sprintf( keystr, "%s%s", PRIVPREFIX, sid_string_static(sid) ); + key.dptr = keystr; + key.dsize = strlen(keystr) + 1; + + /* no packing. static size structure, just write it out */ + + data.dptr = (char*)mask; + data.dsize = sizeof(SE_PRIV); - return tdb_store_uint32( tdb, keystr, mask ); + return ( tdb_store(tdb, key, data, TDB_REPLACE) != -1 ); } /**************************************************************************** check if the privilege is in the privilege list ****************************************************************************/ -static BOOL check_priv_in_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) +static BOOL is_privilege_assigned( SE_PRIV *privileges, SE_PRIV *check ) { - int i; + SE_PRIV p1, p2; - if ( !priv_set ) + if ( !privileges || !check ) return False; - - for ( i = 0; i < priv_set->count; i++ ) { - LUID_ATTR *cur_set; - - cur_set = &priv_set->set[i]; - - /* check only the low and high part. Checking the attr - field has no meaning */ - - if ( (cur_set->luid.low == set.luid.low) - && (cur_set->luid.high == set.luid.high) ) - { - return True; - } - } - - return False; + + se_priv_copy( &p1, check ); + + /* invert the SE_PRIV we want to check for and remove that from the + original set. If we are left with the SE_PRIV we are checking + for then return True */ + + se_priv_invert( &p1, check ); + se_priv_copy( &p2, privileges ); + se_priv_remove( &p2, &p1 ); + + return se_priv_equal( &p2, check ); } /**************************************************************************** add a privilege to a privilege array ****************************************************************************/ -static NTSTATUS add_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) +static BOOL privilege_set_add(PRIVILEGE_SET *priv_set, LUID_ATTR set) { - NTSTATUS ret; LUID_ATTR *new_set; - /* check if the privilege is not already in the list */ - - if ( check_priv_in_privilege(priv_set, set) ) - return NT_STATUS_OK; - /* we can allocate memory to add the new privilege */ new_set = TALLOC_REALLOC_ARRAY(priv_set->mem_ctx, priv_set->set, LUID_ATTR, priv_set->count + 1); - ALLOC_CHECK(new_set, ret, done, "add_privilege"); + if ( !new_set ) { + DEBUG(0,("privilege_set_add: failed to allocate memory!\n")); + return False; + } new_set[priv_set->count].luid.high = set.luid.high; new_set[priv_set->count].luid.low = set.luid.low; @@ -180,78 +280,79 @@ static NTSTATUS add_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) priv_set->count++; priv_set->set = new_set; - ret = NT_STATUS_OK; - -done: - return ret; + return True; } /********************************************************************* Generate the LUID_ATTR structure based on a bitmask *********************************************************************/ -static LUID_ATTR get_privilege_luid( uint32 mask ) +LUID_ATTR get_privilege_luid( SE_PRIV *mask ) { LUID_ATTR priv_luid; + int i; priv_luid.attr = 0; priv_luid.luid.high = 0; - priv_luid.luid.low = mask; + + for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) { + + /* just use the index+1 (so its non-zero) into the + array as the lower portion of the LUID */ + + if ( se_priv_equal( &privs[i].se_priv, mask ) ) { + priv_luid.luid.low = GENERATE_LUID_LOW(i); + } + } return priv_luid; } /********************************************************************* - Convert a privilege mask to an LUID_ATTR[] and add the privileges to - the PRIVILEGE_SET + Generate the LUID_ATTR structure based on a bitmask *********************************************************************/ -static void add_privilege_set( PRIVILEGE_SET *privset, uint32 mask ) +const char* get_privilege_dispname( const char *name ) { - LUID_ATTR luid; int i; - - for (i=0; privs[i].se_priv != SE_END; i++) { - - /* skip if the privilege is not part of the mask */ - - if ( !(mask & privs[i].se_priv) ) - continue; - - /* remove the bit from the mask */ - mask &= ~privs[i].se_priv; - - luid = get_privilege_luid( privs[i].se_priv ); - - add_privilege( privset, luid ); + for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) { + + if ( strequal( privs[i].name, name ) ) { + return privs[i].description; + } } - /* log an error if we have anything left at this point */ - if ( mask ) - DEBUG(0,("add_privilege_set: leftover bits! [0x%x]\n", mask )); + return NULL; } /********************************************************************* get a list of all privleges for all sids the in list *********************************************************************/ -void get_privileges_for_sids(PRIVILEGE_SET *privset, DOM_SID *slist, int scount) +BOOL get_privileges_for_sids(SE_PRIV *privileges, DOM_SID *slist, int scount) { - uint32 priv_mask; + SE_PRIV mask; int i; + BOOL found = False; + + se_priv_copy( privileges, &se_priv_none ); for ( i=0; ise_priv != SE_NONE ) { - uint32 mask = SVAL(data.dptr, 0); + if ( !se_priv_equal(&priv->privilege, &se_priv_none) ) { + SE_PRIV mask; + + se_priv_copy( &mask, (SE_PRIV*)data.dptr ); /* if the SID does not have the specified privilege then just return */ - if ( !(mask & priv->se_priv) ) + if ( !is_privilege_assigned( &mask, &priv->privilege) ) return 0; } @@ -306,7 +414,8 @@ NTSTATUS privilege_enumerate_accounts(DOM_SID **sids, int *num_sids) PRIV_SID_LIST priv; ZERO_STRUCT(priv); - priv.se_priv = SE_NONE; + + se_priv_copy( &priv.privilege, &se_priv_none ); tdb_traverse( tdb, priv_traverse_fn, &priv); @@ -318,18 +427,17 @@ NTSTATUS privilege_enumerate_accounts(DOM_SID **sids, int *num_sids) return NT_STATUS_OK; } +#if 0 /* JERRY - not used */ /*************************************************************************** Retrieve the SIDs assigned to a given privilege ****************************************************************************/ -NTSTATUS priv_get_sids(const char *privname, DOM_SID **sids, int *num_sids) + NTSTATUS priv_get_sids(const char *privname, DOM_SID **sids, int *num_sids) { TDB_CONTEXT *tdb = get_account_pol_tdb(); PRIV_SID_LIST priv; ZERO_STRUCT(priv); - priv.se_priv = - tdb_traverse( tdb, priv_traverse_fn, &priv); @@ -340,24 +448,32 @@ NTSTATUS priv_get_sids(const char *privname, DOM_SID **sids, int *num_sids) return NT_STATUS_OK; } +#endif /*************************************************************************** Add privilege to sid ****************************************************************************/ -BOOL grant_privilege(const DOM_SID *sid, uint32 priv_mask) +BOOL grant_privilege(const DOM_SID *sid, SE_PRIV *priv_mask) { - uint32 old_mask, new_mask; + SE_PRIV old_mask, new_mask; if ( get_privileges( sid, &old_mask ) ) - new_mask = old_mask | priv_mask; + se_priv_copy( &new_mask, &old_mask ); else - new_mask = priv_mask; + se_priv_copy( &new_mask, &se_priv_none ); + + se_priv_add( &new_mask, priv_mask ); - DEBUG(10,("grant_privilege: %s, orig priv set = 0x%x, new privilege set = 0x%x\n", - sid_string_static(sid), old_mask, new_mask )); + DEBUG(10,("grant_privilege: %s\n", sid_string_static(sid))); + + DEBUGADD( 10, ("original privilege mask:\n")); + dump_se_priv( DBGC_ALL, 10, &old_mask ); - return set_privileges( sid, new_mask ); + DEBUGADD( 10, ("new privilege mask:\n")); + dump_se_priv( DBGC_ALL, 10, &new_mask ); + + return set_privileges( sid, &new_mask ); } /********************************************************************* @@ -368,9 +484,9 @@ BOOL grant_privilege_by_name(DOM_SID *sid, const char *name) { int i; - for ( i = 0; privs[i].se_priv != SE_END; i++ ) { + for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) { if ( strequal(privs[i].name, name) ) { - return grant_privilege( sid, privs[i].se_priv ); + return grant_privilege( sid, &privs[i].se_priv ); } } @@ -383,21 +499,35 @@ BOOL grant_privilege_by_name(DOM_SID *sid, const char *name) Remove privilege from sid ****************************************************************************/ -BOOL revoke_privilege(const DOM_SID *sid, uint32 priv_mask) +BOOL revoke_privilege(const DOM_SID *sid, SE_PRIV *priv_mask) { - uint32 old_mask, new_mask; + SE_PRIV mask; - if ( get_privileges( sid, &old_mask ) ) - new_mask = old_mask | priv_mask; - else - new_mask = priv_mask; + /* if the user has no privileges, then we can't revoke any */ + + if ( !get_privileges( sid, &mask ) ) + return True; + + DEBUG(10,("revoke_privilege: %s\n", sid_string_static(sid))); - new_mask = old_mask & ~priv_mask; + DEBUGADD( 10, ("original privilege mask:\n")); + dump_se_priv( DBGC_ALL, 10, &mask ); - DEBUG(10,("revoke_privilege: %s, orig priv set = 0x%x, new priv set = 0x%x\n", - sid_string_static(sid), old_mask, new_mask )); + se_priv_remove( &mask, priv_mask ); - return set_privileges( sid, new_mask ); + DEBUGADD( 10, ("new privilege mask:\n")); + dump_se_priv( DBGC_ALL, 10, &mask ); + + return set_privileges( sid, &mask ); +} + +/********************************************************************* + Revoke all privileges +*********************************************************************/ + +BOOL revoke_all_privileges( DOM_SID *sid ) +{ + return revoke_privilege( sid, &se_priv_all ); } /********************************************************************* @@ -408,9 +538,9 @@ BOOL revoke_privilege_by_name(DOM_SID *sid, const char *name) { int i; - for ( i = 0; privs[i].se_priv != SE_END; i++ ) { + for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) { if ( strequal(privs[i].name, name) ) { - return revoke_privilege( sid, privs[i].se_priv ); + return revoke_privilege( sid, &privs[i].se_priv ); } } @@ -425,7 +555,7 @@ BOOL revoke_privilege_by_name(DOM_SID *sid, const char *name) NTSTATUS privilege_create_account(const DOM_SID *sid ) { - return ( grant_privilege( sid, SE_NONE ) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL); + return ( grant_privilege(sid, &se_priv_none) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL); } /**************************************************************************** @@ -508,12 +638,13 @@ done: return ret; } +#if 0 /* not used */ /**************************************************************************** Performa deep copy of a PRIVILEGE_SET structure. Assumes an initialized destination structure. *****************************************************************************/ -BOOL dup_privilege_set( PRIVILEGE_SET *dest, PRIVILEGE_SET *src ) + BOOL dup_privilege_set( PRIVILEGE_SET *dest, PRIVILEGE_SET *src ) { NTSTATUS result; @@ -532,15 +663,16 @@ BOOL dup_privilege_set( PRIVILEGE_SET *dest, PRIVILEGE_SET *src ) return True; } +#endif /**************************************************************************** Does the user have the specified privilege ? We only deal with one privilege at a time here. *****************************************************************************/ -BOOL user_has_privilege(NT_USER_TOKEN *token, uint32 privilege) +BOOL user_has_privileges(NT_USER_TOKEN *token, SE_PRIV *privilege) { - return check_priv_in_privilege( &token->privileges, get_privilege_luid(privilege) ); + return is_privilege_assigned( &token->privileges, privilege ); } /**************************************************************************** @@ -550,38 +682,37 @@ BOOL user_has_privilege(NT_USER_TOKEN *token, uint32 privilege) char* luid_to_privilege_name(const LUID *set) { static fstring name; - int i = 0; + int max = count_all_privileges(); if (set->high != 0) return NULL; - for ( i=0; privs[i].se_priv!=SE_END; i++ ) { - if (set->low == privs[i].se_priv) { - fstrcpy(name, privs[i].name); - return name; - } - } + if ( set->low > max ) + return NULL; - return NULL; + fstrcpy( name, privs[set->low - 1].name ); + + return name; } /**************************************************************************** Convert an LUID to a 32-bit mask ****************************************************************************/ -uint32 luid_to_privilege_mask(const LUID *set) +SE_PRIV* luid_to_privilege_mask(const LUID *set) { - int i = 0; - + static SE_PRIV mask; + int max = count_all_privileges(); + if (set->high != 0) - return SE_END; + return NULL; - for ( i=0; privs[i].se_priv != SE_END; i++ ) { - if (set->low == privs[i].se_priv) - return privs[i].se_priv; - } + if ( set->low > max ) + return NULL; + + se_priv_copy( &mask, &privs[set->low - 1].se_priv ); - return SE_END; + return &mask; } /******************************************************************* @@ -596,20 +727,78 @@ int count_all_privileges( void ) return count; /* loop over the array and count it */ - for ( count=0; privs[count].se_priv != SE_END; count++ ) ; + for ( count=0; !se_priv_equal(&privs[count].se_priv, &se_priv_end); count++ ) ; return count; } +#if 0 /* not used */ /******************************************************************* + return True is the SID has an entry in the account_pol.tdb *******************************************************************/ -BOOL is_privileged_sid( DOM_SID *sid ) + BOOL is_privileged_sid( DOM_SID *sid ) { - int mask; + SE_PRIV mask; /* check if the lookup succeeds */ return get_privileges( sid, &mask ); } +#endif + +/******************************************************************* +*******************************************************************/ + +BOOL se_priv_to_privilege_set( PRIVILEGE_SET *set, SE_PRIV *mask ) +{ + int i; + uint32 num_privs = count_all_privileges(); + LUID_ATTR luid; + + luid.attr = 0; + luid.luid.high = 0; + + for ( i=0; icount; i++ ) { + SE_PRIV r; + + /* sanity check for invalid privilege. we really + only care about the low 32 bits */ + + if ( privset->set[i].luid.high != 0 ) + return False; + + /* make sure :LUID.low is in range */ + if ( privset->set[i].luid.low == 0 || privset->set[i].luid.low > num_privs ) + return False; + + r = privs[privset->set[i].luid.low - 1].se_priv; + se_priv_add( mask, &r ); + } + + return True; +} diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index a7513030bd5..d22ec935a39 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -5049,6 +5049,7 @@ BOOL print_access_check(struct current_user *user, int snum, int access_type) const char *pname; TALLOC_CTX *mem_ctx = NULL; extern struct current_user current_user; + SE_PRIV se_printop = SE_PRINT_OPERATOR; /* If user is NULL then use the current_user structure */ @@ -5057,7 +5058,7 @@ BOOL print_access_check(struct current_user *user, int snum, int access_type) /* Always allow root or SE_PRINT_OPERATROR to do anything */ - if ( user->uid == 0 || user_has_privilege(user->nt_user_token, SE_PRINT_OPERATOR) ) { + if ( user->uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) { return True; } diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index 304e1d363c9..e5154dbb539 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -765,6 +765,7 @@ NTSTATUS _lsa_enum_privs(pipes_struct *p, LSA_Q_ENUM_PRIVS *q_u, LSA_R_ENUM_PRIV uint32 enum_context = q_u->enum_context; int num_privs = count_all_privileges(); LSA_PRIV_ENTRY *entries = NULL; + LUID_ATTR luid; /* remember that the enum_context starts at 0 and not 1 */ @@ -794,13 +795,17 @@ NTSTATUS _lsa_enum_privs(pipes_struct *p, LSA_Q_ENUM_PRIVS *q_u, LSA_R_ENUM_PRIV if( i < enum_context) { init_unistr2(&entries[i].name, NULL, UNI_FLAGS_NONE); init_uni_hdr(&entries[i].hdr_name, &entries[i].name); + entries[i].luid_low = 0; entries[i].luid_high = 0; } else { init_unistr2(&entries[i].name, privs[i].name, UNI_FLAGS_NONE); init_uni_hdr(&entries[i].hdr_name, &entries[i].name); - entries[i].luid_low = privs[i].se_priv; - entries[i].luid_high = 0; + + luid = get_privilege_luid( &privs[i].se_priv ); + + entries[i].luid_low = luid.luid.low; + entries[i].luid_high = luid.luid.high; } } @@ -819,7 +824,7 @@ NTSTATUS _lsa_priv_get_dispname(pipes_struct *p, LSA_Q_PRIV_GET_DISPNAME *q_u, L { struct lsa_info *handle; fstring name_asc; - int i = 0; + const char *description; if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle)) return NT_STATUS_INVALID_HANDLE; @@ -834,22 +839,25 @@ NTSTATUS _lsa_priv_get_dispname(pipes_struct *p, LSA_Q_PRIV_GET_DISPNAME *q_u, L unistr2_to_ascii(name_asc, &q_u->name, sizeof(name_asc)); - DEBUG(10,("_lsa_priv_get_dispname: %s\n", name_asc)); + DEBUG(10,("_lsa_priv_get_dispname: name = %s\n", name_asc)); - while (privs[i].se_priv != SE_END && !strequal(name_asc, privs[i].name)) - i++; + description = get_privilege_dispname( name_asc ); - if (privs[i].se_priv != SE_END) { - DEBUG(10,(": %s\n", privs[i].description)); - init_unistr2(&r_u->desc, privs[i].description, UNI_FLAGS_NONE); + if ( description ) { + DEBUG(10,("_lsa_priv_get_dispname: display name = %s\n", description)); + + init_unistr2(&r_u->desc, description, UNI_FLAGS_NONE); init_uni_hdr(&r_u->hdr_desc, &r_u->desc); r_u->ptr_info = 0xdeadbeef; r_u->lang_id = q_u->lang_id; + return NT_STATUS_OK; } else { DEBUG(10,("_lsa_priv_get_dispname: doesn't exist\n")); + r_u->ptr_info = 0; + return NT_STATUS_NO_SUCH_PRIVILEGE; } } @@ -1026,24 +1034,31 @@ NTSTATUS _lsa_open_account(pipes_struct *p, LSA_Q_OPENACCOUNT *q_u, LSA_R_OPENAC NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, prs_struct *ps, LSA_Q_ENUMPRIVSACCOUNT *q_u, LSA_R_ENUMPRIVSACCOUNT *r_u) { struct lsa_info *info=NULL; - PRIVILEGE_SET priv; + SE_PRIV mask; + PRIVILEGE_SET privileges; /* find the connection policy handle. */ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; - privilege_set_init( &priv ); + if ( !get_privileges_for_sids( &mask, &info->sid, 1 ) ) + return NT_STATUS_OBJECT_NAME_NOT_FOUND; - get_privileges_for_sids( &priv, &info->sid, 1 ); + privilege_set_init( &privileges ); - DEBUG(10,("_lsa_enum_privsaccount: %s has %d privileges\n", - sid_string_static(&info->sid), priv.count)); + if ( se_priv_to_privilege_set( &privileges, &mask ) ) { - init_lsa_r_enum_privsaccount(ps->mem_ctx, r_u, priv.set, priv.count, 0); + DEBUG(10,("_lsa_enum_privsaccount: %s has %d privileges\n", + sid_string_static(&info->sid), privileges.count)); - privilege_set_free( &priv ); + r_u->status = init_lsa_r_enum_privsaccount(ps->mem_ctx, r_u, privileges.set, privileges.count, 0); + } + else + r_u->status = NT_STATUS_NO_SUCH_PRIVILEGE; - return NT_STATUS_OK; + privilege_set_free( &privileges ); + + return r_u->status; } /*************************************************************************** @@ -1114,8 +1129,7 @@ NTSTATUS _lsa_setsystemaccount(pipes_struct *p, LSA_Q_SETSYSTEMACCOUNT *q_u, LSA NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u) { struct lsa_info *info = NULL; - int i = 0; - uint32 mask; + SE_PRIV mask; PRIVILEGE_SET *set = NULL; /* find the connection policy handle. */ @@ -1130,17 +1144,15 @@ NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u set = &q_u->set; - for (i = 0; i < set->count; i++) { - - mask = luid_to_privilege_mask( &(set->set[i].luid) ); + if ( !privilege_set_to_se_priv( &mask, set ) ) + return NT_STATUS_NO_SUCH_PRIVILEGE; - if ( mask != SE_END ) { - if ( !grant_privilege( &info->sid, mask ) ) { - DEBUG(3,("_lsa_addprivs: grant_privilege( %s, 0x%x) failed!\n", - sid_string_static(&info->sid), mask )); - return NT_STATUS_NO_SUCH_PRIVILEGE; - } - } + if ( !grant_privilege( &info->sid, &mask ) ) { + DEBUG(3,("_lsa_addprivs: grant_privilege(%s) failed!\n", + sid_string_static(&info->sid) )); + DEBUG(3,("Privilege mask:\n")); + dump_se_priv( DBGC_ALL, 3, &mask ); + return NT_STATUS_NO_SUCH_PRIVILEGE; } return NT_STATUS_OK; @@ -1153,8 +1165,7 @@ NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEPRIVS *r_u) { struct lsa_info *info = NULL; - int i = 0; - uint32 mask; + SE_PRIV mask; PRIVILEGE_SET *set = NULL; /* find the connection policy handle. */ @@ -1169,16 +1180,15 @@ NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEP set = &q_u->set; - for (i = 0; i < set->count; i++) { - mask = luid_to_privilege_mask( &(set->set[i].luid) ); + if ( !privilege_set_to_se_priv( &mask, set ) ) + return NT_STATUS_NO_SUCH_PRIVILEGE; - if ( mask != SE_END ) { - if ( !revoke_privilege( &info->sid, mask ) ) { - DEBUG(3,("_lsa_removeprivs: revoke_privilege( %s, 0x%x) failed!\n", - sid_string_static(&info->sid), mask )); - return NT_STATUS_NO_SUCH_PRIVILEGE; - } - } + if ( !revoke_privilege( &info->sid, &mask ) ) { + DEBUG(3,("_lsa_removeprivs: revoke_privilege(%s) failed!\n", + sid_string_static(&info->sid) )); + DEBUG(3,("Privilege mask:\n")); + dump_se_priv( DBGC_ALL, 3, &mask ); + return NT_STATUS_NO_SUCH_PRIVILEGE; } return NT_STATUS_OK; @@ -1373,7 +1383,7 @@ NTSTATUS _lsa_remove_acct_rights(pipes_struct *p, LSA_Q_REMOVE_ACCT_RIGHTS *q_u, sid_copy( &sid, &q_u->sid.sid ); if ( q_u->removeall ) { - if ( !revoke_privilege( &sid, SE_ALL_PRIVS ) ) + if ( !revoke_all_privileges( &sid ) ) return NT_STATUS_ACCESS_DENIED; return NT_STATUS_OK; @@ -1406,6 +1416,7 @@ NTSTATUS _lsa_enum_acct_rights(pipes_struct *p, LSA_Q_ENUM_ACCT_RIGHTS *q_u, LSA struct lsa_info *info = NULL; DOM_SID sid; PRIVILEGE_SET privileges; + SE_PRIV mask; /* find the connection policy handle. */ @@ -1418,11 +1429,20 @@ NTSTATUS _lsa_enum_acct_rights(pipes_struct *p, LSA_Q_ENUM_ACCT_RIGHTS *q_u, LSA sid_copy( &sid, &q_u->sid.sid ); + if ( !get_privileges_for_sids( &mask, &sid, 1 ) ) + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + privilege_set_init( &privileges ); - get_privileges_for_sids( &privileges, &sid, 1 ); + if ( se_priv_to_privilege_set( &privileges, &mask ) ) { + + DEBUG(10,("_lsa_enum_acct_rights: %s has %d privileges\n", + sid_string_static(&sid), privileges.count)); - r_u->status = init_r_enum_acct_rights( r_u, &privileges ); + r_u->status = init_r_enum_acct_rights( r_u, &privileges ); + } + else + r_u->status = NT_STATUS_NO_SUCH_PRIVILEGE; privilege_set_free( &privileges ); diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 4c3f95fe6b8..515eefb1fa6 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -2216,6 +2216,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA /* check this, when giving away 'add computer to domain' privs */ uint32 des_access = GENERIC_RIGHTS_USER_ALL_ACCESS; BOOL can_add_machines = False; + SE_PRIV se_machineop = SE_MACHINE_ACCOUNT; /* Get the domain SID stored in the domain policy */ if (!get_lsa_policy_samr_sid(p, &dom_pol, &sid, &acc_granted)) @@ -2242,7 +2243,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA /* check to see if we are a domain admin */ - can_add_machines = user_has_privilege( p->pipe_user.nt_user_token, SE_MACHINE_ACCOUNT ); + can_add_machines = user_has_privileges( p->pipe_user.nt_user_token, &se_machineop ); DEBUG(5, ("_samr_create_user: %s is%s a member of the Domain Admins group\n", p->pipe_user_name, can_add_machines ? "" : " not")); @@ -3034,6 +3035,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE uint32 acc_granted; uint32 acc_required; BOOL can_add_machines; + SE_PRIV se_machineop = SE_MACHINE_ACCOUNT; DEBUG(5, ("_samr_set_userinfo: %d\n", __LINE__)); @@ -3067,7 +3069,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE /* check to see if we are a domain admin */ - can_add_machines = user_has_privilege( p->pipe_user.nt_user_token, SE_MACHINE_ACCOUNT ); + can_add_machines = user_has_privileges( p->pipe_user.nt_user_token, &se_machineop ); DEBUG(5, ("_samr_create_user: %s is%s a member of the Domain Admins group\n", p->pipe_user_name, can_add_machines ? "" : " not")); @@ -3159,6 +3161,7 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_ uint32 acc_granted; uint32 acc_required; BOOL can_add_machines; + SE_PRIV se_machineop = SE_MACHINE_ACCOUNT; DEBUG(5, ("samr_reply_set_userinfo2: %d\n", __LINE__)); @@ -3184,7 +3187,7 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_ /* check to see if we are a domain admin */ - can_add_machines = user_has_privilege( p->pipe_user.nt_user_token, SE_MACHINE_ACCOUNT ); + can_add_machines = user_has_privileges( p->pipe_user.nt_user_token, &se_machineop ); DEBUG(5, ("_samr_create_user: %s is%s a member of the Domain Admins group\n", p->pipe_user_name, can_add_machines ? "" : " not")); diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index ba3ee4706cb..12611c4ee5a 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -1684,6 +1684,8 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER ) { + SE_PRIV se_printop = SE_PRINT_OPERATOR; + if (!lp_ms_add_printer_wizard()) { close_printer_handle(p, handle); return WERR_ACCESS_DENIED; @@ -1693,7 +1695,7 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, and not a printer admin, then fail */ if ( user.uid != 0 - && !user_has_privilege( user.nt_user_token, SE_PRINT_OPERATOR ) + && !user_has_privileges( user.nt_user_token, &se_printop ) && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) ) { close_printer_handle(p, handle); diff --git a/source3/script/mkproto.awk b/source3/script/mkproto.awk index 4edc7abc63a..45cc0821aa8 100644 --- a/source3/script/mkproto.awk +++ b/source3/script/mkproto.awk @@ -132,7 +132,7 @@ END { gotstart = 1; } - if( $0 ~ /^WINBINDD_PW|^WINBINDD_GR|^NT_PRINTER_INFO_LEVEL_2|^LOGIN_CACHE|^krb5_error_code|^LDAP|^u32/ ) { + if( $0 ~ /^WINBINDD_PW|^WINBINDD_GR|^NT_PRINTER_INFO_LEVEL_2|^LOGIN_CACHE|^krb5_error_code|^LDAP|^u32|^LUID_ATTR/ ) { gotstart = 1; }