s4-privs Seperate rights and privileges
authorAndrew Bartlett <abartlet@samba.org>
Sat, 11 Sep 2010 06:58:45 +0000 (16:58 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Sat, 11 Sep 2010 08:46:13 +0000 (18:46 +1000)
These are related, but slightly different concepts.  The biggest difference
is that rights are not enumerated as a system-wide list.

This moves the rights to security.idl due to dependencies.

Andrew Bartlett

libcli/security/privileges.c
libcli/security/privileges.h
librpc/idl/lsa.idl
librpc/idl/security.idl
source4/dsdb/samdb/samdb_privilege.c
source4/rpc_server/lsa/dcesrv_lsa.c

index 466bea0565519dcf3702b71817f1fedd2a556bdd..1fecf4011d3bfd67c455de89e43ef70583b38b4a 100644 (file)
@@ -59,14 +59,9 @@ static const struct {
        {SEC_PRIV_ADD_USERS,       SEC_PRIV_ADD_USERS_BIT,       "SeAddUsersPrivilege",         "Add users and groups to the domain"},
        {SEC_PRIV_DISK_OPERATOR,   SEC_PRIV_DISK_OPERATOR_BIT,   "SeDiskOperatorPrivilege",     "Manage disk shares"},
 
-       /* The list from here on was not displayed in the code from
-        * source3/ with the comment that usrmgr will display these
-        * next 2 twice if you include them.  The source4/ code has
-        * always included them, but they do not appear in Windows
-        * 2008 R2.
-
-          Finally, the parameter 'short_list' determines if the short
-          or full list (including many other privileges) is used */
+       /* The list from here on is not displayed in the code from
+        * source3, and is after index NUM_SHORT_LIST_PRIVS for that
+        * reason */ 
 
        {SEC_PRIV_SECURITY,
         SEC_PRIV_SECURITY_BIT,
@@ -152,19 +147,26 @@ static const struct {
         SEC_PRIV_ENABLE_DELEGATION_BIT,
         "SeEnableDelegationPrivilege",
        "Enable Delegation"},
+};
 
-       {SEC_PRIV_INTERACTIVE_LOGON,
-        SEC_PRIV_INTERACTIVE_LOGON_BIT,
+/* These are rights, not privileges, and should not be confused.  The
+ * names are very similar, and they are quite similar in behaviour,
+ * but they are not to be enumerated as a system-wide list or have an
+ * LUID value */
+static const struct {
+       uint32_t right_mask;
+       const char *name;
+       const char *description;
+} rights[] = {
+       {LSA_POLICY_MODE_INTERACTIVE,
         "SeInteractiveLogonRight",
        "Interactive logon"},
 
-       {SEC_PRIV_NETWORK_LOGON,
-        SEC_PRIV_NETWORK_LOGON_BIT,
+       {LSA_POLICY_MODE_NETWORK,
         "SeNetworkLogonRight",
        "Network logon"},
 
-       {SEC_PRIV_REMOTE_INTERACTIVE_LOGON,
-        SEC_PRIV_REMOTE_INTERACTIVE_LOGON_BIT,
+       {LSA_POLICY_MODE_REMOTE_INTERACTIVE,
         "SeRemoteInteractiveLogonRight",
        "Remote Interactive logon"}
 };
@@ -368,6 +370,20 @@ enum sec_privilege sec_privilege_id(const char *name)
        return SEC_PRIV_INVALID;
 }
 
+/*
+  map a 'right' name to it's bitmap value. Return 0 if not found
+*/
+uint32_t sec_right_bit(const char *name)
+{
+       int i;
+       for (i=0;i<ARRAY_SIZE(rights);i++) {
+               if (strcasecmp(rights[i].name, name) == 0) {
+                       return rights[i].right_mask;
+               }
+       }
+       return 0;
+}
+
 /*
   assist in walking the table of privileges - return the LUID (low 32 bits) by index
 */
@@ -419,6 +435,14 @@ void security_token_set_privilege(struct security_token *token, enum sec_privile
        token->privilege_mask |= sec_privilege_mask(privilege);
 }
 
+/*
+  set a bit in the rights mask
+*/
+void security_token_set_right_bit(struct security_token *token, uint32_t right_bit)
+{
+       token->rights_mask |= right_bit;
+}
+
 void security_token_debug_privileges(int dbg_lev, const struct security_token *token)
 {
        DEBUGADD(dbg_lev, (" Privileges (0x%16llX):\n",
@@ -434,4 +458,17 @@ void security_token_debug_privileges(int dbg_lev, const struct security_token *t
                        }
                }
        }
+       DEBUGADD(dbg_lev, (" Rights (0x%16lX):\n",
+                           (unsigned long) token->rights_mask));
+
+       if (token->rights_mask) {
+               int idx = 0;
+               int i = 0;
+               for (idx = 0; idx<ARRAY_SIZE(rights); idx++) {
+                       if (token->rights_mask & rights[idx].right_mask) {
+                               DEBUGADD(dbg_lev, ("  Right[%3lu]: %s\n", (unsigned long)i++,
+                                                  rights[idx].name));
+                       }
+               }
+       }
 }
index 25895fd1ff277beed864687160f0ccd17b6c5f13..f67a38bc2788f56c724c4270ae94701252db2d5c 100644 (file)
@@ -69,6 +69,11 @@ const char *sec_privilege_display_name(enum sec_privilege privilege, uint16_t *l
 */
 enum sec_privilege sec_privilege_id(const char *name);
 
+/*
+  map a 'right' name to it's bitmap value. Return 0 if not found
+*/
+uint32_t sec_right_bit(const char *name);
+
 /*
   assist in walking the table of privileges - return the LUID (low 32 bits) by index
 */
@@ -88,6 +93,10 @@ bool security_token_has_privilege(const struct security_token *token, enum sec_p
   set a bit in the privilege mask
 */
 void security_token_set_privilege(struct security_token *token, enum sec_privilege privilege);
+/*
+  set a bit in the rights mask
+*/
+void security_token_set_right_bit(struct security_token *token, uint32_t right_bit);
 
 void security_token_debug_privileges(int dbg_lev, const struct security_token *token);
 
index e9c65045d9cf5e9a17af71af81fbc83bb3b48a4e..343d21da07d35255b3e38a6d1550d8202d3da687 100644 (file)
@@ -639,22 +639,6 @@ import "misc.idl", "security.idl";
        /* Function:           0x16 */
        [todo] NTSTATUS lsa_SetQuotasForAccount();
 
-       typedef [bitmap32bit] bitmap {
-               LSA_POLICY_MODE_INTERACTIVE             = 0x00000001,
-               LSA_POLICY_MODE_NETWORK                 = 0x00000002,
-               LSA_POLICY_MODE_BATCH                   = 0x00000004,
-               LSA_POLICY_MODE_SERVICE                 = 0x00000010,
-               LSA_POLICY_MODE_PROXY                   = 0x00000020,
-               LSA_POLICY_MODE_DENY_INTERACTIVE        = 0x00000040,
-               LSA_POLICY_MODE_DENY_NETWORK            = 0x00000080,
-               LSA_POLICY_MODE_DENY_BATCH              = 0x00000100,
-               LSA_POLICY_MODE_DENY_SERVICE            = 0x00000200,
-               LSA_POLICY_MODE_REMOTE_INTERACTIVE      = 0x00000400,
-               LSA_POLICY_MODE_DENY_REMOTE_INTERACTIVE = 0x00000800,
-               LSA_POLICY_MODE_ALL                     = 0x00000FF7,
-               LSA_POLICY_MODE_ALL_NT4                 = 0x00000037
-       } lsa_SystemAccessModeFlags;
-
        /* Function:    0x17 */
        NTSTATUS lsa_GetSystemAccessAccount(
                [in]      policy_handle *handle,
index 4f5245b2e4fba56157a4e2db696df28f73a702c6..13ccb4953734c02d797b68dad0ab5c339c2e81b5 100644 (file)
@@ -32,6 +32,8 @@ cpp_quote("#define dom_sid0 dom_sid")
 interface security
 {
 
+       typedef bitmap lsa_SystemAccessModeFlags lsa_SystemAccessModeFlags;
+
        typedef [public,gensize,noprint,nosize,nopull,nopush] struct {
                uint8  sid_rev_num;             /**< SID revision number */
                [range(0,15)] int8  num_auths;  /**< Number of sub-authorities */
@@ -390,11 +392,7 @@ interface security
                /* Samba-specific privs */
                SEC_PRIV_PRINT_OPERATOR            = 0x1001,
                SEC_PRIV_ADD_USERS                 = 0x1002,
-               SEC_PRIV_DISK_OPERATOR             = 0x1003,
-               /* Windows privs not in the list above */
-               SEC_PRIV_INTERACTIVE_LOGON         = 0x2022,
-               SEC_PRIV_NETWORK_LOGON             = 0x2023,
-               SEC_PRIV_REMOTE_INTERACTIVE_LOGON  = 0x2024
+               SEC_PRIV_DISK_OPERATOR             = 0x1003
        } sec_privilege;
 
 
@@ -403,10 +401,6 @@ interface security
         * as a bitmap (privilages.ldb uses the string forms).
         */
        typedef [bitmap64bit] bitmap {
-               SEC_PRIV_NETWORK_LOGON_BIT              = 0x00000001,
-               SEC_PRIV_INTERACTIVE_LOGON_BIT          = 0x00000002,
-               SEC_PRIV_BATCH_LOGON_BIT                        = 0x00000004,
-               SEC_PRIV_SERVICE_LOGON_BIT              = 0x00000008,
                SEC_PRIV_MACHINE_ACCOUNT_BIT            = 0x00000010,
 
                /* Samba-specific privs */
@@ -436,11 +430,25 @@ interface security
                SEC_PRIV_ENABLE_DELEGATION_BIT            = 0x02000000,
                SEC_PRIV_MANAGE_VOLUME_BIT                = 0x04000000,
                SEC_PRIV_IMPERSONATE_BIT                  = 0x08000000,
-               SEC_PRIV_CREATE_GLOBAL_BIT                = 0x10000000,
-               /* Windows privs not in the list above */
-               SEC_PRIV_REMOTE_INTERACTIVE_LOGON_BIT     = 0x20000000
+               SEC_PRIV_CREATE_GLOBAL_BIT                = 0x10000000
        } se_privilege;
 
+       typedef [bitmap32bit] bitmap {
+               LSA_POLICY_MODE_INTERACTIVE             = 0x00000001,
+               LSA_POLICY_MODE_NETWORK                 = 0x00000002,
+               LSA_POLICY_MODE_BATCH                   = 0x00000004,
+               LSA_POLICY_MODE_SERVICE                 = 0x00000010,
+               LSA_POLICY_MODE_PROXY                   = 0x00000020,
+               LSA_POLICY_MODE_DENY_INTERACTIVE        = 0x00000040,
+               LSA_POLICY_MODE_DENY_NETWORK            = 0x00000080,
+               LSA_POLICY_MODE_DENY_BATCH              = 0x00000100,
+               LSA_POLICY_MODE_DENY_SERVICE            = 0x00000200,
+               LSA_POLICY_MODE_REMOTE_INTERACTIVE      = 0x00000400,
+               LSA_POLICY_MODE_DENY_REMOTE_INTERACTIVE = 0x00000800,
+               LSA_POLICY_MODE_ALL                     = 0x00000FF7,
+               LSA_POLICY_MODE_ALL_NT4                 = 0x00000037
+       } lsa_SystemAccessModeFlags;
+
        typedef [public,bitmap8bit] bitmap {
                SEC_ACE_FLAG_OBJECT_INHERIT             = 0x01,
                SEC_ACE_FLAG_CONTAINER_INHERIT          = 0x02,
@@ -564,7 +572,8 @@ interface security
        typedef [public] struct {
                uint32 num_sids;
                [size_is(num_sids)] dom_sid sids[*];
-               udlong privilege_mask;
+               se_privilege privilege_mask;
+               lsa_SystemAccessModeFlags rights_mask;
        } security_token;
 
        /* bits that determine which parts of a security descriptor
index 6186097d7887ad8775f753286509a52415b6cda7..69c4ebea6172f594883773057fb263cb47c22bfe 100644 (file)
@@ -70,8 +70,12 @@ static NTSTATUS samdb_privilege_setup_sid(struct ldb_context *pdb, TALLOC_CTX *m
                const char *priv_str = (const char *)el->values[i].data;
                enum sec_privilege privilege = sec_privilege_id(priv_str);
                if (privilege == SEC_PRIV_INVALID) {
-                       DEBUG(1,("Unknown privilege '%s' in samdb\n",
-                                priv_str));
+                       uint32_t right_bit = sec_right_bit(priv_str);
+                       security_token_set_right_bit(token, right_bit);
+                       if (right_bit == 0) {
+                               DEBUG(1,("Unknown privilege '%s' in samdb\n",
+                                        priv_str));
+                       }
                        continue;
                }
                security_token_set_privilege(token, privilege);
index 675aa178a723d628aeff7c5c63fef34148a2a800..81ad6f7a92262d3d45ce812bdcee6b626a481e36 100644 (file)
@@ -2410,7 +2410,7 @@ static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
        struct dcesrv_handle *h;
        struct lsa_account_state *astate;
        int ret;
-       unsigned int i;
+       unsigned int i, j;
        struct ldb_message **res;
        const char * const attrs[] = { "privilege", NULL};
        struct ldb_message_element *el;
@@ -2456,17 +2456,20 @@ static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
                return NT_STATUS_NO_MEMORY;
        }
 
+       j = 0;
        for (i=0;i<el->num_values;i++) {
                int id = sec_privilege_id((const char *)el->values[i].data);
                if (id == SEC_PRIV_INVALID) {
-                       return NT_STATUS_INTERNAL_DB_CORRUPTION;
+                       /* Perhaps an account right, not a privilege */
+                       continue;
                }
-               privs->set[i].attribute = 0;
-               privs->set[i].luid.low = id;
-               privs->set[i].luid.high = 0;
+               privs->set[j].attribute = 0;
+               privs->set[j].luid.low = id;
+               privs->set[j].luid.high = 0;
+               j++;
        }
 
-       privs->count = el->num_values;
+       privs->count = j;
 
        return NT_STATUS_OK;
 }
@@ -2585,6 +2588,11 @@ static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_
 
        for (i=0;i<rights->count;i++) {
                if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
+                       if (sec_right_bit(rights->names[i].string) == 0) {
+                               talloc_free(msg);
+                               return NT_STATUS_NO_SUCH_PRIVILEGE;
+                       }
+
                        talloc_free(msg);
                        return NT_STATUS_NO_SUCH_PRIVILEGE;
                }
@@ -2765,43 +2773,47 @@ static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_cal
 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct lsa_GetSystemAccessAccount *r)
 {
-       uint32_t i;
-       NTSTATUS status;
-       struct lsa_EnumPrivsAccount enumPrivs;
-       struct lsa_PrivilegeSet *privs;
+       struct dcesrv_handle *h;
+       struct lsa_account_state *astate;
+       int ret;
+       unsigned int i;
+       struct ldb_message **res;
+       const char * const attrs[] = { "privilege", NULL};
+       struct ldb_message_element *el;
+       const char *sidstr;
 
-       privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
-       if (!privs) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       privs->count = 0;
-       privs->unknown = 0;
-       privs->set = NULL;
+       *(r->out.access_mask) = 0x00000000;
 
-       enumPrivs.in.handle = r->in.handle;
-       enumPrivs.out.privs = &privs;
+       DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
 
-       status = dcesrv_lsa_EnumPrivsAccount(dce_call, mem_ctx, &enumPrivs);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }       
+       astate = h->data;
 
-       *(r->out.access_mask) = 0x00000000;
+       sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
+       if (sidstr == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       for (i = 0; i < privs->count; i++) {
-               int priv = privs->set[i].luid.low;
+       ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs, 
+                          "objectSid=%s", sidstr);
+       if (ret < 0) {
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+       if (ret != 1) {
+               return NT_STATUS_OK;
+       }
 
-               switch (priv) {
-               case SEC_PRIV_INTERACTIVE_LOGON:
-                       *(r->out.access_mask) |= LSA_POLICY_MODE_INTERACTIVE;
-                       break;
-               case SEC_PRIV_NETWORK_LOGON:
-                       *(r->out.access_mask) |= LSA_POLICY_MODE_NETWORK;
-                       break;
-               case SEC_PRIV_REMOTE_INTERACTIVE_LOGON:
-                       *(r->out.access_mask) |= LSA_POLICY_MODE_REMOTE_INTERACTIVE;
-                       break;
+       el = ldb_msg_find_element(res[0], "privilege");
+       if (el == NULL || el->num_values == 0) {
+               return NT_STATUS_OK;
+       }
+
+       for (i=0;i<el->num_values;i++) {
+               uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
+               if (right_bit == 0) {
+                       /* Perhaps an privilege, not a right */
+                       continue;
                }
+               *(r->out.access_mask) |= right_bit;
        }
 
        return NT_STATUS_OK;
@@ -3495,7 +3507,7 @@ static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *d
        } 
 
        privname = r->in.name->string;
-       if (sec_privilege_id(privname) == SEC_PRIV_INVALID) {
+       if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
                return NT_STATUS_NO_SUCH_PRIVILEGE;
        }