summaryrefslogtreecommitdiffstats
path: root/source/rpc_server/srv_lsa_nt.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/rpc_server/srv_lsa_nt.c')
-rw-r--r--source/rpc_server/srv_lsa_nt.c492
1 files changed, 327 insertions, 165 deletions
diff --git a/source/rpc_server/srv_lsa_nt.c b/source/rpc_server/srv_lsa_nt.c
index fcd574971f7..13053d9877b 100644
--- a/source/rpc_server/srv_lsa_nt.c
+++ b/source/rpc_server/srv_lsa_nt.c
@@ -1,4 +1,4 @@
-/*
+/*
* Unix SMB/CIFS implementation.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
@@ -7,6 +7,7 @@
* Copyright (C) Jeremy Allison 2001,
* Copyright (C) Rafal Szczesniak 2002,
* Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002,
+ * Copyright (C) Simo Sorce 2003.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -411,9 +412,12 @@ NTSTATUS _lsa_open_policy2(pipes_struct *p, LSA_Q_OPEN_POL2 *q_u, LSA_R_OPEN_POL
DEBUG(4,("ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
acc_granted, des_access));
DEBUGADD(4,("but overwritten by euid == 0\n"));
- acc_granted = des_access;
}
+ /* This is needed for lsa_open_account and rpcclient .... :-) */
+
+ if (geteuid() == 0)
+ acc_granted = POLICY_ALL_ACCESS;
/* associate the domain SID with the (unique) handle. */
if ((info = SMB_MALLOC_P(struct lsa_info)) == NULL)
@@ -758,49 +762,56 @@ NTSTATUS _lsa_enum_privs(pipes_struct *p, LSA_Q_ENUM_PRIVS *q_u, LSA_R_ENUM_PRIV
{
struct lsa_info *handle;
uint32 i;
+ uint32 enum_context = q_u->enum_context;
+ int num_privs = count_all_privileges();
+ LSA_PRIV_ENTRY *entries = NULL;
+ LUID_ATTR luid;
- uint32 enum_context=q_u->enum_context;
- LSA_PRIV_ENTRY *entry;
- LSA_PRIV_ENTRY *entries=NULL;
+ /* remember that the enum_context starts at 0 and not 1 */
- if (enum_context >= PRIV_ALL_INDEX)
+ if ( enum_context >= num_privs )
return NT_STATUS_NO_MORE_ENTRIES;
-
- entries = TALLOC_ZERO_ARRAY(p->mem_ctx, LSA_PRIV_ENTRY, PRIV_ALL_INDEX);
- if (entries==NULL)
+
+ DEBUG(10,("_lsa_enum_privs: enum_context:%d total entries:%d\n",
+ enum_context, num_privs));
+
+ if ( !(entries = TALLOC_ZERO_ARRAY(p->mem_ctx, LSA_PRIV_ENTRY, num_privs + 1)))
return NT_STATUS_NO_MEMORY;
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
return NT_STATUS_INVALID_HANDLE;
- /* check if the user have enough rights */
+ /* check if the user have enough rights
+ I don't know if it's the right one. not documented. */
- /*
- * I don't know if it's the right one. not documented.
- */
if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
return NT_STATUS_ACCESS_DENIED;
- entry = entries;
-
- DEBUG(10,("_lsa_enum_privs: enum_context:%d total entries:%d\n", enum_context, PRIV_ALL_INDEX));
-
- for (i = 0; i < PRIV_ALL_INDEX; i++, entry++) {
- if( i<enum_context) {
- init_unistr2(&entry->name, NULL, UNI_FLAGS_NONE);
- init_uni_hdr(&entry->hdr_name, &entry->name);
- entry->luid_low = 0;
- entry->luid_high = 0;
+ if ( !(entries = TALLOC_ZERO_ARRAY(p->mem_ctx, LSA_PRIV_ENTRY, num_privs )) )
+ return NT_STATUS_NO_MEMORY;
+
+
+ for (i = 0; i < num_privs; i++) {
+ 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(&entry->name, privs[i+1].priv, UNI_FLAGS_NONE);
- init_uni_hdr(&entry->hdr_name, &entry->name);
- entry->luid_low = privs[i+1].se_priv;
- entry->luid_high = 0;
+ init_unistr2(&entries[i].name, privs[i].name, UNI_FLAGS_NONE);
+ init_uni_hdr(&entries[i].hdr_name, &entries[i].name);
+
+ luid = get_privilege_luid( &privs[i].se_priv );
+
+ entries[i].luid_low = luid.luid.low;
+ entries[i].luid_high = luid.luid.high;
}
}
- enum_context = PRIV_ALL_INDEX;
- init_lsa_r_enum_privs(r_u, enum_context, PRIV_ALL_INDEX, entries);
+ enum_context = num_privs;
+
+ init_lsa_r_enum_privs(r_u, enum_context, num_privs, entries);
return NT_STATUS_OK;
}
@@ -813,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=1;
+ const char *description;
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
return NT_STATUS_INVALID_HANDLE;
@@ -828,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", name_asc));
+ DEBUG(10,("_lsa_priv_get_dispname: name = %s\n", name_asc));
- while (privs[i].se_priv!=SE_PRIV_ALL && strcmp(name_asc, privs[i].priv))
- i++;
+ description = get_privilege_dispname( name_asc );
- if (privs[i].se_priv!=SE_PRIV_ALL) {
- 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;
+ 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;
+
+ r_u->ptr_info = 0;
+
return NT_STATUS_NO_SUCH_PRIVILEGE;
}
}
@@ -855,32 +869,26 @@ _lsa_enum_accounts.
NTSTATUS _lsa_enum_accounts(pipes_struct *p, LSA_Q_ENUM_ACCOUNTS *q_u, LSA_R_ENUM_ACCOUNTS *r_u)
{
struct lsa_info *handle;
- GROUP_MAP *map=NULL;
- int num_entries=0;
+ DOM_SID *sid_list;
+ int i, j, num_entries;
LSA_SID_ENUM *sids=&r_u->sids;
- int i=0,j=0;
- BOOL ret;
+ NTSTATUS ret;
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
return NT_STATUS_INVALID_HANDLE;
- /* check if the user have enough rights */
-
- /*
- * I don't know if it's the right one. not documented.
- */
if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
return NT_STATUS_ACCESS_DENIED;
- /* get the list of mapped groups (domain, local, builtin) */
- become_root();
- ret = pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries, ENUM_ONLY_MAPPED);
- unbecome_root();
- if( !ret ) {
- DEBUG(3,("_lsa_enum_accounts: enumeration of groups failed!\n"));
- return NT_STATUS_OK;
+ sid_list = NULL;
+ num_entries = 0;
+
+ /* The only way we can currently find out all the SIDs that have been
+ privileged is to scan all privileges */
+
+ if (!NT_STATUS_IS_OK(ret = privilege_enumerate_accounts(&sid_list, &num_entries))) {
+ return ret;
}
-
if (q_u->enum_context >= num_entries)
return NT_STATUS_NO_MORE_ENTRIES;
@@ -889,19 +897,18 @@ NTSTATUS _lsa_enum_accounts(pipes_struct *p, LSA_Q_ENUM_ACCOUNTS *q_u, LSA_R_ENU
sids->sid = TALLOC_ZERO_ARRAY(p->mem_ctx, DOM_SID2, num_entries-q_u->enum_context);
if (sids->ptr_sid==NULL || sids->sid==NULL) {
- SAFE_FREE(map);
+ SAFE_FREE(sid_list);
return NT_STATUS_NO_MEMORY;
}
- for (i=q_u->enum_context, j=0; i<num_entries; i++) {
- init_dom_sid2( &(*sids).sid[j], &map[i].sid);
- (*sids).ptr_sid[j]=1;
- j++;
+ for (i = q_u->enum_context, j = 0; i < num_entries; i++, j++) {
+ init_dom_sid2(&(*sids).sid[j], &sid_list[i]);
+ (*sids).ptr_sid[j] = 1;
}
- SAFE_FREE(map);
+ SAFE_FREE(sid_list);
- init_lsa_r_enum_accounts(r_u, j);
+ init_lsa_r_enum_accounts(r_u, num_entries);
return NT_STATUS_OK;
}
@@ -934,15 +941,61 @@ NTSTATUS _lsa_unk_get_connuser(pipes_struct *p, LSA_Q_UNK_GET_CONNUSER *q_u, LSA
}
/***************************************************************************
-
+ Lsa Create Account
***************************************************************************/
-NTSTATUS _lsa_open_account(pipes_struct *p, LSA_Q_OPENACCOUNT *q_u, LSA_R_OPENACCOUNT *r_u)
+NTSTATUS _lsa_create_account(pipes_struct *p, LSA_Q_CREATEACCOUNT *q_u, LSA_R_CREATEACCOUNT *r_u)
{
struct lsa_info *handle;
struct lsa_info *info;
- r_u->status = NT_STATUS_OK;
+ /* find the connection policy handle. */
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
+ return NT_STATUS_INVALID_HANDLE;
+
+ /* check if the user have enough rights */
+
+ /*
+ * I don't know if it's the right one. not documented.
+ * but guessed with rpcclient.
+ */
+ if (!(handle->access & POLICY_GET_PRIVATE_INFORMATION))
+ return NT_STATUS_ACCESS_DENIED;
+
+ /* check to see if the pipe_user is a Domain Admin since
+ account_pol.tdb was already opened as root, this is all we have */
+
+ if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
+ return NT_STATUS_ACCESS_DENIED;
+
+ if ( is_privileged_sid( &info->sid ) )
+ return NT_STATUS_OBJECT_NAME_COLLISION;
+
+ /* associate the user/group SID with the (unique) handle. */
+
+ if ((info = SMB_MALLOC_P(struct lsa_info)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ ZERO_STRUCTP(info);
+ info->sid = q_u->sid.sid;
+ info->access = q_u->access;
+
+ /* get a (unique) handle. open a policy on it. */
+ if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info))
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+
+ return privilege_create_account( &info->sid );
+}
+
+
+/***************************************************************************
+ Lsa Open Account
+ ***************************************************************************/
+
+NTSTATUS _lsa_open_account(pipes_struct *p, LSA_Q_OPENACCOUNT *q_u, LSA_R_OPENACCOUNT *r_u)
+{
+ struct lsa_info *handle;
+ struct lsa_info *info;
/* find the connection policy handle. */
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
@@ -957,6 +1010,11 @@ NTSTATUS _lsa_open_account(pipes_struct *p, LSA_Q_OPENACCOUNT *q_u, LSA_R_OPENAC
if (!(handle->access & POLICY_GET_PRIVATE_INFORMATION))
return NT_STATUS_ACCESS_DENIED;
+ /* TODO: Fis the parsing routine before reenabling this check! */
+ #if 0
+ if (!lookup_sid(&handle->sid, dom_name, name, &type))
+ return NT_STATUS_ACCESS_DENIED;
+ #endif
/* associate the user/group SID with the (unique) handle. */
if ((info = SMB_MALLOC_P(struct lsa_info)) == NULL)
return NT_STATUS_NO_MEMORY;
@@ -969,7 +1027,7 @@ NTSTATUS _lsa_open_account(pipes_struct *p, LSA_Q_OPENACCOUNT *q_u, LSA_R_OPENAC
if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info))
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- return r_u->status;
+ return NT_STATUS_OK;
}
/***************************************************************************
@@ -979,42 +1037,29 @@ 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;
- GROUP_MAP map;
- LUID_ATTR *set=NULL;
-
- r_u->status = NT_STATUS_OK;
+ 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;
- if (!pdb_getgrsid(&map, info->sid))
- return NT_STATUS_NO_SUCH_GROUP;
+ if ( !get_privileges_for_sids( &mask, &info->sid, 1 ) )
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-#if 0 /* privileges currently not implemented! */
- DEBUG(10,("_lsa_enum_privsaccount: %d privileges\n", map.priv_set->count));
- if (map.priv_set->count!=0) {
-
- set=(LUID_ATTR *)talloc(map.priv_set->mem_ctx, map.priv_set.count*sizeof(LUID_ATTR));
- if (set == NULL) {
- destroy_privilege(&map.priv_set);
- return NT_STATUS_NO_MEMORY;
- }
+ privilege_set_init( &privileges );
- for (i = 0; i < map.priv_set.count; i++) {
- set[i].luid.low = map.priv_set->set[i].luid.low;
- set[i].luid.high = map.priv_set->set[i].luid.high;
- set[i].attr = map.priv_set->set[i].attr;
- DEBUG(10,("_lsa_enum_privsaccount: priv %d: %d:%d:%d\n", i,
- set[i].luid.high, set[i].luid.low, set[i].attr));
- }
- }
+ if ( se_priv_to_privilege_set( &privileges, &mask ) ) {
- init_lsa_r_enum_privsaccount(ps->mem_ctx, r_u, set, map.priv_set->count, 0);
- destroy_privilege(&map.priv_set);
-#endif
+ DEBUG(10,("_lsa_enum_privsaccount: %s has %d privileges\n",
+ sid_string_static(&info->sid), privileges.count));
- init_lsa_r_enum_privsaccount(ps->mem_ctx, r_u, set, 0, 0);
+ 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;
+
+ privilege_set_free( &privileges );
return r_u->status;
}
@@ -1026,15 +1071,16 @@ NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, prs_struct *ps, LSA_Q_ENUMPRIVS
NTSTATUS _lsa_getsystemaccount(pipes_struct *p, LSA_Q_GETSYSTEMACCOUNT *q_u, LSA_R_GETSYSTEMACCOUNT *r_u)
{
struct lsa_info *info=NULL;
- GROUP_MAP map;
- r_u->status = NT_STATUS_OK;
+ fstring name, dom_name;
+ enum SID_NAME_USE type;
/* find the connection policy handle. */
+
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
- if (!pdb_getgrsid(&map, info->sid))
- return NT_STATUS_NO_SUCH_GROUP;
+ if (!lookup_sid(&info->sid, dom_name, name, &type))
+ return NT_STATUS_ACCESS_DENIED;
/*
0x01 -> Log on locally
@@ -1047,7 +1093,7 @@ NTSTATUS _lsa_getsystemaccount(pipes_struct *p, LSA_Q_GETSYSTEMACCOUNT *q_u, LSA
r_u->access = PR_LOG_ON_LOCALLY | PR_ACCESS_FROM_NETWORK;
- return r_u->status;
+ return NT_STATUS_OK;
}
/***************************************************************************
@@ -1064,6 +1110,12 @@ NTSTATUS _lsa_setsystemaccount(pipes_struct *p, LSA_Q_SETSYSTEMACCOUNT *q_u, LSA
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
+ /* check to see if the pipe_user is a Domain Admin since
+ account_pol.tdb was already opened as root, this is all we have */
+
+ if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
+ return NT_STATUS_ACCESS_DENIED;
+
if (!pdb_getgrsid(&map, info->sid))
return NT_STATUS_NO_SUCH_GROUP;
@@ -1079,44 +1131,34 @@ 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)
{
-#if 0
struct lsa_info *info = NULL;
- GROUP_MAP map;
- int i = 0;
- LUID_ATTR *luid_attr = NULL;
+ SE_PRIV mask;
PRIVILEGE_SET *set = NULL;
-#endif
- r_u->status = NT_STATUS_OK;
-
-#if 0 /* privileges are not implemented */
/* find the connection policy handle. */
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
-
- if (!pdb_getgrsid(&map, info->sid))
- return NT_STATUS_NO_SUCH_GROUP;
+
+ /* check to see if the pipe_user is a Domain Admin since
+ account_pol.tdb was already opened as root, this is all we have */
+
+ if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
+ return NT_STATUS_ACCESS_DENIED;
set = &q_u->set;
- for (i = 0; i < set->count; i++) {
- luid_attr = &set->set[i];
-
- /* check if the privilege is already there */
- if (check_priv_in_privilege(map.priv_set, *luid_attr)){
- destroy_privilege(&map.priv_set);
- }
-
- add_privilege(map.priv_set, *luid_attr);
- }
+ if ( !privilege_set_to_se_priv( &mask, set ) )
+ return NT_STATUS_NO_SUCH_PRIVILEGE;
- if(!pdb_update_group_mapping_entry(&map))
- return NT_STATUS_NO_SUCH_GROUP;
-
- destroy_privilege(&map.priv_set);
+ 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;
+ }
-#endif
- return r_u->status;
+ return NT_STATUS_OK;
}
/***************************************************************************
@@ -1125,57 +1167,34 @@ 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)
{
-#if 0
struct lsa_info *info = NULL;
- GROUP_MAP map;
- int i=0;
- LUID_ATTR *luid_attr = NULL;
+ SE_PRIV mask;
PRIVILEGE_SET *set = NULL;
-#endif
-
- r_u->status = NT_STATUS_OK;
-#if 0 /* privileges are not implemented */
/* find the connection policy handle. */
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
- if (!pdb_getgrsid(&map, info->sid))
- return NT_STATUS_NO_SUCH_GROUP;
-
- if (q_u->allrights != 0) {
- /* log it and return, until I see one myself don't do anything */
- DEBUG(5,("_lsa_removeprivs: trying to remove all privileges ?\n"));
- return NT_STATUS_OK;
- }
-
- if (q_u->ptr == 0) {
- /* log it and return, until I see one myself don't do anything */
- DEBUG(5,("_lsa_removeprivs: no privileges to remove ?\n"));
- return NT_STATUS_OK;
- }
+ /* check to see if the pipe_user is a Domain Admin since
+ account_pol.tdb was already opened as root, this is all we have */
+
+ if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
+ return NT_STATUS_ACCESS_DENIED;
set = &q_u->set;
- for (i = 0; i < set->count; i++) {
- luid_attr = &set->set[i];
-
- /* if we don't have the privilege, we're trying to remove, give up */
- /* what else can we do ??? JFM. */
- if (!check_priv_in_privilege(map.priv_set, *luid_attr)){
- destroy_privilege(&map.priv_set);
- return NT_STATUS_NO_SUCH_PRIVILEGE;
- }
-
- remove_privilege(map.priv_set, *luid_attr);
+ if ( !privilege_set_to_se_priv( &mask, set ) )
+ 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;
}
- if(!pdb_update_group_mapping_entry(&map))
- return NT_STATUS_NO_SUCH_GROUP;
-
- destroy_privilege(&map.priv_set);
-#endif
- return r_u->status;
+ return NT_STATUS_OK;
}
/***************************************************************************
@@ -1231,6 +1250,8 @@ NTSTATUS _lsa_query_secobj(pipes_struct *p, LSA_Q_QUERY_SEC_OBJ *q_u, LSA_R_QUER
return r_u->status;
}
+/***************************************************************************
+ ***************************************************************************/
NTSTATUS _lsa_query_info2(pipes_struct *p, LSA_Q_QUERY_INFO2 *q_u, LSA_R_QUERY_INFO2 *r_u)
{
@@ -1291,3 +1312,144 @@ NTSTATUS _lsa_query_info2(pipes_struct *p, LSA_Q_QUERY_INFO2 *q_u, LSA_R_QUERY_I
return r_u->status;
}
+
+/***************************************************************************
+ ***************************************************************************/
+
+NTSTATUS _lsa_add_acct_rights(pipes_struct *p, LSA_Q_ADD_ACCT_RIGHTS *q_u, LSA_R_ADD_ACCT_RIGHTS *r_u)
+{
+ struct lsa_info *info = NULL;
+ int i = 0;
+ DOM_SID sid;
+ fstring privname;
+ UNISTR2_ARRAY *uni_privnames = &q_u->rights;
+
+
+ /* find the connection policy handle. */
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
+ return NT_STATUS_INVALID_HANDLE;
+
+ /* check to see if the pipe_user is a Domain Admin since
+ account_pol.tdb was already opened as root, this is all we have */
+
+ if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
+ return NT_STATUS_ACCESS_DENIED;
+
+ /* according to an NT4 PDC, you can add privileges to SIDs even without
+ call_lsa_create_account() first. And you can use any arbitrary SID. */
+
+ sid_copy( &sid, &q_u->sid.sid );
+
+ /* just a little sanity check */
+
+ if ( q_u->count != uni_privnames->count ) {
+ DEBUG(0,("_lsa_add_acct_rights: count != number of UNISTR2 elements!\n"));
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ for ( i=0; i<q_u->count; i++ ) {
+ unistr2_to_ascii( privname, &uni_privnames->strings[i].string, sizeof(fstring)-1 );
+
+ /* only try to add non-null strings */
+
+ if ( *privname && !grant_privilege_by_name( &sid, privname ) ) {
+ DEBUG(2,("_lsa_add_acct_rights: Failed to add privilege [%s]\n", privname ));
+ return NT_STATUS_NO_SUCH_PRIVILEGE;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+
+NTSTATUS _lsa_remove_acct_rights(pipes_struct *p, LSA_Q_REMOVE_ACCT_RIGHTS *q_u, LSA_R_REMOVE_ACCT_RIGHTS *r_u)
+{
+ struct lsa_info *info = NULL;
+ int i = 0;
+ DOM_SID sid;
+ fstring privname;
+ UNISTR2_ARRAY *uni_privnames = &q_u->rights;
+
+
+ /* find the connection policy handle. */
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
+ return NT_STATUS_INVALID_HANDLE;
+
+ /* check to see if the pipe_user is a Domain Admin since
+ account_pol.tdb was already opened as root, this is all we have */
+
+ if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
+ return NT_STATUS_ACCESS_DENIED;
+
+ sid_copy( &sid, &q_u->sid.sid );
+
+ if ( q_u->removeall ) {
+ if ( !revoke_all_privileges( &sid ) )
+ return NT_STATUS_ACCESS_DENIED;
+
+ return NT_STATUS_OK;
+ }
+
+ /* just a little sanity check */
+
+ if ( q_u->count != uni_privnames->count ) {
+ DEBUG(0,("_lsa_add_acct_rights: count != number of UNISTR2 elements!\n"));
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ for ( i=0; i<q_u->count; i++ ) {
+ unistr2_to_ascii( privname, &uni_privnames->strings[i].string, sizeof(fstring)-1 );
+
+ /* only try to add non-null strings */
+
+ if ( *privname && !revoke_privilege_by_name( &sid, privname ) ) {
+ DEBUG(2,("_lsa_remove_acct_rights: Failed to revoke privilege [%s]\n", privname ));
+ return NT_STATUS_NO_SUCH_PRIVILEGE;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+NTSTATUS _lsa_enum_acct_rights(pipes_struct *p, LSA_Q_ENUM_ACCT_RIGHTS *q_u, LSA_R_ENUM_ACCT_RIGHTS *r_u)
+{
+ struct lsa_info *info = NULL;
+ DOM_SID sid;
+ PRIVILEGE_SET privileges;
+ SE_PRIV mask;
+
+
+ /* find the connection policy handle. */
+
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
+ return NT_STATUS_INVALID_HANDLE;
+
+ /* according to an NT4 PDC, you can add privileges to SIDs even without
+ call_lsa_create_account() first. And you can use any arbitrary SID. */
+
+ 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 );
+
+ 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 );
+ }
+ else
+ r_u->status = NT_STATUS_NO_SUCH_PRIVILEGE;
+
+ privilege_set_free( &privileges );
+
+ return r_u->status;
+}
+
+