{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,
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"}
};
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
*/
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",
}
}
}
+ 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));
+ }
+ }
+ }
}
*/
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
*/
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);
/* 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,
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 */
/* 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;
* 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 */
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,
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
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);
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;
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;
}
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;
}
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;
}
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;
}