diff options
Diffstat (limited to 'source/rpc_server/srv_lsa_nt.c')
-rw-r--r-- | source/rpc_server/srv_lsa_nt.c | 492 |
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; +} + + |