r4805: Last planned change to the privileges infrastructure:
authorGerald Carter <jerry@samba.org>
Mon, 17 Jan 2005 15:23:11 +0000 (15:23 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:53:55 +0000 (10:53 -0500)
* 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)

source3/auth/auth_util.c
source3/include/privileges.h
source3/include/smb.h
source3/lib/privileges.c
source3/printing/nt_printing.c
source3/rpc_server/srv_lsa_nt.c
source3/rpc_server/srv_samr_nt.c
source3/rpc_server/srv_spoolss_nt.c
source3/script/mkproto.awk

index e4793c3df39745dbbbe444a94632ea827df26591..4a23ec8adc5a1e595215d1aef6faf2eb5716d1a6 100644 (file)
@@ -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;
index cdf62b7f858db718e4dd7a288685505675e3153e..b4972c7a602ef895a949ca11af058f1ecfc16fcd 100644 (file)
 
 /* 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;
index 1cf5aac0c507906a3ad5ce5c98f0ba9cd976d5ec..913061014dbca17325af0aeb2aa73804a5e07dc7 100644 (file)
@@ -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 ***/
index 09a868fc277079ff95778b99c3bc7c4b893afffb..973e9acc65f7a6c965d998d035cfe342ebb517ec 100644 (file)
 
 #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;
+}
 
index a7513030bd52744753f3754ae6061e604b1e7182..d22ec935a39cc737990614784aad31879581487a 100644 (file)
@@ -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;
        }
 
index 304e1d363c9b6c9851ab55e2e7234076118a4ea7..e5154dbb539204858bb00e5a976a7e68df2624c7 100644 (file)
@@ -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 );
 
index 4c3f95fe6b8480e1fa2ea90d145645fa5d17a1e6..515eefb1fa6945ce6794ab0d55534b1f14325189 100644 (file)
@@ -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"));
index ba3ee4706cb5f7c0a637b30259d8a07920d4e09b..12611c4ee5a399259fc8b80fce03a7162d52528f 100644 (file)
@@ -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);
index 4edc7abc63a42a39f32f0ac0252f4092d639745c..45cc0821aa8c083f275eb2e30be151b027e02644 100644 (file)
@@ -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;
   }