diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/auth/auth_util.c | 15 | ||||
-rw-r--r-- | source3/include/privileges.h | 30 | ||||
-rw-r--r-- | source3/include/smb.h | 2 | ||||
-rw-r--r-- | source3/lib/privileges.c | 429 | ||||
-rw-r--r-- | source3/printing/nt_printing.c | 3 | ||||
-rw-r--r-- | source3/rpc_server/srv_lsa_nt.c | 106 | ||||
-rw-r--r-- | source3/rpc_server/srv_samr_nt.c | 9 | ||||
-rw-r--r-- | source3/rpc_server/srv_spoolss_nt.c | 4 | ||||
-rw-r--r-- | source3/script/mkproto.awk | 2 |
9 files changed, 406 insertions, 194 deletions
diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index e4793c3df3..4a23ec8adc 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; i<token->privileges.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 cdf62b7f85..b4972c7a60 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 1cf5aac0c5..913061014d 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 09a868fc27..973e9acc65 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; i<SE_PRIV_MASKSIZE; i++ ) { + mask->mask[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; i<SE_PRIV_MASKSIZE; i++ ) { + mask->mask[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; i<SE_PRIV_MASKSIZE; i++ ) { + DEBUGADDC( dbg_cl, dbg_lvl,(" 0x%x", mask->mask[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_<SID> (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_<SID> (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; i<scount; i++ ) { /* don't add unless we actually have a privilege assigned */ - if ( !get_privileges( &slist[i], &priv_mask ) ) + if ( !get_privileges( &slist[i], &mask ) ) continue; - DEBUG(5,("get_privileges_for_sids: sid = %s, privilege mask = 0x%x\n", - sid_string_static(&slist[i]), priv_mask)); + DEBUG(5,("get_privileges_for_sids: sid = %s\nPrivilege set:\n", + sid_string_static(&slist[i]))); + dump_se_priv( DBGC_ALL, 5, &mask ); - add_privilege_set( privset, priv_mask ); + se_priv_add( privileges, &mask ); + found = True; } + + return found; } @@ -265,6 +366,11 @@ static int priv_traverse_fn(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *s int prefixlen = strlen(PRIVPREFIX); DOM_SID sid; fstring sid_string; + + /* easy check first */ + + if ( data.dsize != sizeof(SE_PRIV) ) + return 0; /* check we have a PRIV_+SID entry */ @@ -273,13 +379,15 @@ static int priv_traverse_fn(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *s /* check to see if we are looking for a particular privilege */ - if ( priv->se_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; i<num_privs; i++ ) { + if ( !is_privilege_assigned(mask, &privs[i].se_priv) ) + continue; + + luid.luid.low = GENERATE_LUID_LOW(i); + + if ( !privilege_set_add( set, luid ) ) + return False; + } + + return True; +} + +/******************************************************************* +*******************************************************************/ + +BOOL privilege_set_to_se_priv( SE_PRIV *mask, PRIVILEGE_SET *privset ) +{ + int i; + uint32 num_privs = count_all_privileges(); + + ZERO_STRUCTP( mask ); + + for ( i=0; i<privset->count; 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 a7513030bd..d22ec935a3 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 304e1d363c..e5154dbb53 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 4c3f95fe6b..515eefb1fa 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 ba3ee4706c..12611c4ee5 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 4edc7abc63..45cc0821aa 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; } |