From 0eea8ecfe262e515011e7637c5a574f23923f169 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 11 Sep 2010 16:58:45 +1000 Subject: s4-privs Seperate rights and privileges 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 | 65 +++++++++++++++++++++------ libcli/security/privileges.h | 9 ++++ librpc/idl/lsa.idl | 16 ------- librpc/idl/security.idl | 35 +++++++++------ source4/dsdb/samdb/samdb_privilege.c | 8 +++- source4/rpc_server/lsa/dcesrv_lsa.c | 86 ++++++++++++++++++++---------------- 6 files changed, 137 insertions(+), 82 deletions(-) diff --git a/libcli/security/privileges.c b/libcli/security/privileges.c index 466bea0565..1fecf4011d 100644 --- a/libcli/security/privileges.c +++ b/libcli/security/privileges.c @@ -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;iprivilege_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; idxrights_mask & rights[idx].right_mask) { + DEBUGADD(dbg_lev, (" Right[%3lu]: %s\n", (unsigned long)i++, + rights[idx].name)); + } + } + } } diff --git a/libcli/security/privileges.h b/libcli/security/privileges.h index 25895fd1ff..f67a38bc27 100644 --- a/libcli/security/privileges.h +++ b/libcli/security/privileges.h @@ -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); diff --git a/librpc/idl/lsa.idl b/librpc/idl/lsa.idl index e9c65045d9..343d21da07 100644 --- a/librpc/idl/lsa.idl +++ b/librpc/idl/lsa.idl @@ -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, diff --git a/librpc/idl/security.idl b/librpc/idl/security.idl index 4f5245b2e4..13ccb49537 100644 --- a/librpc/idl/security.idl +++ b/librpc/idl/security.idl @@ -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 diff --git a/source4/dsdb/samdb/samdb_privilege.c b/source4/dsdb/samdb/samdb_privilege.c index 6186097d78..69c4ebea61 100644 --- a/source4/dsdb/samdb/samdb_privilege.c +++ b/source4/dsdb/samdb/samdb_privilege.c @@ -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); diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c index 675aa178a7..81ad6f7a92 100644 --- a/source4/rpc_server/lsa/dcesrv_lsa.c +++ b/source4/rpc_server/lsa/dcesrv_lsa.c @@ -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;inum_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;icount;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;inum_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; } -- cgit