From 4063bde3edd15b241f2b93bb5aedfef57ec4df91 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 8 Feb 2011 14:17:14 +0100 Subject: s3-rpc_server: move services into individual directories. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Autobuild-User: Günther Deschner Autobuild-Date: Thu Feb 10 22:13:17 CET 2011 on sn-devel-104 --- source3/rpc_server/srv_samr_nt.c | 6969 -------------------------------------- 1 file changed, 6969 deletions(-) delete mode 100644 source3/rpc_server/srv_samr_nt.c (limited to 'source3/rpc_server/srv_samr_nt.c') diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c deleted file mode 100644 index 4e6d94d957..0000000000 --- a/source3/rpc_server/srv_samr_nt.c +++ /dev/null @@ -1,6969 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Andrew Tridgell 1992-1997, - * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, - * Copyright (C) Paul Ashton 1997, - * Copyright (C) Marc Jacobsen 1999, - * Copyright (C) Jeremy Allison 2001-2008, - * Copyright (C) Jean François Micouleau 1998-2001, - * Copyright (C) Jim McDonough 2002, - * Copyright (C) Gerald (Jerry) Carter 2003-2004, - * Copyright (C) Simo Sorce 2003. - * Copyright (C) Volker Lendecke 2005. - * Copyright (C) Guenther Deschner 2008. - * - * 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 - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -/* - * This is the implementation of the SAMR code. - */ - -#include "includes.h" -#include "smbd/globals.h" -#include "../libcli/auth/libcli_auth.h" -#include "../librpc/gen_ndr/srv_samr.h" -#include "rpc_server/srv_samr_util.h" -#include "../lib/crypto/arcfour.h" -#include "secrets.h" -#include "rpc_client/init_lsa.h" -#include "../libcli/security/security.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_RPC_SRV - -#define SAMR_USR_RIGHTS_WRITE_PW \ - ( READ_CONTROL_ACCESS | \ - SAMR_USER_ACCESS_CHANGE_PASSWORD | \ - SAMR_USER_ACCESS_SET_LOC_COM) -#define SAMR_USR_RIGHTS_CANT_WRITE_PW \ - ( READ_CONTROL_ACCESS | SAMR_USER_ACCESS_SET_LOC_COM ) - -#define DISP_INFO_CACHE_TIMEOUT 10 - -#define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */ -#define MAX_SAM_ENTRIES_W95 50 - -struct samr_connect_info { - uint8_t dummy; -}; - -struct samr_domain_info { - struct dom_sid sid; - struct disp_info *disp_info; -}; - -struct samr_user_info { - struct dom_sid sid; -}; - -struct samr_group_info { - struct dom_sid sid; -}; - -struct samr_alias_info { - struct dom_sid sid; -}; - -typedef struct disp_info { - struct dom_sid sid; /* identify which domain this is. */ - struct pdb_search *users; /* querydispinfo 1 and 4 */ - struct pdb_search *machines; /* querydispinfo 2 */ - struct pdb_search *groups; /* querydispinfo 3 and 5, enumgroups */ - struct pdb_search *aliases; /* enumaliases */ - - uint32_t enum_acb_mask; - struct pdb_search *enum_users; /* enumusers with a mask */ - - struct timed_event *cache_timeout_event; /* cache idle timeout - * handler. */ -} DISP_INFO; - -static const struct generic_mapping sam_generic_mapping = { - GENERIC_RIGHTS_SAM_READ, - GENERIC_RIGHTS_SAM_WRITE, - GENERIC_RIGHTS_SAM_EXECUTE, - GENERIC_RIGHTS_SAM_ALL_ACCESS}; -static const struct generic_mapping dom_generic_mapping = { - GENERIC_RIGHTS_DOMAIN_READ, - GENERIC_RIGHTS_DOMAIN_WRITE, - GENERIC_RIGHTS_DOMAIN_EXECUTE, - GENERIC_RIGHTS_DOMAIN_ALL_ACCESS}; -static const struct generic_mapping usr_generic_mapping = { - GENERIC_RIGHTS_USER_READ, - GENERIC_RIGHTS_USER_WRITE, - GENERIC_RIGHTS_USER_EXECUTE, - GENERIC_RIGHTS_USER_ALL_ACCESS}; -static const struct generic_mapping usr_nopwchange_generic_mapping = { - GENERIC_RIGHTS_USER_READ, - GENERIC_RIGHTS_USER_WRITE, - GENERIC_RIGHTS_USER_EXECUTE & ~SAMR_USER_ACCESS_CHANGE_PASSWORD, - GENERIC_RIGHTS_USER_ALL_ACCESS}; -static const struct generic_mapping grp_generic_mapping = { - GENERIC_RIGHTS_GROUP_READ, - GENERIC_RIGHTS_GROUP_WRITE, - GENERIC_RIGHTS_GROUP_EXECUTE, - GENERIC_RIGHTS_GROUP_ALL_ACCESS}; -static const struct generic_mapping ali_generic_mapping = { - GENERIC_RIGHTS_ALIAS_READ, - GENERIC_RIGHTS_ALIAS_WRITE, - GENERIC_RIGHTS_ALIAS_EXECUTE, - GENERIC_RIGHTS_ALIAS_ALL_ACCESS}; - -/******************************************************************* -*******************************************************************/ - -static NTSTATUS make_samr_object_sd( TALLOC_CTX *ctx, struct security_descriptor **psd, size_t *sd_size, - const struct generic_mapping *map, - struct dom_sid *sid, uint32 sid_access ) -{ - struct dom_sid domadmin_sid; - struct security_ace ace[5]; /* at most 5 entries */ - size_t i = 0; - - struct security_acl *psa = NULL; - - /* basic access for Everyone */ - - init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, - map->generic_execute | map->generic_read, 0); - - /* add Full Access 'BUILTIN\Administrators' and 'BUILTIN\Account Operators */ - - init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, - SEC_ACE_TYPE_ACCESS_ALLOWED, map->generic_all, 0); - init_sec_ace(&ace[i++], &global_sid_Builtin_Account_Operators, - SEC_ACE_TYPE_ACCESS_ALLOWED, map->generic_all, 0); - - /* Add Full Access for Domain Admins if we are a DC */ - - if ( IS_DC ) { - sid_compose(&domadmin_sid, get_global_sam_sid(), - DOMAIN_RID_ADMINS); - init_sec_ace(&ace[i++], &domadmin_sid, - SEC_ACE_TYPE_ACCESS_ALLOWED, map->generic_all, 0); - } - - /* if we have a sid, give it some special access */ - - if ( sid ) { - init_sec_ace(&ace[i++], sid, SEC_ACE_TYPE_ACCESS_ALLOWED, sid_access, 0); - } - - /* create the security descriptor */ - - if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) == NULL) - return NT_STATUS_NO_MEMORY; - - if ((*psd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1, - SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, - psa, sd_size)) == NULL) - return NT_STATUS_NO_MEMORY; - - return NT_STATUS_OK; -} - -/******************************************************************* - Checks if access to an object should be granted, and returns that - level of access for further checks. - - If the user has either of needed_priv_1 or needed_priv_2 then they - get the rights in rights_mask in addition to any calulated rights. - - This handles the unusual case where we need to allow two different - privileges to obtain exactly the same rights, which occours only in - SAMR. -********************************************************************/ - -NTSTATUS access_check_object( struct security_descriptor *psd, struct security_token *token, - enum sec_privilege needed_priv_1, enum sec_privilege needed_priv_2, - uint32 rights_mask, - uint32 des_access, uint32 *acc_granted, - const char *debug ) -{ - NTSTATUS status = NT_STATUS_ACCESS_DENIED; - uint32 saved_mask = 0; - - /* check privileges; certain SAM access bits should be overridden - by privileges (mostly having to do with creating/modifying/deleting - users and groups) */ - - if ((needed_priv_1 != SEC_PRIV_INVALID && security_token_has_privilege(token, needed_priv_1)) || - (needed_priv_2 != SEC_PRIV_INVALID && security_token_has_privilege(token, needed_priv_2))) { - saved_mask = (des_access & rights_mask); - des_access &= ~saved_mask; - - DEBUG(4,("access_check_object: user rights access mask [0x%x]\n", - rights_mask)); - } - - - /* check the security descriptor first */ - - status = se_access_check(psd, token, des_access, acc_granted); - if (NT_STATUS_IS_OK(status)) { - goto done; - } - - /* give root a free pass */ - - if ( geteuid() == sec_initial_uid() ) { - - DEBUG(4,("%s: ACCESS should be DENIED (requested: %#010x)\n", debug, des_access)); - DEBUGADD(4,("but overritten by euid == sec_initial_uid()\n")); - - *acc_granted = des_access; - - status = NT_STATUS_OK; - goto done; - } - - -done: - /* add in any bits saved during the privilege check (only - matters is status is ok) */ - - *acc_granted |= rights_mask; - - DEBUG(4,("%s: access %s (requested: 0x%08x, granted: 0x%08x)\n", - debug, NT_STATUS_IS_OK(status) ? "GRANTED" : "DENIED", - des_access, *acc_granted)); - - return status; -} - - -/******************************************************************* - Map any MAXIMUM_ALLOWED_ACCESS request to a valid access set. -********************************************************************/ - -void map_max_allowed_access(const struct security_token *nt_token, - const struct unix_user_token *unix_token, - uint32_t *pacc_requested) -{ - if (!((*pacc_requested) & MAXIMUM_ALLOWED_ACCESS)) { - return; - } - *pacc_requested &= ~MAXIMUM_ALLOWED_ACCESS; - - /* At least try for generic read|execute - Everyone gets that. */ - *pacc_requested = GENERIC_READ_ACCESS|GENERIC_EXECUTE_ACCESS; - - /* root gets anything. */ - if (unix_token->uid == sec_initial_uid()) { - *pacc_requested |= GENERIC_ALL_ACCESS; - return; - } - - /* Full Access for 'BUILTIN\Administrators' and 'BUILTIN\Account Operators */ - - if (security_token_has_sid(nt_token, &global_sid_Builtin_Administrators) || - security_token_has_sid(nt_token, &global_sid_Builtin_Account_Operators)) { - *pacc_requested |= GENERIC_ALL_ACCESS; - return; - } - - /* Full access for DOMAIN\Domain Admins. */ - if ( IS_DC ) { - struct dom_sid domadmin_sid; - sid_compose(&domadmin_sid, get_global_sam_sid(), - DOMAIN_RID_ADMINS); - if (security_token_has_sid(nt_token, &domadmin_sid)) { - *pacc_requested |= GENERIC_ALL_ACCESS; - return; - } - } - /* TODO ! Check privileges. */ -} - -/******************************************************************* - Fetch or create a dispinfo struct. -********************************************************************/ - -static DISP_INFO *get_samr_dispinfo_by_sid(const struct dom_sid *psid) -{ - /* - * We do a static cache for DISP_INFO's here. Explanation can be found - * in Jeremy's checkin message to r11793: - * - * Fix the SAMR cache so it works across completely insane - * client behaviour (ie.: - * open pipe/open SAMR handle/enumerate 0 - 1024 - * close SAMR handle, close pipe. - * open pipe/open SAMR handle/enumerate 1024 - 2048... - * close SAMR handle, close pipe. - * And on ad-nausium. Amazing.... probably object-oriented - * client side programming in action yet again. - * This change should *massively* improve performance when - * enumerating users from an LDAP database. - * Jeremy. - * - * "Our" and the builtin domain are the only ones where we ever - * enumerate stuff, so just cache 2 entries. - */ - - static struct disp_info *builtin_dispinfo; - static struct disp_info *domain_dispinfo; - - /* There are two cases to consider here: - 1) The SID is a domain SID and we look for an equality match, or - 2) This is an account SID and so we return the DISP_INFO* for our - domain */ - - if (psid == NULL) { - return NULL; - } - - if (sid_check_is_builtin(psid) || sid_check_is_in_builtin(psid)) { - /* - * Necessary only once, but it does not really hurt. - */ - if (builtin_dispinfo == NULL) { - builtin_dispinfo = talloc_zero(NULL, struct disp_info); - if (builtin_dispinfo == NULL) { - return NULL; - } - } - sid_copy(&builtin_dispinfo->sid, &global_sid_Builtin); - - return builtin_dispinfo; - } - - if (sid_check_is_domain(psid) || sid_check_is_in_our_domain(psid)) { - /* - * Necessary only once, but it does not really hurt. - */ - if (domain_dispinfo == NULL) { - domain_dispinfo = talloc_zero(NULL, struct disp_info); - if (domain_dispinfo == NULL) { - return NULL; - } - } - sid_copy(&domain_dispinfo->sid, get_global_sam_sid()); - - return domain_dispinfo; - } - - return NULL; -} - -/******************************************************************* - Function to free the per SID data. - ********************************************************************/ - -static void free_samr_cache(DISP_INFO *disp_info) -{ - DEBUG(10, ("free_samr_cache: deleting cache for SID %s\n", - sid_string_dbg(&disp_info->sid))); - - /* We need to become root here because the paged search might have to - * tell the LDAP server we're not interested in the rest anymore. */ - - become_root(); - - TALLOC_FREE(disp_info->users); - TALLOC_FREE(disp_info->machines); - TALLOC_FREE(disp_info->groups); - TALLOC_FREE(disp_info->aliases); - TALLOC_FREE(disp_info->enum_users); - - unbecome_root(); -} - -/******************************************************************* - Idle event handler. Throw away the disp info cache. - ********************************************************************/ - -static void disp_info_cache_idle_timeout_handler(struct event_context *ev_ctx, - struct timed_event *te, - struct timeval now, - void *private_data) -{ - DISP_INFO *disp_info = (DISP_INFO *)private_data; - - TALLOC_FREE(disp_info->cache_timeout_event); - - DEBUG(10, ("disp_info_cache_idle_timeout_handler: caching timed " - "out\n")); - free_samr_cache(disp_info); -} - -/******************************************************************* - Setup cache removal idle event handler. - ********************************************************************/ - -static void set_disp_info_cache_timeout(DISP_INFO *disp_info, time_t secs_fromnow) -{ - /* Remove any pending timeout and update. */ - - TALLOC_FREE(disp_info->cache_timeout_event); - - DEBUG(10,("set_disp_info_cache_timeout: caching enumeration for " - "SID %s for %u seconds\n", sid_string_dbg(&disp_info->sid), - (unsigned int)secs_fromnow )); - - disp_info->cache_timeout_event = event_add_timed( - server_event_context(), NULL, - timeval_current_ofs(secs_fromnow, 0), - disp_info_cache_idle_timeout_handler, (void *)disp_info); -} - -/******************************************************************* - Force flush any cache. We do this on any samr_set_xxx call. - We must also remove the timeout handler. - ********************************************************************/ - -static void force_flush_samr_cache(const struct dom_sid *sid) -{ - struct disp_info *disp_info = get_samr_dispinfo_by_sid(sid); - - if ((disp_info == NULL) || (disp_info->cache_timeout_event == NULL)) { - return; - } - - DEBUG(10,("force_flush_samr_cache: clearing idle event\n")); - TALLOC_FREE(disp_info->cache_timeout_event); - free_samr_cache(disp_info); -} - -/******************************************************************* - Ensure password info is never given out. Paranioa... JRA. - ********************************************************************/ - -static void samr_clear_sam_passwd(struct samu *sam_pass) -{ - - if (!sam_pass) - return; - - /* These now zero out the old password */ - - pdb_set_lanman_passwd(sam_pass, NULL, PDB_DEFAULT); - pdb_set_nt_passwd(sam_pass, NULL, PDB_DEFAULT); -} - -static uint32 count_sam_users(struct disp_info *info, uint32 acct_flags) -{ - struct samr_displayentry *entry; - - if (sid_check_is_builtin(&info->sid)) { - /* No users in builtin. */ - return 0; - } - - if (info->users == NULL) { - info->users = pdb_search_users(info, acct_flags); - if (info->users == NULL) { - return 0; - } - } - /* Fetch the last possible entry, thus trigger an enumeration */ - pdb_search_entries(info->users, 0xffffffff, 1, &entry); - - /* Ensure we cache this enumeration. */ - set_disp_info_cache_timeout(info, DISP_INFO_CACHE_TIMEOUT); - - return info->users->num_entries; -} - -static uint32 count_sam_groups(struct disp_info *info) -{ - struct samr_displayentry *entry; - - if (sid_check_is_builtin(&info->sid)) { - /* No groups in builtin. */ - return 0; - } - - if (info->groups == NULL) { - info->groups = pdb_search_groups(info); - if (info->groups == NULL) { - return 0; - } - } - /* Fetch the last possible entry, thus trigger an enumeration */ - pdb_search_entries(info->groups, 0xffffffff, 1, &entry); - - /* Ensure we cache this enumeration. */ - set_disp_info_cache_timeout(info, DISP_INFO_CACHE_TIMEOUT); - - return info->groups->num_entries; -} - -static uint32 count_sam_aliases(struct disp_info *info) -{ - struct samr_displayentry *entry; - - if (info->aliases == NULL) { - info->aliases = pdb_search_aliases(info, &info->sid); - if (info->aliases == NULL) { - return 0; - } - } - /* Fetch the last possible entry, thus trigger an enumeration */ - pdb_search_entries(info->aliases, 0xffffffff, 1, &entry); - - /* Ensure we cache this enumeration. */ - set_disp_info_cache_timeout(info, DISP_INFO_CACHE_TIMEOUT); - - return info->aliases->num_entries; -} - -/******************************************************************* - _samr_Close - ********************************************************************/ - -NTSTATUS _samr_Close(struct pipes_struct *p, struct samr_Close *r) -{ - if (!close_policy_hnd(p, r->in.handle)) { - return NT_STATUS_INVALID_HANDLE; - } - - ZERO_STRUCTP(r->out.handle); - - return NT_STATUS_OK; -} - -/******************************************************************* - _samr_OpenDomain - ********************************************************************/ - -NTSTATUS _samr_OpenDomain(struct pipes_struct *p, - struct samr_OpenDomain *r) -{ - struct samr_connect_info *cinfo; - struct samr_domain_info *dinfo; - struct security_descriptor *psd = NULL; - uint32 acc_granted; - uint32 des_access = r->in.access_mask; - NTSTATUS status; - size_t sd_size; - uint32_t extra_access = SAMR_DOMAIN_ACCESS_CREATE_USER; - - /* find the connection policy handle. */ - - cinfo = policy_handle_find(p, r->in.connect_handle, 0, NULL, - struct samr_connect_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - /*check if access can be granted as requested by client. */ - map_max_allowed_access(p->server_info->security_token, - &p->server_info->utok, - &des_access); - - make_samr_object_sd( p->mem_ctx, &psd, &sd_size, &dom_generic_mapping, NULL, 0 ); - se_map_generic( &des_access, &dom_generic_mapping ); - - /* - * Users with SeAddUser get the ability to manipulate groups - * and aliases. - */ - if (security_token_has_privilege(p->server_info->security_token, SEC_PRIV_ADD_USERS)) { - extra_access |= (SAMR_DOMAIN_ACCESS_CREATE_GROUP | - SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS | - SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT | - SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS | - SAMR_DOMAIN_ACCESS_CREATE_ALIAS); - } - - /* - * Users with SeMachineAccount or SeAddUser get additional - * SAMR_DOMAIN_ACCESS_CREATE_USER access. - */ - - status = access_check_object( psd, p->server_info->security_token, - SEC_PRIV_MACHINE_ACCOUNT, SEC_PRIV_ADD_USERS, - extra_access, des_access, - &acc_granted, "_samr_OpenDomain" ); - - if ( !NT_STATUS_IS_OK(status) ) - return status; - - if (!sid_check_is_domain(r->in.sid) && - !sid_check_is_builtin(r->in.sid)) { - return NT_STATUS_NO_SUCH_DOMAIN; - } - - dinfo = policy_handle_create(p, r->out.domain_handle, acc_granted, - struct samr_domain_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - dinfo->sid = *r->in.sid; - dinfo->disp_info = get_samr_dispinfo_by_sid(r->in.sid); - - DEBUG(5,("_samr_OpenDomain: %d\n", __LINE__)); - - return NT_STATUS_OK; -} - -/******************************************************************* - _samr_GetUserPwInfo - ********************************************************************/ - -NTSTATUS _samr_GetUserPwInfo(struct pipes_struct *p, - struct samr_GetUserPwInfo *r) -{ - struct samr_user_info *uinfo; - enum lsa_SidType sid_type; - uint32_t min_password_length = 0; - uint32_t password_properties = 0; - bool ret = false; - NTSTATUS status; - - DEBUG(5,("_samr_GetUserPwInfo: %d\n", __LINE__)); - - uinfo = policy_handle_find(p, r->in.user_handle, - SAMR_USER_ACCESS_GET_ATTRIBUTES, NULL, - struct samr_user_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if (!sid_check_is_in_our_domain(&uinfo->sid)) { - return NT_STATUS_OBJECT_TYPE_MISMATCH; - } - - become_root(); - ret = lookup_sid(p->mem_ctx, &uinfo->sid, NULL, NULL, &sid_type); - unbecome_root(); - if (ret == false) { - return NT_STATUS_NO_SUCH_USER; - } - - switch (sid_type) { - case SID_NAME_USER: - become_root(); - pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_LEN, - &min_password_length); - pdb_get_account_policy(PDB_POLICY_USER_MUST_LOGON_TO_CHG_PASS, - &password_properties); - unbecome_root(); - - if (lp_check_password_script() && *lp_check_password_script()) { - password_properties |= DOMAIN_PASSWORD_COMPLEX; - } - - break; - default: - break; - } - - r->out.info->min_password_length = min_password_length; - r->out.info->password_properties = password_properties; - - DEBUG(5,("_samr_GetUserPwInfo: %d\n", __LINE__)); - - return NT_STATUS_OK; -} - -/******************************************************************* - _samr_SetSecurity - ********************************************************************/ - -NTSTATUS _samr_SetSecurity(struct pipes_struct *p, - struct samr_SetSecurity *r) -{ - struct samr_user_info *uinfo; - uint32 i; - struct security_acl *dacl; - bool ret; - struct samu *sampass=NULL; - NTSTATUS status; - - uinfo = policy_handle_find(p, r->in.handle, - SAMR_USER_ACCESS_SET_ATTRIBUTES, NULL, - struct samr_user_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if (!(sampass = samu_new( p->mem_ctx))) { - DEBUG(0,("No memory!\n")); - return NT_STATUS_NO_MEMORY; - } - - /* get the user record */ - become_root(); - ret = pdb_getsampwsid(sampass, &uinfo->sid); - unbecome_root(); - - if (!ret) { - DEBUG(4, ("User %s not found\n", - sid_string_dbg(&uinfo->sid))); - TALLOC_FREE(sampass); - return NT_STATUS_INVALID_HANDLE; - } - - dacl = r->in.sdbuf->sd->dacl; - for (i=0; i < dacl->num_aces; i++) { - if (dom_sid_equal(&uinfo->sid, &dacl->aces[i].trustee)) { - ret = pdb_set_pass_can_change(sampass, - (dacl->aces[i].access_mask & - SAMR_USER_ACCESS_CHANGE_PASSWORD) ? - True: False); - break; - } - } - - if (!ret) { - TALLOC_FREE(sampass); - return NT_STATUS_ACCESS_DENIED; - } - - become_root(); - status = pdb_update_sam_account(sampass); - unbecome_root(); - - TALLOC_FREE(sampass); - - return status; -} - -/******************************************************************* - build correct perms based on policies and password times for _samr_query_sec_obj -*******************************************************************/ -static bool check_change_pw_access(TALLOC_CTX *mem_ctx, struct dom_sid *user_sid) -{ - struct samu *sampass=NULL; - bool ret; - - if ( !(sampass = samu_new( mem_ctx )) ) { - DEBUG(0,("No memory!\n")); - return False; - } - - become_root(); - ret = pdb_getsampwsid(sampass, user_sid); - unbecome_root(); - - if (ret == False) { - DEBUG(4,("User %s not found\n", sid_string_dbg(user_sid))); - TALLOC_FREE(sampass); - return False; - } - - DEBUG(3,("User:[%s]\n", pdb_get_username(sampass) )); - - if (pdb_get_pass_can_change(sampass)) { - TALLOC_FREE(sampass); - return True; - } - TALLOC_FREE(sampass); - return False; -} - - -/******************************************************************* - _samr_QuerySecurity - ********************************************************************/ - -NTSTATUS _samr_QuerySecurity(struct pipes_struct *p, - struct samr_QuerySecurity *r) -{ - struct samr_connect_info *cinfo; - struct samr_domain_info *dinfo; - struct samr_user_info *uinfo; - struct samr_group_info *ginfo; - struct samr_alias_info *ainfo; - NTSTATUS status; - struct security_descriptor * psd = NULL; - size_t sd_size = 0; - - cinfo = policy_handle_find(p, r->in.handle, - SEC_STD_READ_CONTROL, NULL, - struct samr_connect_info, &status); - if (NT_STATUS_IS_OK(status)) { - DEBUG(5,("_samr_QuerySecurity: querying security on SAM\n")); - status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, - &sam_generic_mapping, NULL, 0); - goto done; - } - - dinfo = policy_handle_find(p, r->in.handle, - SEC_STD_READ_CONTROL, NULL, - struct samr_domain_info, &status); - if (NT_STATUS_IS_OK(status)) { - DEBUG(5,("_samr_QuerySecurity: querying security on Domain " - "with SID: %s\n", sid_string_dbg(&dinfo->sid))); - /* - * TODO: Builtin probably needs a different SD with restricted - * write access - */ - status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, - &dom_generic_mapping, NULL, 0); - goto done; - } - - uinfo = policy_handle_find(p, r->in.handle, - SEC_STD_READ_CONTROL, NULL, - struct samr_user_info, &status); - if (NT_STATUS_IS_OK(status)) { - DEBUG(10,("_samr_QuerySecurity: querying security on user " - "Object with SID: %s\n", - sid_string_dbg(&uinfo->sid))); - if (check_change_pw_access(p->mem_ctx, &uinfo->sid)) { - status = make_samr_object_sd( - p->mem_ctx, &psd, &sd_size, - &usr_generic_mapping, - &uinfo->sid, SAMR_USR_RIGHTS_WRITE_PW); - } else { - status = make_samr_object_sd( - p->mem_ctx, &psd, &sd_size, - &usr_nopwchange_generic_mapping, - &uinfo->sid, SAMR_USR_RIGHTS_CANT_WRITE_PW); - } - goto done; - } - - ginfo = policy_handle_find(p, r->in.handle, - SEC_STD_READ_CONTROL, NULL, - struct samr_group_info, &status); - if (NT_STATUS_IS_OK(status)) { - /* - * TODO: different SDs have to be generated for aliases groups - * and users. Currently all three get a default user SD - */ - DEBUG(10,("_samr_QuerySecurity: querying security on group " - "Object with SID: %s\n", - sid_string_dbg(&ginfo->sid))); - status = make_samr_object_sd( - p->mem_ctx, &psd, &sd_size, - &usr_nopwchange_generic_mapping, - &ginfo->sid, SAMR_USR_RIGHTS_CANT_WRITE_PW); - goto done; - } - - ainfo = policy_handle_find(p, r->in.handle, - SEC_STD_READ_CONTROL, NULL, - struct samr_alias_info, &status); - if (NT_STATUS_IS_OK(status)) { - /* - * TODO: different SDs have to be generated for aliases groups - * and users. Currently all three get a default user SD - */ - DEBUG(10,("_samr_QuerySecurity: querying security on alias " - "Object with SID: %s\n", - sid_string_dbg(&ainfo->sid))); - status = make_samr_object_sd( - p->mem_ctx, &psd, &sd_size, - &usr_nopwchange_generic_mapping, - &ainfo->sid, SAMR_USR_RIGHTS_CANT_WRITE_PW); - goto done; - } - - return NT_STATUS_OBJECT_TYPE_MISMATCH; -done: - if ((*r->out.sdbuf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL) - return NT_STATUS_NO_MEMORY; - - return status; -} - -/******************************************************************* -makes a SAM_ENTRY / UNISTR2* structure from a user list. -********************************************************************/ - -static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, - struct samr_SamEntry **sam_pp, - uint32_t num_entries, - uint32_t start_idx, - struct samr_displayentry *entries) -{ - uint32_t i; - struct samr_SamEntry *sam; - - *sam_pp = NULL; - - if (num_entries == 0) { - return NT_STATUS_OK; - } - - sam = TALLOC_ZERO_ARRAY(ctx, struct samr_SamEntry, num_entries); - if (sam == NULL) { - DEBUG(0, ("make_user_sam_entry_list: TALLOC_ZERO failed!\n")); - return NT_STATUS_NO_MEMORY; - } - - for (i = 0; i < num_entries; i++) { -#if 0 - /* - * usrmgr expects a non-NULL terminated string with - * trust relationships - */ - if (entries[i].acct_flags & ACB_DOMTRUST) { - init_unistr2(&uni_temp_name, entries[i].account_name, - UNI_FLAGS_NONE); - } else { - init_unistr2(&uni_temp_name, entries[i].account_name, - UNI_STR_TERMINATE); - } -#endif - init_lsa_String(&sam[i].name, entries[i].account_name); - sam[i].idx = entries[i].rid; - } - - *sam_pp = sam; - - return NT_STATUS_OK; -} - -#define MAX_SAM_ENTRIES MAX_SAM_ENTRIES_W2K - -/******************************************************************* - _samr_EnumDomainUsers - ********************************************************************/ - -NTSTATUS _samr_EnumDomainUsers(struct pipes_struct *p, - struct samr_EnumDomainUsers *r) -{ - NTSTATUS status; - struct samr_domain_info *dinfo; - int num_account; - uint32 enum_context = *r->in.resume_handle; - enum remote_arch_types ra_type = get_remote_arch(); - int max_sam_entries = (ra_type == RA_WIN95) ? MAX_SAM_ENTRIES_W95 : MAX_SAM_ENTRIES_W2K; - uint32 max_entries = max_sam_entries; - struct samr_displayentry *entries = NULL; - struct samr_SamArray *samr_array = NULL; - struct samr_SamEntry *samr_entries = NULL; - - DEBUG(5,("_samr_EnumDomainUsers: %d\n", __LINE__)); - - dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL, - struct samr_domain_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - samr_array = TALLOC_ZERO_P(p->mem_ctx, struct samr_SamArray); - if (!samr_array) { - return NT_STATUS_NO_MEMORY; - } - *r->out.sam = samr_array; - - if (sid_check_is_builtin(&dinfo->sid)) { - /* No users in builtin. */ - *r->out.resume_handle = *r->in.resume_handle; - DEBUG(5,("_samr_EnumDomainUsers: No users in BUILTIN\n")); - return status; - } - - become_root(); - - /* AS ROOT !!!! */ - - if ((dinfo->disp_info->enum_users != NULL) && - (dinfo->disp_info->enum_acb_mask != r->in.acct_flags)) { - TALLOC_FREE(dinfo->disp_info->enum_users); - } - - if (dinfo->disp_info->enum_users == NULL) { - dinfo->disp_info->enum_users = pdb_search_users( - dinfo->disp_info, r->in.acct_flags); - dinfo->disp_info->enum_acb_mask = r->in.acct_flags; - } - - if (dinfo->disp_info->enum_users == NULL) { - /* END AS ROOT !!!! */ - unbecome_root(); - return NT_STATUS_ACCESS_DENIED; - } - - num_account = pdb_search_entries(dinfo->disp_info->enum_users, - enum_context, max_entries, - &entries); - - /* END AS ROOT !!!! */ - - unbecome_root(); - - if (num_account == 0) { - DEBUG(5, ("_samr_EnumDomainUsers: enumeration handle over " - "total entries\n")); - *r->out.resume_handle = *r->in.resume_handle; - return NT_STATUS_OK; - } - - status = make_user_sam_entry_list(p->mem_ctx, &samr_entries, - num_account, enum_context, - entries); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if (max_entries <= num_account) { - status = STATUS_MORE_ENTRIES; - } else { - status = NT_STATUS_OK; - } - - /* Ensure we cache this enumeration. */ - set_disp_info_cache_timeout(dinfo->disp_info, DISP_INFO_CACHE_TIMEOUT); - - DEBUG(5, ("_samr_EnumDomainUsers: %d\n", __LINE__)); - - samr_array->count = num_account; - samr_array->entries = samr_entries; - - *r->out.resume_handle = *r->in.resume_handle + num_account; - *r->out.num_entries = num_account; - - DEBUG(5,("_samr_EnumDomainUsers: %d\n", __LINE__)); - - return status; -} - -/******************************************************************* -makes a SAM_ENTRY / UNISTR2* structure from a group list. -********************************************************************/ - -static void make_group_sam_entry_list(TALLOC_CTX *ctx, - struct samr_SamEntry **sam_pp, - uint32_t num_sam_entries, - struct samr_displayentry *entries) -{ - struct samr_SamEntry *sam; - uint32_t i; - - *sam_pp = NULL; - - if (num_sam_entries == 0) { - return; - } - - sam = TALLOC_ZERO_ARRAY(ctx, struct samr_SamEntry, num_sam_entries); - if (sam == NULL) { - return; - } - - for (i = 0; i < num_sam_entries; i++) { - /* - * JRA. I think this should include the null. TNG does not. - */ - init_lsa_String(&sam[i].name, entries[i].account_name); - sam[i].idx = entries[i].rid; - } - - *sam_pp = sam; -} - -/******************************************************************* - _samr_EnumDomainGroups - ********************************************************************/ - -NTSTATUS _samr_EnumDomainGroups(struct pipes_struct *p, - struct samr_EnumDomainGroups *r) -{ - NTSTATUS status; - struct samr_domain_info *dinfo; - struct samr_displayentry *groups; - uint32 num_groups; - struct samr_SamArray *samr_array = NULL; - struct samr_SamEntry *samr_entries = NULL; - - dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL, - struct samr_domain_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - DEBUG(5,("_samr_EnumDomainGroups: %d\n", __LINE__)); - - samr_array = TALLOC_ZERO_P(p->mem_ctx, struct samr_SamArray); - if (!samr_array) { - return NT_STATUS_NO_MEMORY; - } - *r->out.sam = samr_array; - - if (sid_check_is_builtin(&dinfo->sid)) { - /* No groups in builtin. */ - *r->out.resume_handle = *r->in.resume_handle; - DEBUG(5,("_samr_EnumDomainGroups: No groups in BUILTIN\n")); - return status; - } - - /* the domain group array is being allocated in the function below */ - - become_root(); - - if (dinfo->disp_info->groups == NULL) { - dinfo->disp_info->groups = pdb_search_groups(dinfo->disp_info); - - if (dinfo->disp_info->groups == NULL) { - unbecome_root(); - return NT_STATUS_ACCESS_DENIED; - } - } - - num_groups = pdb_search_entries(dinfo->disp_info->groups, - *r->in.resume_handle, - MAX_SAM_ENTRIES, &groups); - unbecome_root(); - - /* Ensure we cache this enumeration. */ - set_disp_info_cache_timeout(dinfo->disp_info, DISP_INFO_CACHE_TIMEOUT); - - make_group_sam_entry_list(p->mem_ctx, &samr_entries, - num_groups, groups); - - if (MAX_SAM_ENTRIES <= num_groups) { - status = STATUS_MORE_ENTRIES; - } else { - status = NT_STATUS_OK; - } - - samr_array->count = num_groups; - samr_array->entries = samr_entries; - - *r->out.num_entries = num_groups; - *r->out.resume_handle = num_groups + *r->in.resume_handle; - - DEBUG(5,("_samr_EnumDomainGroups: %d\n", __LINE__)); - - return status; -} - -/******************************************************************* - _samr_EnumDomainAliases - ********************************************************************/ - -NTSTATUS _samr_EnumDomainAliases(struct pipes_struct *p, - struct samr_EnumDomainAliases *r) -{ - NTSTATUS status; - struct samr_domain_info *dinfo; - struct samr_displayentry *aliases; - uint32 num_aliases = 0; - struct samr_SamArray *samr_array = NULL; - struct samr_SamEntry *samr_entries = NULL; - - dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL, - struct samr_domain_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - DEBUG(5,("_samr_EnumDomainAliases: sid %s\n", - sid_string_dbg(&dinfo->sid))); - - samr_array = TALLOC_ZERO_P(p->mem_ctx, struct samr_SamArray); - if (!samr_array) { - return NT_STATUS_NO_MEMORY; - } - - become_root(); - - if (dinfo->disp_info->aliases == NULL) { - dinfo->disp_info->aliases = pdb_search_aliases( - dinfo->disp_info, &dinfo->sid); - if (dinfo->disp_info->aliases == NULL) { - unbecome_root(); - return NT_STATUS_ACCESS_DENIED; - } - } - - num_aliases = pdb_search_entries(dinfo->disp_info->aliases, - *r->in.resume_handle, - MAX_SAM_ENTRIES, &aliases); - unbecome_root(); - - /* Ensure we cache this enumeration. */ - set_disp_info_cache_timeout(dinfo->disp_info, DISP_INFO_CACHE_TIMEOUT); - - make_group_sam_entry_list(p->mem_ctx, &samr_entries, - num_aliases, aliases); - - DEBUG(5,("_samr_EnumDomainAliases: %d\n", __LINE__)); - - if (MAX_SAM_ENTRIES <= num_aliases) { - status = STATUS_MORE_ENTRIES; - } else { - status = NT_STATUS_OK; - } - - samr_array->count = num_aliases; - samr_array->entries = samr_entries; - - *r->out.sam = samr_array; - *r->out.num_entries = num_aliases; - *r->out.resume_handle = num_aliases + *r->in.resume_handle; - - return status; -} - -/******************************************************************* - inits a samr_DispInfoGeneral structure. -********************************************************************/ - -static NTSTATUS init_samr_dispinfo_1(TALLOC_CTX *ctx, - struct samr_DispInfoGeneral *r, - uint32_t num_entries, - uint32_t start_idx, - struct samr_displayentry *entries) -{ - uint32 i; - - DEBUG(10, ("init_samr_dispinfo_1: num_entries: %d\n", num_entries)); - - if (num_entries == 0) { - return NT_STATUS_OK; - } - - r->count = num_entries; - - r->entries = TALLOC_ZERO_ARRAY(ctx, struct samr_DispEntryGeneral, num_entries); - if (!r->entries) { - return NT_STATUS_NO_MEMORY; - } - - for (i = 0; i < num_entries ; i++) { - - init_lsa_String(&r->entries[i].account_name, - entries[i].account_name); - - init_lsa_String(&r->entries[i].description, - entries[i].description); - - init_lsa_String(&r->entries[i].full_name, - entries[i].fullname); - - r->entries[i].rid = entries[i].rid; - r->entries[i].acct_flags = entries[i].acct_flags; - r->entries[i].idx = start_idx+i+1; - } - - return NT_STATUS_OK; -} - -/******************************************************************* - inits a samr_DispInfoFull structure. -********************************************************************/ - -static NTSTATUS init_samr_dispinfo_2(TALLOC_CTX *ctx, - struct samr_DispInfoFull *r, - uint32_t num_entries, - uint32_t start_idx, - struct samr_displayentry *entries) -{ - uint32_t i; - - DEBUG(10, ("init_samr_dispinfo_2: num_entries: %d\n", num_entries)); - - if (num_entries == 0) { - return NT_STATUS_OK; - } - - r->count = num_entries; - - r->entries = TALLOC_ZERO_ARRAY(ctx, struct samr_DispEntryFull, num_entries); - if (!r->entries) { - return NT_STATUS_NO_MEMORY; - } - - for (i = 0; i < num_entries ; i++) { - - init_lsa_String(&r->entries[i].account_name, - entries[i].account_name); - - init_lsa_String(&r->entries[i].description, - entries[i].description); - - r->entries[i].rid = entries[i].rid; - r->entries[i].acct_flags = entries[i].acct_flags; - r->entries[i].idx = start_idx+i+1; - } - - return NT_STATUS_OK; -} - -/******************************************************************* - inits a samr_DispInfoFullGroups structure. -********************************************************************/ - -static NTSTATUS init_samr_dispinfo_3(TALLOC_CTX *ctx, - struct samr_DispInfoFullGroups *r, - uint32_t num_entries, - uint32_t start_idx, - struct samr_displayentry *entries) -{ - uint32_t i; - - DEBUG(5, ("init_samr_dispinfo_3: num_entries: %d\n", num_entries)); - - if (num_entries == 0) { - return NT_STATUS_OK; - } - - r->count = num_entries; - - r->entries = TALLOC_ZERO_ARRAY(ctx, struct samr_DispEntryFullGroup, num_entries); - if (!r->entries) { - return NT_STATUS_NO_MEMORY; - } - - for (i = 0; i < num_entries ; i++) { - - init_lsa_String(&r->entries[i].account_name, - entries[i].account_name); - - init_lsa_String(&r->entries[i].description, - entries[i].description); - - r->entries[i].rid = entries[i].rid; - r->entries[i].acct_flags = entries[i].acct_flags; - r->entries[i].idx = start_idx+i+1; - } - - return NT_STATUS_OK; -} - -/******************************************************************* - inits a samr_DispInfoAscii structure. -********************************************************************/ - -static NTSTATUS init_samr_dispinfo_4(TALLOC_CTX *ctx, - struct samr_DispInfoAscii *r, - uint32_t num_entries, - uint32_t start_idx, - struct samr_displayentry *entries) -{ - uint32_t i; - - DEBUG(5, ("init_samr_dispinfo_4: num_entries: %d\n", num_entries)); - - if (num_entries == 0) { - return NT_STATUS_OK; - } - - r->count = num_entries; - - r->entries = TALLOC_ZERO_ARRAY(ctx, struct samr_DispEntryAscii, num_entries); - if (!r->entries) { - return NT_STATUS_NO_MEMORY; - } - - for (i = 0; i < num_entries ; i++) { - - init_lsa_AsciiStringLarge(&r->entries[i].account_name, - entries[i].account_name); - - r->entries[i].idx = start_idx+i+1; - } - - return NT_STATUS_OK; -} - -/******************************************************************* - inits a samr_DispInfoAscii structure. -********************************************************************/ - -static NTSTATUS init_samr_dispinfo_5(TALLOC_CTX *ctx, - struct samr_DispInfoAscii *r, - uint32_t num_entries, - uint32_t start_idx, - struct samr_displayentry *entries) -{ - uint32_t i; - - DEBUG(5, ("init_samr_dispinfo_5: num_entries: %d\n", num_entries)); - - if (num_entries == 0) { - return NT_STATUS_OK; - } - - r->count = num_entries; - - r->entries = TALLOC_ZERO_ARRAY(ctx, struct samr_DispEntryAscii, num_entries); - if (!r->entries) { - return NT_STATUS_NO_MEMORY; - } - - for (i = 0; i < num_entries ; i++) { - - init_lsa_AsciiStringLarge(&r->entries[i].account_name, - entries[i].account_name); - - r->entries[i].idx = start_idx+i+1; - } - - return NT_STATUS_OK; -} - -/******************************************************************* - _samr_QueryDisplayInfo - ********************************************************************/ - -NTSTATUS _samr_QueryDisplayInfo(struct pipes_struct *p, - struct samr_QueryDisplayInfo *r) -{ - NTSTATUS status; - struct samr_domain_info *dinfo; - uint32 struct_size=0x20; /* W2K always reply that, client doesn't care */ - - uint32 max_entries = r->in.max_entries; - - union samr_DispInfo *disp_info = r->out.info; - - uint32 temp_size=0; - NTSTATUS disp_ret = NT_STATUS_UNSUCCESSFUL; - uint32 num_account = 0; - enum remote_arch_types ra_type = get_remote_arch(); - int max_sam_entries = (ra_type == RA_WIN95) ? MAX_SAM_ENTRIES_W95 : MAX_SAM_ENTRIES_W2K; - struct samr_displayentry *entries = NULL; - - DEBUG(5,("_samr_QueryDisplayInfo: %d\n", __LINE__)); - - dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL, - struct samr_domain_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if (sid_check_is_builtin(&dinfo->sid)) { - DEBUG(5,("_samr_QueryDisplayInfo: no users in BUILTIN\n")); - return NT_STATUS_OK; - } - - /* - * calculate how many entries we will return. - * based on - * - the number of entries the client asked - * - our limit on that - * - the starting point (enumeration context) - * - the buffer size the client will accept - */ - - /* - * We are a lot more like W2K. Instead of reading the SAM - * each time to find the records we need to send back, - * we read it once and link that copy to the sam handle. - * For large user list (over the MAX_SAM_ENTRIES) - * it's a definitive win. - * second point to notice: between enumerations - * our sam is now the same as it's a snapshoot. - * third point: got rid of the static SAM_USER_21 struct - * no more intermediate. - * con: it uses much more memory, as a full copy is stored - * in memory. - * - * If you want to change it, think twice and think - * of the second point , that's really important. - * - * JFM, 12/20/2001 - */ - - if ((r->in.level < 1) || (r->in.level > 5)) { - DEBUG(0,("_samr_QueryDisplayInfo: Unknown info level (%u)\n", - (unsigned int)r->in.level )); - return NT_STATUS_INVALID_INFO_CLASS; - } - - /* first limit the number of entries we will return */ - if (r->in.max_entries > max_sam_entries) { - DEBUG(5, ("_samr_QueryDisplayInfo: client requested %d " - "entries, limiting to %d\n", r->in.max_entries, - max_sam_entries)); - max_entries = max_sam_entries; - } - - /* calculate the size and limit on the number of entries we will - * return */ - - temp_size=max_entries*struct_size; - - if (temp_size > r->in.buf_size) { - max_entries = MIN((r->in.buf_size / struct_size),max_entries); - DEBUG(5, ("_samr_QueryDisplayInfo: buffer size limits to " - "only %d entries\n", max_entries)); - } - - become_root(); - - /* THe following done as ROOT. Don't return without unbecome_root(). */ - - switch (r->in.level) { - case 1: - case 4: - if (dinfo->disp_info->users == NULL) { - dinfo->disp_info->users = pdb_search_users( - dinfo->disp_info, ACB_NORMAL); - if (dinfo->disp_info->users == NULL) { - unbecome_root(); - return NT_STATUS_ACCESS_DENIED; - } - DEBUG(10,("_samr_QueryDisplayInfo: starting user enumeration at index %u\n", - (unsigned int)r->in.start_idx)); - } else { - DEBUG(10,("_samr_QueryDisplayInfo: using cached user enumeration at index %u\n", - (unsigned int)r->in.start_idx)); - } - - num_account = pdb_search_entries(dinfo->disp_info->users, - r->in.start_idx, max_entries, - &entries); - break; - case 2: - if (dinfo->disp_info->machines == NULL) { - dinfo->disp_info->machines = pdb_search_users( - dinfo->disp_info, ACB_WSTRUST|ACB_SVRTRUST); - if (dinfo->disp_info->machines == NULL) { - unbecome_root(); - return NT_STATUS_ACCESS_DENIED; - } - DEBUG(10,("_samr_QueryDisplayInfo: starting machine enumeration at index %u\n", - (unsigned int)r->in.start_idx)); - } else { - DEBUG(10,("_samr_QueryDisplayInfo: using cached machine enumeration at index %u\n", - (unsigned int)r->in.start_idx)); - } - - num_account = pdb_search_entries(dinfo->disp_info->machines, - r->in.start_idx, max_entries, - &entries); - break; - case 3: - case 5: - if (dinfo->disp_info->groups == NULL) { - dinfo->disp_info->groups = pdb_search_groups( - dinfo->disp_info); - if (dinfo->disp_info->groups == NULL) { - unbecome_root(); - return NT_STATUS_ACCESS_DENIED; - } - DEBUG(10,("_samr_QueryDisplayInfo: starting group enumeration at index %u\n", - (unsigned int)r->in.start_idx)); - } else { - DEBUG(10,("_samr_QueryDisplayInfo: using cached group enumeration at index %u\n", - (unsigned int)r->in.start_idx)); - } - - num_account = pdb_search_entries(dinfo->disp_info->groups, - r->in.start_idx, max_entries, - &entries); - break; - default: - unbecome_root(); - smb_panic("info class changed"); - break; - } - unbecome_root(); - - - /* Now create reply structure */ - switch (r->in.level) { - case 1: - disp_ret = init_samr_dispinfo_1(p->mem_ctx, &disp_info->info1, - num_account, r->in.start_idx, - entries); - break; - case 2: - disp_ret = init_samr_dispinfo_2(p->mem_ctx, &disp_info->info2, - num_account, r->in.start_idx, - entries); - break; - case 3: - disp_ret = init_samr_dispinfo_3(p->mem_ctx, &disp_info->info3, - num_account, r->in.start_idx, - entries); - break; - case 4: - disp_ret = init_samr_dispinfo_4(p->mem_ctx, &disp_info->info4, - num_account, r->in.start_idx, - entries); - break; - case 5: - disp_ret = init_samr_dispinfo_5(p->mem_ctx, &disp_info->info5, - num_account, r->in.start_idx, - entries); - break; - default: - smb_panic("info class changed"); - break; - } - - if (!NT_STATUS_IS_OK(disp_ret)) - return disp_ret; - - if (max_entries <= num_account) { - status = STATUS_MORE_ENTRIES; - } else { - status = NT_STATUS_OK; - } - - /* Ensure we cache this enumeration. */ - set_disp_info_cache_timeout(dinfo->disp_info, DISP_INFO_CACHE_TIMEOUT); - - DEBUG(5, ("_samr_QueryDisplayInfo: %d\n", __LINE__)); - - *r->out.total_size = num_account * struct_size; - *r->out.returned_size = num_account ? temp_size : 0; - - return status; -} - -/**************************************************************** - _samr_QueryDisplayInfo2 -****************************************************************/ - -NTSTATUS _samr_QueryDisplayInfo2(struct pipes_struct *p, - struct samr_QueryDisplayInfo2 *r) -{ - struct samr_QueryDisplayInfo q; - - q.in.domain_handle = r->in.domain_handle; - q.in.level = r->in.level; - q.in.start_idx = r->in.start_idx; - q.in.max_entries = r->in.max_entries; - q.in.buf_size = r->in.buf_size; - - q.out.total_size = r->out.total_size; - q.out.returned_size = r->out.returned_size; - q.out.info = r->out.info; - - return _samr_QueryDisplayInfo(p, &q); -} - -/**************************************************************** - _samr_QueryDisplayInfo3 -****************************************************************/ - -NTSTATUS _samr_QueryDisplayInfo3(struct pipes_struct *p, - struct samr_QueryDisplayInfo3 *r) -{ - struct samr_QueryDisplayInfo q; - - q.in.domain_handle = r->in.domain_handle; - q.in.level = r->in.level; - q.in.start_idx = r->in.start_idx; - q.in.max_entries = r->in.max_entries; - q.in.buf_size = r->in.buf_size; - - q.out.total_size = r->out.total_size; - q.out.returned_size = r->out.returned_size; - q.out.info = r->out.info; - - return _samr_QueryDisplayInfo(p, &q); -} - -/******************************************************************* - _samr_QueryAliasInfo - ********************************************************************/ - -NTSTATUS _samr_QueryAliasInfo(struct pipes_struct *p, - struct samr_QueryAliasInfo *r) -{ - struct samr_alias_info *ainfo; - struct acct_info info; - NTSTATUS status; - union samr_AliasInfo *alias_info = NULL; - const char *alias_name = NULL; - const char *alias_description = NULL; - - DEBUG(5,("_samr_QueryAliasInfo: %d\n", __LINE__)); - - ainfo = policy_handle_find(p, r->in.alias_handle, - SAMR_ALIAS_ACCESS_LOOKUP_INFO, NULL, - struct samr_alias_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - alias_info = TALLOC_ZERO_P(p->mem_ctx, union samr_AliasInfo); - if (!alias_info) { - return NT_STATUS_NO_MEMORY; - } - - become_root(); - status = pdb_get_aliasinfo(&ainfo->sid, &info); - unbecome_root(); - - if ( !NT_STATUS_IS_OK(status)) - return status; - - /* FIXME: info contains fstrings */ - alias_name = talloc_strdup(r, info.acct_name); - alias_description = talloc_strdup(r, info.acct_desc); - - switch (r->in.level) { - case ALIASINFOALL: - alias_info->all.name.string = alias_name; - alias_info->all.num_members = 1; /* ??? */ - alias_info->all.description.string = alias_description; - break; - case ALIASINFONAME: - alias_info->name.string = alias_name; - break; - case ALIASINFODESCRIPTION: - alias_info->description.string = alias_description; - break; - default: - return NT_STATUS_INVALID_INFO_CLASS; - } - - *r->out.info = alias_info; - - DEBUG(5,("_samr_QueryAliasInfo: %d\n", __LINE__)); - - return NT_STATUS_OK; -} - -/******************************************************************* - _samr_LookupNames - ********************************************************************/ - -NTSTATUS _samr_LookupNames(struct pipes_struct *p, - struct samr_LookupNames *r) -{ - struct samr_domain_info *dinfo; - NTSTATUS status; - uint32 *rid; - enum lsa_SidType *type; - int i; - int num_rids = r->in.num_names; - struct samr_Ids rids, types; - uint32_t num_mapped = 0; - - DEBUG(5,("_samr_LookupNames: %d\n", __LINE__)); - - dinfo = policy_handle_find(p, r->in.domain_handle, - 0 /* Don't know the acc_bits yet */, NULL, - struct samr_domain_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if (num_rids > MAX_SAM_ENTRIES) { - num_rids = MAX_SAM_ENTRIES; - DEBUG(5,("_samr_LookupNames: truncating entries to %d\n", num_rids)); - } - - rid = talloc_array(p->mem_ctx, uint32, num_rids); - NT_STATUS_HAVE_NO_MEMORY(rid); - - type = talloc_array(p->mem_ctx, enum lsa_SidType, num_rids); - NT_STATUS_HAVE_NO_MEMORY(type); - - DEBUG(5,("_samr_LookupNames: looking name on SID %s\n", - sid_string_dbg(&dinfo->sid))); - - for (i = 0; i < num_rids; i++) { - - status = NT_STATUS_NONE_MAPPED; - type[i] = SID_NAME_UNKNOWN; - - rid[i] = 0xffffffff; - - if (sid_check_is_builtin(&dinfo->sid)) { - if (lookup_builtin_name(r->in.names[i].string, - &rid[i])) - { - type[i] = SID_NAME_ALIAS; - } - } else { - lookup_global_sam_name(r->in.names[i].string, 0, - &rid[i], &type[i]); - } - - if (type[i] != SID_NAME_UNKNOWN) { - num_mapped++; - } - } - - if (num_mapped == num_rids) { - status = NT_STATUS_OK; - } else if (num_mapped == 0) { - status = NT_STATUS_NONE_MAPPED; - } else { - status = STATUS_SOME_UNMAPPED; - } - - rids.count = num_rids; - rids.ids = rid; - - types.count = num_rids; - types.ids = talloc_array(p->mem_ctx, uint32_t, num_rids); - NT_STATUS_HAVE_NO_MEMORY(type); - for (i = 0; i < num_rids; i++) { - types.ids[i] = (type[i] & 0xffffffff); - } - - *r->out.rids = rids; - *r->out.types = types; - - DEBUG(5,("_samr_LookupNames: %d\n", __LINE__)); - - return status; -} - -/**************************************************************** - _samr_ChangePasswordUser -****************************************************************/ - -NTSTATUS _samr_ChangePasswordUser(struct pipes_struct *p, - struct samr_ChangePasswordUser *r) -{ - NTSTATUS status; - bool ret = false; - struct samr_user_info *uinfo; - struct samu *pwd; - struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash; - struct samr_Password lm_pwd, nt_pwd; - - uinfo = policy_handle_find(p, r->in.user_handle, - SAMR_USER_ACCESS_SET_PASSWORD, NULL, - struct samr_user_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - DEBUG(5,("_samr_ChangePasswordUser: sid:%s\n", - sid_string_dbg(&uinfo->sid))); - - if (!(pwd = samu_new(NULL))) { - return NT_STATUS_NO_MEMORY; - } - - become_root(); - ret = pdb_getsampwsid(pwd, &uinfo->sid); - unbecome_root(); - - if (!ret) { - TALLOC_FREE(pwd); - return NT_STATUS_WRONG_PASSWORD; - } - - { - const uint8_t *lm_pass, *nt_pass; - - lm_pass = pdb_get_lanman_passwd(pwd); - nt_pass = pdb_get_nt_passwd(pwd); - - if (!lm_pass || !nt_pass) { - status = NT_STATUS_WRONG_PASSWORD; - goto out; - } - - memcpy(&lm_pwd.hash, lm_pass, sizeof(lm_pwd.hash)); - memcpy(&nt_pwd.hash, nt_pass, sizeof(nt_pwd.hash)); - } - - /* basic sanity checking on parameters. Do this before any database ops */ - if (!r->in.lm_present || !r->in.nt_present || - !r->in.old_lm_crypted || !r->in.new_lm_crypted || - !r->in.old_nt_crypted || !r->in.new_nt_crypted) { - /* we should really handle a change with lm not - present */ - status = NT_STATUS_INVALID_PARAMETER_MIX; - goto out; - } - - /* decrypt and check the new lm hash */ - D_P16(lm_pwd.hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash); - D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash); - if (memcmp(checkHash.hash, lm_pwd.hash, 16) != 0) { - status = NT_STATUS_WRONG_PASSWORD; - goto out; - } - - /* decrypt and check the new nt hash */ - D_P16(nt_pwd.hash, r->in.new_nt_crypted->hash, new_ntPwdHash.hash); - D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash); - if (memcmp(checkHash.hash, nt_pwd.hash, 16) != 0) { - status = NT_STATUS_WRONG_PASSWORD; - goto out; - } - - /* The NT Cross is not required by Win2k3 R2, but if present - check the nt cross hash */ - if (r->in.cross1_present && r->in.nt_cross) { - D_P16(lm_pwd.hash, r->in.nt_cross->hash, checkHash.hash); - if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) { - status = NT_STATUS_WRONG_PASSWORD; - goto out; - } - } - - /* The LM Cross is not required by Win2k3 R2, but if present - check the lm cross hash */ - if (r->in.cross2_present && r->in.lm_cross) { - D_P16(nt_pwd.hash, r->in.lm_cross->hash, checkHash.hash); - if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) { - status = NT_STATUS_WRONG_PASSWORD; - goto out; - } - } - - if (!pdb_set_nt_passwd(pwd, new_ntPwdHash.hash, PDB_CHANGED) || - !pdb_set_lanman_passwd(pwd, new_lmPwdHash.hash, PDB_CHANGED)) { - status = NT_STATUS_ACCESS_DENIED; - goto out; - } - - status = pdb_update_sam_account(pwd); - out: - TALLOC_FREE(pwd); - - return status; -} - -/******************************************************************* - _samr_ChangePasswordUser2 - ********************************************************************/ - -NTSTATUS _samr_ChangePasswordUser2(struct pipes_struct *p, - struct samr_ChangePasswordUser2 *r) -{ - NTSTATUS status; - char *user_name = NULL; - fstring wks; - - DEBUG(5,("_samr_ChangePasswordUser2: %d\n", __LINE__)); - - if (!r->in.account->string) { - return NT_STATUS_INVALID_PARAMETER; - } - fstrcpy(wks, r->in.server->string); - - DEBUG(5,("_samr_ChangePasswordUser2: user: %s wks: %s\n", user_name, wks)); - - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - (void)map_username(talloc_tos(), r->in.account->string, &user_name); - if (!user_name) { - return NT_STATUS_NO_MEMORY; - } - - /* - * UNIX username case mangling not required, pass_oem_change - * is case insensitive. - */ - - status = pass_oem_change(user_name, - p->client_id->name, - r->in.lm_password->data, - r->in.lm_verifier->hash, - r->in.nt_password->data, - r->in.nt_verifier->hash, - NULL); - - DEBUG(5,("_samr_ChangePasswordUser2: %d\n", __LINE__)); - - if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) { - return NT_STATUS_WRONG_PASSWORD; - } - - return status; -} - -/**************************************************************** - _samr_OemChangePasswordUser2 -****************************************************************/ - -NTSTATUS _samr_OemChangePasswordUser2(struct pipes_struct *p, - struct samr_OemChangePasswordUser2 *r) -{ - NTSTATUS status; - char *user_name = NULL; - const char *wks = NULL; - - DEBUG(5,("_samr_OemChangePasswordUser2: %d\n", __LINE__)); - - if (!r->in.account->string) { - return NT_STATUS_INVALID_PARAMETER; - } - if (r->in.server && r->in.server->string) { - wks = r->in.server->string; - } - - DEBUG(5,("_samr_OemChangePasswordUser2: user: %s wks: %s\n", user_name, wks)); - - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - (void)map_username(talloc_tos(), r->in.account->string, &user_name); - if (!user_name) { - return NT_STATUS_NO_MEMORY; - } - - /* - * UNIX username case mangling not required, pass_oem_change - * is case insensitive. - */ - - if (!r->in.hash || !r->in.password) { - return NT_STATUS_INVALID_PARAMETER; - } - - status = pass_oem_change(user_name, - p->client_id->name, - r->in.password->data, - r->in.hash->hash, - 0, - 0, - NULL); - - if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) { - return NT_STATUS_WRONG_PASSWORD; - } - - DEBUG(5,("_samr_OemChangePasswordUser2: %d\n", __LINE__)); - - return status; -} - -/******************************************************************* - _samr_ChangePasswordUser3 - ********************************************************************/ - -NTSTATUS _samr_ChangePasswordUser3(struct pipes_struct *p, - struct samr_ChangePasswordUser3 *r) -{ - NTSTATUS status; - char *user_name = NULL; - const char *wks = NULL; - enum samPwdChangeReason reject_reason; - struct samr_DomInfo1 *dominfo = NULL; - struct userPwdChangeFailureInformation *reject = NULL; - uint32_t tmp; - - DEBUG(5,("_samr_ChangePasswordUser3: %d\n", __LINE__)); - - if (!r->in.account->string) { - return NT_STATUS_INVALID_PARAMETER; - } - if (r->in.server && r->in.server->string) { - wks = r->in.server->string; - } - - DEBUG(5,("_samr_ChangePasswordUser3: user: %s wks: %s\n", user_name, wks)); - - /* - * Pass the user through the NT -> unix user mapping - * function. - */ - - (void)map_username(talloc_tos(), r->in.account->string, &user_name); - if (!user_name) { - return NT_STATUS_NO_MEMORY; - } - - /* - * UNIX username case mangling not required, pass_oem_change - * is case insensitive. - */ - - status = pass_oem_change(user_name, - p->client_id->name, - r->in.lm_password->data, - r->in.lm_verifier->hash, - r->in.nt_password->data, - r->in.nt_verifier->hash, - &reject_reason); - if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) { - return NT_STATUS_WRONG_PASSWORD; - } - - if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) || - NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_RESTRICTION)) { - - time_t u_expire, u_min_age; - uint32 account_policy_temp; - - dominfo = TALLOC_ZERO_P(p->mem_ctx, struct samr_DomInfo1); - if (!dominfo) { - return NT_STATUS_NO_MEMORY; - } - - reject = TALLOC_ZERO_P(p->mem_ctx, - struct userPwdChangeFailureInformation); - if (!reject) { - return NT_STATUS_NO_MEMORY; - } - - become_root(); - - /* AS ROOT !!! */ - - pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_LEN, &tmp); - dominfo->min_password_length = tmp; - - pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &tmp); - dominfo->password_history_length = tmp; - - pdb_get_account_policy(PDB_POLICY_USER_MUST_LOGON_TO_CHG_PASS, - &dominfo->password_properties); - - pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, &account_policy_temp); - u_expire = account_policy_temp; - - pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_AGE, &account_policy_temp); - u_min_age = account_policy_temp; - - /* !AS ROOT */ - - unbecome_root(); - - unix_to_nt_time_abs((NTTIME *)&dominfo->max_password_age, u_expire); - unix_to_nt_time_abs((NTTIME *)&dominfo->min_password_age, u_min_age); - - if (lp_check_password_script() && *lp_check_password_script()) { - dominfo->password_properties |= DOMAIN_PASSWORD_COMPLEX; - } - - reject->extendedFailureReason = reject_reason; - - *r->out.dominfo = dominfo; - *r->out.reject = reject; - } - - DEBUG(5,("_samr_ChangePasswordUser3: %d\n", __LINE__)); - - return status; -} - -/******************************************************************* -makes a SAMR_R_LOOKUP_RIDS structure. -********************************************************************/ - -static bool make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names, - const char **names, - struct lsa_String **lsa_name_array_p) -{ - struct lsa_String *lsa_name_array = NULL; - uint32_t i; - - *lsa_name_array_p = NULL; - - if (num_names != 0) { - lsa_name_array = TALLOC_ZERO_ARRAY(ctx, struct lsa_String, num_names); - if (!lsa_name_array) { - return false; - } - } - - for (i = 0; i < num_names; i++) { - DEBUG(10, ("names[%d]:%s\n", i, names[i] && *names[i] ? names[i] : "")); - init_lsa_String(&lsa_name_array[i], names[i]); - } - - *lsa_name_array_p = lsa_name_array; - - return true; -} - -/******************************************************************* - _samr_LookupRids - ********************************************************************/ - -NTSTATUS _samr_LookupRids(struct pipes_struct *p, - struct samr_LookupRids *r) -{ - struct samr_domain_info *dinfo; - NTSTATUS status; - const char **names; - enum lsa_SidType *attrs = NULL; - uint32 *wire_attrs = NULL; - int num_rids = (int)r->in.num_rids; - int i; - struct lsa_Strings names_array; - struct samr_Ids types_array; - struct lsa_String *lsa_names = NULL; - - DEBUG(5,("_samr_LookupRids: %d\n", __LINE__)); - - dinfo = policy_handle_find(p, r->in.domain_handle, - 0 /* Don't know the acc_bits yet */, NULL, - struct samr_domain_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if (num_rids > 1000) { - DEBUG(0, ("Got asked for %d rids (more than 1000) -- according " - "to samba4 idl this is not possible\n", num_rids)); - return NT_STATUS_UNSUCCESSFUL; - } - - if (num_rids) { - names = TALLOC_ZERO_ARRAY(p->mem_ctx, const char *, num_rids); - attrs = TALLOC_ZERO_ARRAY(p->mem_ctx, enum lsa_SidType, num_rids); - wire_attrs = TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, num_rids); - - if ((names == NULL) || (attrs == NULL) || (wire_attrs==NULL)) - return NT_STATUS_NO_MEMORY; - } else { - names = NULL; - attrs = NULL; - wire_attrs = NULL; - } - - become_root(); /* lookup_sid can require root privs */ - status = pdb_lookup_rids(&dinfo->sid, num_rids, r->in.rids, - names, attrs); - unbecome_root(); - - if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED) && (num_rids == 0)) { - status = NT_STATUS_OK; - } - - if (!make_samr_lookup_rids(p->mem_ctx, num_rids, names, - &lsa_names)) { - return NT_STATUS_NO_MEMORY; - } - - /* Convert from enum lsa_SidType to uint32 for wire format. */ - for (i = 0; i < num_rids; i++) { - wire_attrs[i] = (uint32)attrs[i]; - } - - names_array.count = num_rids; - names_array.names = lsa_names; - - types_array.count = num_rids; - types_array.ids = wire_attrs; - - *r->out.names = names_array; - *r->out.types = types_array; - - DEBUG(5,("_samr_LookupRids: %d\n", __LINE__)); - - return status; -} - -/******************************************************************* - _samr_OpenUser -********************************************************************/ - -NTSTATUS _samr_OpenUser(struct pipes_struct *p, - struct samr_OpenUser *r) -{ - struct samu *sampass=NULL; - struct dom_sid sid; - struct samr_domain_info *dinfo; - struct samr_user_info *uinfo; - struct security_descriptor *psd = NULL; - uint32 acc_granted; - uint32 des_access = r->in.access_mask; - uint32_t extra_access = 0; - size_t sd_size; - bool ret; - NTSTATUS nt_status; - - /* These two privileges, if != SEC_PRIV_INVALID, indicate - * privileges that the user must have to complete this - * operation in defience of the fixed ACL */ - enum sec_privilege needed_priv_1, needed_priv_2; - NTSTATUS status; - - dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, NULL, - struct samr_domain_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if ( !(sampass = samu_new( p->mem_ctx )) ) { - return NT_STATUS_NO_MEMORY; - } - - /* append the user's RID to it */ - - if (!sid_compose(&sid, &dinfo->sid, r->in.rid)) - return NT_STATUS_NO_SUCH_USER; - - /* check if access can be granted as requested by client. */ - map_max_allowed_access(p->server_info->security_token, - &p->server_info->utok, - &des_access); - - make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, &sid, SAMR_USR_RIGHTS_WRITE_PW); - se_map_generic(&des_access, &usr_generic_mapping); - - /* - * Get the sampass first as we need to check privileges - * based on what kind of user object this is. - * But don't reveal info too early if it didn't exist. - */ - - become_root(); - ret=pdb_getsampwsid(sampass, &sid); - unbecome_root(); - - needed_priv_1 = SEC_PRIV_INVALID; - needed_priv_2 = SEC_PRIV_INVALID; - /* - * We do the override access checks on *open*, not at - * SetUserInfo time. - */ - if (ret) { - uint32_t acb_info = pdb_get_acct_ctrl(sampass); - - if (acb_info & ACB_WSTRUST) { - /* - * SeMachineAccount is needed to add - * GENERIC_RIGHTS_USER_WRITE to a machine - * account. - */ - needed_priv_1 = SEC_PRIV_MACHINE_ACCOUNT; - } - if (acb_info & ACB_NORMAL) { - /* - * SeAddUsers is needed to add - * GENERIC_RIGHTS_USER_WRITE to a normal - * account. - */ - needed_priv_1 = SEC_PRIV_ADD_USERS; - } - /* - * Cheat - we have not set a specific privilege for - * server (BDC) or domain trust account, so allow - * GENERIC_RIGHTS_USER_WRITE if pipe user is in - * DOMAIN_RID_ADMINS. - */ - if (acb_info & (ACB_SVRTRUST|ACB_DOMTRUST)) { - if (lp_enable_privileges() && nt_token_check_domain_rid(p->server_info->security_token, - DOMAIN_RID_ADMINS)) { - des_access &= ~GENERIC_RIGHTS_USER_WRITE; - extra_access = GENERIC_RIGHTS_USER_WRITE; - DEBUG(4,("_samr_OpenUser: Allowing " - "GENERIC_RIGHTS_USER_WRITE for " - "rid admins\n")); - } - } - } - - TALLOC_FREE(sampass); - - nt_status = access_check_object(psd, p->server_info->security_token, - needed_priv_1, needed_priv_2, - GENERIC_RIGHTS_USER_WRITE, des_access, - &acc_granted, "_samr_OpenUser"); - - if ( !NT_STATUS_IS_OK(nt_status) ) - return nt_status; - - /* check that the SID exists in our domain. */ - if (ret == False) { - return NT_STATUS_NO_SUCH_USER; - } - - /* If we did the rid admins hack above, allow access. */ - acc_granted |= extra_access; - - uinfo = policy_handle_create(p, r->out.user_handle, acc_granted, - struct samr_user_info, &nt_status); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } - uinfo->sid = sid; - - return NT_STATUS_OK; -} - -/************************************************************************* - *************************************************************************/ - -static NTSTATUS init_samr_parameters_string(TALLOC_CTX *mem_ctx, - DATA_BLOB *blob, - struct lsa_BinaryString **_r) -{ - struct lsa_BinaryString *r; - - if (!blob || !_r) { - return NT_STATUS_INVALID_PARAMETER; - } - - r = TALLOC_ZERO_P(mem_ctx, struct lsa_BinaryString); - if (!r) { - return NT_STATUS_NO_MEMORY; - } - - r->array = TALLOC_ZERO_ARRAY(mem_ctx, uint16_t, blob->length/2); - if (!r->array) { - return NT_STATUS_NO_MEMORY; - } - memcpy(r->array, blob->data, blob->length); - r->size = blob->length; - r->length = blob->length; - - if (!r->array) { - return NT_STATUS_NO_MEMORY; - } - - *_r = r; - - return NT_STATUS_OK; -} - -/************************************************************************* - *************************************************************************/ - -static struct samr_LogonHours get_logon_hours_from_pdb(TALLOC_CTX *mem_ctx, - struct samu *pw) -{ - struct samr_LogonHours hours; - const int units_per_week = 168; - - ZERO_STRUCT(hours); - hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week); - if (!hours.bits) { - return hours; - } - - hours.units_per_week = units_per_week; - memset(hours.bits, 0xFF, units_per_week); - - if (pdb_get_hours(pw)) { - memcpy(hours.bits, pdb_get_hours(pw), - MIN(pdb_get_hours_len(pw), units_per_week)); - } - - return hours; -} - -/************************************************************************* - get_user_info_1. - *************************************************************************/ - -static NTSTATUS get_user_info_1(TALLOC_CTX *mem_ctx, - struct samr_UserInfo1 *r, - struct samu *pw, - struct dom_sid *domain_sid) -{ - const struct dom_sid *sid_group; - uint32_t primary_gid; - - become_root(); - sid_group = pdb_get_group_sid(pw); - unbecome_root(); - - if (!sid_peek_check_rid(domain_sid, sid_group, &primary_gid)) { - DEBUG(0, ("get_user_info_1: User %s has Primary Group SID %s, \n" - "which conflicts with the domain sid %s. Failing operation.\n", - pdb_get_username(pw), sid_string_dbg(sid_group), - sid_string_dbg(domain_sid))); - return NT_STATUS_UNSUCCESSFUL; - } - - r->account_name.string = talloc_strdup(mem_ctx, pdb_get_username(pw)); - r->full_name.string = talloc_strdup(mem_ctx, pdb_get_fullname(pw)); - r->primary_gid = primary_gid; - r->description.string = talloc_strdup(mem_ctx, pdb_get_acct_desc(pw)); - r->comment.string = talloc_strdup(mem_ctx, pdb_get_comment(pw)); - - return NT_STATUS_OK; -} - -/************************************************************************* - get_user_info_2. - *************************************************************************/ - -static NTSTATUS get_user_info_2(TALLOC_CTX *mem_ctx, - struct samr_UserInfo2 *r, - struct samu *pw) -{ - r->comment.string = talloc_strdup(mem_ctx, pdb_get_comment(pw)); - r->reserved.string = NULL; - r->country_code = 0; - r->code_page = 0; - - return NT_STATUS_OK; -} - -/************************************************************************* - get_user_info_3. - *************************************************************************/ - -static NTSTATUS get_user_info_3(TALLOC_CTX *mem_ctx, - struct samr_UserInfo3 *r, - struct samu *pw, - struct dom_sid *domain_sid) -{ - const struct dom_sid *sid_user, *sid_group; - uint32_t rid, primary_gid; - - sid_user = pdb_get_user_sid(pw); - - if (!sid_peek_check_rid(domain_sid, sid_user, &rid)) { - DEBUG(0, ("get_user_info_3: User %s has SID %s, \nwhich conflicts with " - "the domain sid %s. Failing operation.\n", - pdb_get_username(pw), sid_string_dbg(sid_user), - sid_string_dbg(domain_sid))); - return NT_STATUS_UNSUCCESSFUL; - } - - become_root(); - sid_group = pdb_get_group_sid(pw); - unbecome_root(); - - if (!sid_peek_check_rid(domain_sid, sid_group, &primary_gid)) { - DEBUG(0, ("get_user_info_3: User %s has Primary Group SID %s, \n" - "which conflicts with the domain sid %s. Failing operation.\n", - pdb_get_username(pw), sid_string_dbg(sid_group), - sid_string_dbg(domain_sid))); - return NT_STATUS_UNSUCCESSFUL; - } - - unix_to_nt_time(&r->last_logon, pdb_get_logon_time(pw)); - unix_to_nt_time(&r->last_logoff, pdb_get_logoff_time(pw)); - unix_to_nt_time(&r->last_password_change, pdb_get_pass_last_set_time(pw)); - unix_to_nt_time(&r->allow_password_change, pdb_get_pass_can_change_time(pw)); - unix_to_nt_time(&r->force_password_change, pdb_get_pass_must_change_time(pw)); - - r->account_name.string = talloc_strdup(mem_ctx, pdb_get_username(pw)); - r->full_name.string = talloc_strdup(mem_ctx, pdb_get_fullname(pw)); - r->home_directory.string= talloc_strdup(mem_ctx, pdb_get_homedir(pw)); - r->home_drive.string = talloc_strdup(mem_ctx, pdb_get_dir_drive(pw)); - r->logon_script.string = talloc_strdup(mem_ctx, pdb_get_logon_script(pw)); - r->profile_path.string = talloc_strdup(mem_ctx, pdb_get_profile_path(pw)); - r->workstations.string = talloc_strdup(mem_ctx, pdb_get_workstations(pw)); - - r->logon_hours = get_logon_hours_from_pdb(mem_ctx, pw); - r->rid = rid; - r->primary_gid = primary_gid; - r->acct_flags = pdb_get_acct_ctrl(pw); - r->bad_password_count = pdb_get_bad_password_count(pw); - r->logon_count = pdb_get_logon_count(pw); - - return NT_STATUS_OK; -} - -/************************************************************************* - get_user_info_4. - *************************************************************************/ - -static NTSTATUS get_user_info_4(TALLOC_CTX *mem_ctx, - struct samr_UserInfo4 *r, - struct samu *pw) -{ - r->logon_hours = get_logon_hours_from_pdb(mem_ctx, pw); - - return NT_STATUS_OK; -} - -/************************************************************************* - get_user_info_5. - *************************************************************************/ - -static NTSTATUS get_user_info_5(TALLOC_CTX *mem_ctx, - struct samr_UserInfo5 *r, - struct samu *pw, - struct dom_sid *domain_sid) -{ - const struct dom_sid *sid_user, *sid_group; - uint32_t rid, primary_gid; - - sid_user = pdb_get_user_sid(pw); - - if (!sid_peek_check_rid(domain_sid, sid_user, &rid)) { - DEBUG(0, ("get_user_info_5: User %s has SID %s, \nwhich conflicts with " - "the domain sid %s. Failing operation.\n", - pdb_get_username(pw), sid_string_dbg(sid_user), - sid_string_dbg(domain_sid))); - return NT_STATUS_UNSUCCESSFUL; - } - - become_root(); - sid_group = pdb_get_group_sid(pw); - unbecome_root(); - - if (!sid_peek_check_rid(domain_sid, sid_group, &primary_gid)) { - DEBUG(0, ("get_user_info_5: User %s has Primary Group SID %s, \n" - "which conflicts with the domain sid %s. Failing operation.\n", - pdb_get_username(pw), sid_string_dbg(sid_group), - sid_string_dbg(domain_sid))); - return NT_STATUS_UNSUCCESSFUL; - } - - unix_to_nt_time(&r->last_logon, pdb_get_logon_time(pw)); - unix_to_nt_time(&r->last_logoff, pdb_get_logoff_time(pw)); - unix_to_nt_time(&r->acct_expiry, pdb_get_kickoff_time(pw)); - unix_to_nt_time(&r->last_password_change, pdb_get_pass_last_set_time(pw)); - - r->account_name.string = talloc_strdup(mem_ctx, pdb_get_username(pw)); - r->full_name.string = talloc_strdup(mem_ctx, pdb_get_fullname(pw)); - r->home_directory.string= talloc_strdup(mem_ctx, pdb_get_homedir(pw)); - r->home_drive.string = talloc_strdup(mem_ctx, pdb_get_dir_drive(pw)); - r->logon_script.string = talloc_strdup(mem_ctx, pdb_get_logon_script(pw)); - r->profile_path.string = talloc_strdup(mem_ctx, pdb_get_profile_path(pw)); - r->description.string = talloc_strdup(mem_ctx, pdb_get_acct_desc(pw)); - r->workstations.string = talloc_strdup(mem_ctx, pdb_get_workstations(pw)); - - r->logon_hours = get_logon_hours_from_pdb(mem_ctx, pw); - r->rid = rid; - r->primary_gid = primary_gid; - r->acct_flags = pdb_get_acct_ctrl(pw); - r->bad_password_count = pdb_get_bad_password_count(pw); - r->logon_count = pdb_get_logon_count(pw); - - return NT_STATUS_OK; -} - -/************************************************************************* - get_user_info_6. - *************************************************************************/ - -static NTSTATUS get_user_info_6(TALLOC_CTX *mem_ctx, - struct samr_UserInfo6 *r, - struct samu *pw) -{ - r->account_name.string = talloc_strdup(mem_ctx, pdb_get_username(pw)); - r->full_name.string = talloc_strdup(mem_ctx, pdb_get_fullname(pw)); - - return NT_STATUS_OK; -} - -/************************************************************************* - get_user_info_7. Safe. Only gives out account_name. - *************************************************************************/ - -static NTSTATUS get_user_info_7(TALLOC_CTX *mem_ctx, - struct samr_UserInfo7 *r, - struct samu *smbpass) -{ - r->account_name.string = talloc_strdup(mem_ctx, pdb_get_username(smbpass)); - if (!r->account_name.string) { - return NT_STATUS_NO_MEMORY; - } - - return NT_STATUS_OK; -} - -/************************************************************************* - get_user_info_8. - *************************************************************************/ - -static NTSTATUS get_user_info_8(TALLOC_CTX *mem_ctx, - struct samr_UserInfo8 *r, - struct samu *pw) -{ - r->full_name.string = talloc_strdup(mem_ctx, pdb_get_fullname(pw)); - - return NT_STATUS_OK; -} - -/************************************************************************* - get_user_info_9. Only gives out primary group SID. - *************************************************************************/ - -static NTSTATUS get_user_info_9(TALLOC_CTX *mem_ctx, - struct samr_UserInfo9 *r, - struct samu *smbpass) -{ - r->primary_gid = pdb_get_group_rid(smbpass); - - return NT_STATUS_OK; -} - -/************************************************************************* - get_user_info_10. - *************************************************************************/ - -static NTSTATUS get_user_info_10(TALLOC_CTX *mem_ctx, - struct samr_UserInfo10 *r, - struct samu *pw) -{ - r->home_directory.string= talloc_strdup(mem_ctx, pdb_get_homedir(pw)); - r->home_drive.string = talloc_strdup(mem_ctx, pdb_get_dir_drive(pw)); - - return NT_STATUS_OK; -} - -/************************************************************************* - get_user_info_11. - *************************************************************************/ - -static NTSTATUS get_user_info_11(TALLOC_CTX *mem_ctx, - struct samr_UserInfo11 *r, - struct samu *pw) -{ - r->logon_script.string = talloc_strdup(mem_ctx, pdb_get_logon_script(pw)); - - return NT_STATUS_OK; -} - -/************************************************************************* - get_user_info_12. - *************************************************************************/ - -static NTSTATUS get_user_info_12(TALLOC_CTX *mem_ctx, - struct samr_UserInfo12 *r, - struct samu *pw) -{ - r->profile_path.string = talloc_strdup(mem_ctx, pdb_get_profile_path(pw)); - - return NT_STATUS_OK; -} - -/************************************************************************* - get_user_info_13. - *************************************************************************/ - -static NTSTATUS get_user_info_13(TALLOC_CTX *mem_ctx, - struct samr_UserInfo13 *r, - struct samu *pw) -{ - r->description.string = talloc_strdup(mem_ctx, pdb_get_acct_desc(pw)); - - return NT_STATUS_OK; -} - -/************************************************************************* - get_user_info_14. - *************************************************************************/ - -static NTSTATUS get_user_info_14(TALLOC_CTX *mem_ctx, - struct samr_UserInfo14 *r, - struct samu *pw) -{ - r->workstations.string = talloc_strdup(mem_ctx, pdb_get_workstations(pw)); - - return NT_STATUS_OK; -} - -/************************************************************************* - get_user_info_16. Safe. Only gives out acb bits. - *************************************************************************/ - -static NTSTATUS get_user_info_16(TALLOC_CTX *mem_ctx, - struct samr_UserInfo16 *r, - struct samu *smbpass) -{ - r->acct_flags = pdb_get_acct_ctrl(smbpass); - - return NT_STATUS_OK; -} - -/************************************************************************* - get_user_info_17. - *************************************************************************/ - -static NTSTATUS get_user_info_17(TALLOC_CTX *mem_ctx, - struct samr_UserInfo17 *r, - struct samu *pw) -{ - unix_to_nt_time(&r->acct_expiry, pdb_get_kickoff_time(pw)); - - return NT_STATUS_OK; -} - -/************************************************************************* - get_user_info_18. OK - this is the killer as it gives out password info. - Ensure that this is only allowed on an encrypted connection with a root - user. JRA. - *************************************************************************/ - -static NTSTATUS get_user_info_18(struct pipes_struct *p, - TALLOC_CTX *mem_ctx, - struct samr_UserInfo18 *r, - struct dom_sid *user_sid) -{ - struct samu *smbpass=NULL; - bool ret; - const uint8_t *nt_pass = NULL; - const uint8_t *lm_pass = NULL; - - ZERO_STRUCTP(r); - - if (p->server_info->system) { - goto query; - } - - if ((p->auth.auth_type != DCERPC_AUTH_TYPE_NTLMSSP) || - (p->auth.auth_type != DCERPC_AUTH_TYPE_KRB5) || - (p->auth.auth_type != DCERPC_AUTH_TYPE_SPNEGO)) { - return NT_STATUS_ACCESS_DENIED; - } - - if (p->auth.auth_level != DCERPC_AUTH_LEVEL_PRIVACY) { - return NT_STATUS_ACCESS_DENIED; - } - - query: - /* - * Do *NOT* do become_root()/unbecome_root() here ! JRA. - */ - - if ( !(smbpass = samu_new( mem_ctx )) ) { - return NT_STATUS_NO_MEMORY; - } - - ret = pdb_getsampwsid(smbpass, user_sid); - - if (ret == False) { - DEBUG(4, ("User %s not found\n", sid_string_dbg(user_sid))); - TALLOC_FREE(smbpass); - return (geteuid() == sec_initial_uid()) ? NT_STATUS_NO_SUCH_USER : NT_STATUS_ACCESS_DENIED; - } - - DEBUG(3,("User:[%s] 0x%x\n", pdb_get_username(smbpass), pdb_get_acct_ctrl(smbpass) )); - - if ( pdb_get_acct_ctrl(smbpass) & ACB_DISABLED) { - TALLOC_FREE(smbpass); - return NT_STATUS_ACCOUNT_DISABLED; - } - - lm_pass = pdb_get_lanman_passwd(smbpass); - if (lm_pass != NULL) { - memcpy(r->lm_pwd.hash, lm_pass, 16); - r->lm_pwd_active = true; - } - - nt_pass = pdb_get_nt_passwd(smbpass); - if (nt_pass != NULL) { - memcpy(r->nt_pwd.hash, nt_pass, 16); - r->nt_pwd_active = true; - } - r->password_expired = 0; /* FIXME */ - - TALLOC_FREE(smbpass); - - return NT_STATUS_OK; -} - -/************************************************************************* - get_user_info_20 - *************************************************************************/ - -static NTSTATUS get_user_info_20(TALLOC_CTX *mem_ctx, - struct samr_UserInfo20 *r, - struct samu *sampass) -{ - const char *munged_dial = NULL; - DATA_BLOB blob; - NTSTATUS status; - struct lsa_BinaryString *parameters = NULL; - - ZERO_STRUCTP(r); - - munged_dial = pdb_get_munged_dial(sampass); - - DEBUG(3,("User:[%s] has [%s] (length: %d)\n", pdb_get_username(sampass), - munged_dial, (int)strlen(munged_dial))); - - if (munged_dial) { - blob = base64_decode_data_blob(munged_dial); - } else { - blob = data_blob_string_const_null(""); - } - - status = init_samr_parameters_string(mem_ctx, &blob, ¶meters); - data_blob_free(&blob); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - r->parameters = *parameters; - - return NT_STATUS_OK; -} - - -/************************************************************************* - get_user_info_21 - *************************************************************************/ - -static NTSTATUS get_user_info_21(TALLOC_CTX *mem_ctx, - struct samr_UserInfo21 *r, - struct samu *pw, - struct dom_sid *domain_sid, - uint32_t acc_granted) -{ - NTSTATUS status; - const struct dom_sid *sid_user, *sid_group; - uint32_t rid, primary_gid; - NTTIME force_password_change; - time_t must_change_time; - struct lsa_BinaryString *parameters = NULL; - const char *munged_dial = NULL; - DATA_BLOB blob; - - ZERO_STRUCTP(r); - - sid_user = pdb_get_user_sid(pw); - - if (!sid_peek_check_rid(domain_sid, sid_user, &rid)) { - DEBUG(0, ("get_user_info_21: User %s has SID %s, \nwhich conflicts with " - "the domain sid %s. Failing operation.\n", - pdb_get_username(pw), sid_string_dbg(sid_user), - sid_string_dbg(domain_sid))); - return NT_STATUS_UNSUCCESSFUL; - } - - become_root(); - sid_group = pdb_get_group_sid(pw); - unbecome_root(); - - if (!sid_peek_check_rid(domain_sid, sid_group, &primary_gid)) { - DEBUG(0, ("get_user_info_21: User %s has Primary Group SID %s, \n" - "which conflicts with the domain sid %s. Failing operation.\n", - pdb_get_username(pw), sid_string_dbg(sid_group), - sid_string_dbg(domain_sid))); - return NT_STATUS_UNSUCCESSFUL; - } - - unix_to_nt_time(&r->last_logon, pdb_get_logon_time(pw)); - unix_to_nt_time(&r->last_logoff, pdb_get_logoff_time(pw)); - unix_to_nt_time(&r->acct_expiry, pdb_get_kickoff_time(pw)); - unix_to_nt_time(&r->last_password_change, pdb_get_pass_last_set_time(pw)); - unix_to_nt_time(&r->allow_password_change, pdb_get_pass_can_change_time(pw)); - - must_change_time = pdb_get_pass_must_change_time(pw); - if (must_change_time == get_time_t_max()) { - unix_to_nt_time_abs(&force_password_change, must_change_time); - } else { - unix_to_nt_time(&force_password_change, must_change_time); - } - - munged_dial = pdb_get_munged_dial(pw); - if (munged_dial) { - blob = base64_decode_data_blob(munged_dial); - } else { - blob = data_blob_string_const_null(""); - } - - status = init_samr_parameters_string(mem_ctx, &blob, ¶meters); - data_blob_free(&blob); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - r->force_password_change = force_password_change; - - r->account_name.string = talloc_strdup(mem_ctx, pdb_get_username(pw)); - r->full_name.string = talloc_strdup(mem_ctx, pdb_get_fullname(pw)); - r->home_directory.string = talloc_strdup(mem_ctx, pdb_get_homedir(pw)); - r->home_drive.string = talloc_strdup(mem_ctx, pdb_get_dir_drive(pw)); - r->logon_script.string = talloc_strdup(mem_ctx, pdb_get_logon_script(pw)); - r->profile_path.string = talloc_strdup(mem_ctx, pdb_get_profile_path(pw)); - r->description.string = talloc_strdup(mem_ctx, pdb_get_acct_desc(pw)); - r->workstations.string = talloc_strdup(mem_ctx, pdb_get_workstations(pw)); - r->comment.string = talloc_strdup(mem_ctx, pdb_get_comment(pw)); - - r->logon_hours = get_logon_hours_from_pdb(mem_ctx, pw); - r->parameters = *parameters; - r->rid = rid; - r->primary_gid = primary_gid; - r->acct_flags = pdb_get_acct_ctrl(pw); - r->bad_password_count = pdb_get_bad_password_count(pw); - r->logon_count = pdb_get_logon_count(pw); - r->fields_present = pdb_build_fields_present(pw); - r->password_expired = (pdb_get_pass_must_change_time(pw) == 0) ? - PASS_MUST_CHANGE_AT_NEXT_LOGON : 0; - r->country_code = 0; - r->code_page = 0; - r->lm_password_set = 0; - r->nt_password_set = 0; - -#if 0 - - /* - Look at a user on a real NT4 PDC with usrmgr, press - 'ok'. Then you will see that fields_present is set to - 0x08f827fa. Look at the user immediately after that again, - and you will see that 0x00fffff is returned. This solves - the problem that you get access denied after having looked - at the user. - -- Volker - */ - -#endif - - - return NT_STATUS_OK; -} - -/******************************************************************* - _samr_QueryUserInfo - ********************************************************************/ - -NTSTATUS _samr_QueryUserInfo(struct pipes_struct *p, - struct samr_QueryUserInfo *r) -{ - NTSTATUS status; - union samr_UserInfo *user_info = NULL; - struct samr_user_info *uinfo; - struct dom_sid domain_sid; - uint32 rid; - bool ret = false; - struct samu *pwd = NULL; - uint32_t acc_required, acc_granted; - - switch (r->in.level) { - case 1: /* UserGeneralInformation */ - /* USER_READ_GENERAL */ - acc_required = SAMR_USER_ACCESS_GET_NAME_ETC; - break; - case 2: /* UserPreferencesInformation */ - /* USER_READ_PREFERENCES | USER_READ_GENERAL */ - acc_required = SAMR_USER_ACCESS_GET_LOCALE | - SAMR_USER_ACCESS_GET_NAME_ETC; - break; - case 3: /* UserLogonInformation */ - /* USER_READ_GENERAL | USER_READ_PREFERENCES | USER_READ_LOGON | USER_READ_ACCOUNT */ - acc_required = SAMR_USER_ACCESS_GET_NAME_ETC | - SAMR_USER_ACCESS_GET_LOCALE | - SAMR_USER_ACCESS_GET_LOGONINFO | - SAMR_USER_ACCESS_GET_ATTRIBUTES; - break; - case 4: /* UserLogonHoursInformation */ - /* USER_READ_LOGON */ - acc_required = SAMR_USER_ACCESS_GET_LOGONINFO; - break; - case 5: /* UserAccountInformation */ - /* USER_READ_GENERAL | USER_READ_PREFERENCES | USER_READ_LOGON | USER_READ_ACCOUNT */ - acc_required = SAMR_USER_ACCESS_GET_NAME_ETC | - SAMR_USER_ACCESS_GET_LOCALE | - SAMR_USER_ACCESS_GET_LOGONINFO | - SAMR_USER_ACCESS_GET_ATTRIBUTES; - break; - case 6: /* UserNameInformation */ - case 7: /* UserAccountNameInformation */ - case 8: /* UserFullNameInformation */ - case 9: /* UserPrimaryGroupInformation */ - case 13: /* UserAdminCommentInformation */ - /* USER_READ_GENERAL */ - acc_required = SAMR_USER_ACCESS_GET_NAME_ETC; - break; - case 10: /* UserHomeInformation */ - case 11: /* UserScriptInformation */ - case 12: /* UserProfileInformation */ - case 14: /* UserWorkStationsInformation */ - /* USER_READ_LOGON */ - acc_required = SAMR_USER_ACCESS_GET_LOGONINFO; - break; - case 16: /* UserControlInformation */ - case 17: /* UserExpiresInformation */ - case 20: /* UserParametersInformation */ - /* USER_READ_ACCOUNT */ - acc_required = SAMR_USER_ACCESS_GET_ATTRIBUTES; - break; - case 21: /* UserAllInformation */ - /* FIXME! - gd */ - acc_required = SAMR_USER_ACCESS_GET_ATTRIBUTES; - break; - case 18: /* UserInternal1Information */ - /* FIXME! - gd */ - acc_required = SAMR_USER_ACCESS_GET_ATTRIBUTES; - break; - case 23: /* UserInternal4Information */ - case 24: /* UserInternal4InformationNew */ - case 25: /* UserInternal4InformationNew */ - case 26: /* UserInternal5InformationNew */ - default: - return NT_STATUS_INVALID_INFO_CLASS; - break; - } - - uinfo = policy_handle_find(p, r->in.user_handle, - acc_required, &acc_granted, - struct samr_user_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - domain_sid = uinfo->sid; - - sid_split_rid(&domain_sid, &rid); - - if (!sid_check_is_in_our_domain(&uinfo->sid)) - return NT_STATUS_OBJECT_TYPE_MISMATCH; - - DEBUG(5,("_samr_QueryUserInfo: sid:%s\n", - sid_string_dbg(&uinfo->sid))); - - user_info = TALLOC_ZERO_P(p->mem_ctx, union samr_UserInfo); - if (!user_info) { - return NT_STATUS_NO_MEMORY; - } - - DEBUG(5,("_samr_QueryUserInfo: user info level: %d\n", r->in.level)); - - if (!(pwd = samu_new(p->mem_ctx))) { - return NT_STATUS_NO_MEMORY; - } - - become_root(); - ret = pdb_getsampwsid(pwd, &uinfo->sid); - unbecome_root(); - - if (ret == false) { - DEBUG(4,("User %s not found\n", sid_string_dbg(&uinfo->sid))); - TALLOC_FREE(pwd); - return NT_STATUS_NO_SUCH_USER; - } - - DEBUG(3,("User:[%s]\n", pdb_get_username(pwd))); - - samr_clear_sam_passwd(pwd); - - switch (r->in.level) { - case 1: - status = get_user_info_1(p->mem_ctx, &user_info->info1, pwd, &domain_sid); - break; - case 2: - status = get_user_info_2(p->mem_ctx, &user_info->info2, pwd); - break; - case 3: - status = get_user_info_3(p->mem_ctx, &user_info->info3, pwd, &domain_sid); - break; - case 4: - status = get_user_info_4(p->mem_ctx, &user_info->info4, pwd); - break; - case 5: - status = get_user_info_5(p->mem_ctx, &user_info->info5, pwd, &domain_sid); - break; - case 6: - status = get_user_info_6(p->mem_ctx, &user_info->info6, pwd); - break; - case 7: - status = get_user_info_7(p->mem_ctx, &user_info->info7, pwd); - break; - case 8: - status = get_user_info_8(p->mem_ctx, &user_info->info8, pwd); - break; - case 9: - status = get_user_info_9(p->mem_ctx, &user_info->info9, pwd); - break; - case 10: - status = get_user_info_10(p->mem_ctx, &user_info->info10, pwd); - break; - case 11: - status = get_user_info_11(p->mem_ctx, &user_info->info11, pwd); - break; - case 12: - status = get_user_info_12(p->mem_ctx, &user_info->info12, pwd); - break; - case 13: - status = get_user_info_13(p->mem_ctx, &user_info->info13, pwd); - break; - case 14: - status = get_user_info_14(p->mem_ctx, &user_info->info14, pwd); - break; - case 16: - status = get_user_info_16(p->mem_ctx, &user_info->info16, pwd); - break; - case 17: - status = get_user_info_17(p->mem_ctx, &user_info->info17, pwd); - break; - case 18: - /* level 18 is special */ - status = get_user_info_18(p, p->mem_ctx, &user_info->info18, - &uinfo->sid); - break; - case 20: - status = get_user_info_20(p->mem_ctx, &user_info->info20, pwd); - break; - case 21: - status = get_user_info_21(p->mem_ctx, &user_info->info21, pwd, &domain_sid, acc_granted); - break; - default: - status = NT_STATUS_INVALID_INFO_CLASS; - break; - } - - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - - *r->out.info = user_info; - - done: - TALLOC_FREE(pwd); - - DEBUG(5,("_samr_QueryUserInfo: %d\n", __LINE__)); - - return status; -} - -/**************************************************************** -****************************************************************/ - -NTSTATUS _samr_QueryUserInfo2(struct pipes_struct *p, - struct samr_QueryUserInfo2 *r) -{ - struct samr_QueryUserInfo u; - - u.in.user_handle = r->in.user_handle; - u.in.level = r->in.level; - u.out.info = r->out.info; - - return _samr_QueryUserInfo(p, &u); -} - -/******************************************************************* - _samr_GetGroupsForUser - ********************************************************************/ - -NTSTATUS _samr_GetGroupsForUser(struct pipes_struct *p, - struct samr_GetGroupsForUser *r) -{ - struct samr_user_info *uinfo; - struct samu *sam_pass=NULL; - struct dom_sid *sids; - struct samr_RidWithAttribute dom_gid; - struct samr_RidWithAttribute *gids = NULL; - uint32 primary_group_rid; - size_t num_groups = 0; - gid_t *unix_gids; - size_t i, num_gids; - bool ret; - NTSTATUS result; - bool success = False; - - struct samr_RidWithAttributeArray *rids = NULL; - - /* - * from the SID in the request: - * we should send back the list of DOMAIN GROUPS - * the user is a member of - * - * and only the DOMAIN GROUPS - * no ALIASES !!! neither aliases of the domain - * nor aliases of the builtin SID - * - * JFM, 12/2/2001 - */ - - DEBUG(5,("_samr_GetGroupsForUser: %d\n", __LINE__)); - - uinfo = policy_handle_find(p, r->in.user_handle, - SAMR_USER_ACCESS_GET_GROUPS, NULL, - struct samr_user_info, &result); - if (!NT_STATUS_IS_OK(result)) { - return result; - } - - rids = TALLOC_ZERO_P(p->mem_ctx, struct samr_RidWithAttributeArray); - if (!rids) { - return NT_STATUS_NO_MEMORY; - } - - if (!sid_check_is_in_our_domain(&uinfo->sid)) - return NT_STATUS_OBJECT_TYPE_MISMATCH; - - if ( !(sam_pass = samu_new( p->mem_ctx )) ) { - return NT_STATUS_NO_MEMORY; - } - - become_root(); - ret = pdb_getsampwsid(sam_pass, &uinfo->sid); - unbecome_root(); - - if (!ret) { - DEBUG(10, ("pdb_getsampwsid failed for %s\n", - sid_string_dbg(&uinfo->sid))); - return NT_STATUS_NO_SUCH_USER; - } - - sids = NULL; - - /* make both calls inside the root block */ - become_root(); - result = pdb_enum_group_memberships(p->mem_ctx, sam_pass, - &sids, &unix_gids, &num_groups); - if ( NT_STATUS_IS_OK(result) ) { - success = sid_peek_check_rid(get_global_sam_sid(), - pdb_get_group_sid(sam_pass), - &primary_group_rid); - } - unbecome_root(); - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(10, ("pdb_enum_group_memberships failed for %s\n", - sid_string_dbg(&uinfo->sid))); - return result; - } - - if ( !success ) { - DEBUG(5, ("Group sid %s for user %s not in our domain\n", - sid_string_dbg(pdb_get_group_sid(sam_pass)), - pdb_get_username(sam_pass))); - TALLOC_FREE(sam_pass); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - gids = NULL; - num_gids = 0; - - dom_gid.attributes = (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT| - SE_GROUP_ENABLED); - dom_gid.rid = primary_group_rid; - ADD_TO_ARRAY(p->mem_ctx, struct samr_RidWithAttribute, dom_gid, &gids, &num_gids); - - for (i=0; imem_ctx, struct samr_RidWithAttribute, dom_gid, &gids, &num_gids); - } - - rids->count = num_gids; - rids->rids = gids; - - *r->out.rids = rids; - - DEBUG(5,("_samr_GetGroupsForUser: %d\n", __LINE__)); - - return result; -} - -/******************************************************************* - ********************************************************************/ - -static uint32_t samr_get_server_role(void) -{ - uint32_t role = ROLE_DOMAIN_PDC; - - if (lp_server_role() == ROLE_DOMAIN_BDC) { - role = ROLE_DOMAIN_BDC; - } - - return role; -} - -/******************************************************************* - ********************************************************************/ - -static NTSTATUS query_dom_info_1(TALLOC_CTX *mem_ctx, - struct samr_DomInfo1 *r) -{ - uint32_t account_policy_temp; - time_t u_expire, u_min_age; - - become_root(); - - /* AS ROOT !!! */ - - pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_LEN, &account_policy_temp); - r->min_password_length = account_policy_temp; - - pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &account_policy_temp); - r->password_history_length = account_policy_temp; - - pdb_get_account_policy(PDB_POLICY_USER_MUST_LOGON_TO_CHG_PASS, - &r->password_properties); - - pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, &account_policy_temp); - u_expire = account_policy_temp; - - pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_AGE, &account_policy_temp); - u_min_age = account_policy_temp; - - /* !AS ROOT */ - - unbecome_root(); - - unix_to_nt_time_abs((NTTIME *)&r->max_password_age, u_expire); - unix_to_nt_time_abs((NTTIME *)&r->min_password_age, u_min_age); - - if (lp_check_password_script() && *lp_check_password_script()) { - r->password_properties |= DOMAIN_PASSWORD_COMPLEX; - } - - return NT_STATUS_OK; -} - -/******************************************************************* - ********************************************************************/ - -static NTSTATUS query_dom_info_2(TALLOC_CTX *mem_ctx, - struct samr_DomGeneralInformation *r, - struct samr_domain_info *dinfo) -{ - uint32_t u_logout; - time_t seq_num; - - become_root(); - - /* AS ROOT !!! */ - - r->num_users = count_sam_users(dinfo->disp_info, ACB_NORMAL); - r->num_groups = count_sam_groups(dinfo->disp_info); - r->num_aliases = count_sam_aliases(dinfo->disp_info); - - pdb_get_account_policy(PDB_POLICY_TIME_TO_LOGOUT, &u_logout); - - unix_to_nt_time_abs(&r->force_logoff_time, u_logout); - - if (!pdb_get_seq_num(&seq_num)) { - seq_num = time(NULL); - } - - /* !AS ROOT */ - - unbecome_root(); - - r->oem_information.string = lp_serverstring(); - r->domain_name.string = lp_workgroup(); - r->primary.string = global_myname(); - r->sequence_num = seq_num; - r->domain_server_state = DOMAIN_SERVER_ENABLED; - r->role = (enum samr_Role) samr_get_server_role(); - r->unknown3 = 1; - - return NT_STATUS_OK; -} - -/******************************************************************* - ********************************************************************/ - -static NTSTATUS query_dom_info_3(TALLOC_CTX *mem_ctx, - struct samr_DomInfo3 *r) -{ - uint32_t u_logout; - - become_root(); - - /* AS ROOT !!! */ - - { - uint32_t ul; - pdb_get_account_policy(PDB_POLICY_TIME_TO_LOGOUT, &ul); - u_logout = (time_t)ul; - } - - /* !AS ROOT */ - - unbecome_root(); - - unix_to_nt_time_abs(&r->force_logoff_time, u_logout); - - return NT_STATUS_OK; -} - -/******************************************************************* - ********************************************************************/ - -static NTSTATUS query_dom_info_4(TALLOC_CTX *mem_ctx, - struct samr_DomOEMInformation *r) -{ - r->oem_information.string = lp_serverstring(); - - return NT_STATUS_OK; -} - -/******************************************************************* - ********************************************************************/ - -static NTSTATUS query_dom_info_5(TALLOC_CTX *mem_ctx, - struct samr_DomInfo5 *r) -{ - r->domain_name.string = get_global_sam_name(); - - return NT_STATUS_OK; -} - -/******************************************************************* - ********************************************************************/ - -static NTSTATUS query_dom_info_6(TALLOC_CTX *mem_ctx, - struct samr_DomInfo6 *r) -{ - /* NT returns its own name when a PDC. win2k and later - * only the name of the PDC if itself is a BDC (samba4 - * idl) */ - r->primary.string = global_myname(); - - return NT_STATUS_OK; -} - -/******************************************************************* - ********************************************************************/ - -static NTSTATUS query_dom_info_7(TALLOC_CTX *mem_ctx, - struct samr_DomInfo7 *r) -{ - r->role = (enum samr_Role) samr_get_server_role(); - - return NT_STATUS_OK; -} - -/******************************************************************* - ********************************************************************/ - -static NTSTATUS query_dom_info_8(TALLOC_CTX *mem_ctx, - struct samr_DomInfo8 *r) -{ - time_t seq_num; - - become_root(); - - /* AS ROOT !!! */ - - if (!pdb_get_seq_num(&seq_num)) { - seq_num = time(NULL); - } - - /* !AS ROOT */ - - unbecome_root(); - - r->sequence_num = seq_num; - r->domain_create_time = 0; - - return NT_STATUS_OK; -} - -/******************************************************************* - ********************************************************************/ - -static NTSTATUS query_dom_info_9(TALLOC_CTX *mem_ctx, - struct samr_DomInfo9 *r) -{ - r->domain_server_state = DOMAIN_SERVER_ENABLED; - - return NT_STATUS_OK; -} - -/******************************************************************* - ********************************************************************/ - -static NTSTATUS query_dom_info_11(TALLOC_CTX *mem_ctx, - struct samr_DomGeneralInformation2 *r, - struct samr_domain_info *dinfo) -{ - NTSTATUS status; - uint32_t account_policy_temp; - time_t u_lock_duration, u_reset_time; - - status = query_dom_info_2(mem_ctx, &r->general, dinfo); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - /* AS ROOT !!! */ - - become_root(); - - pdb_get_account_policy(PDB_POLICY_LOCK_ACCOUNT_DURATION, &account_policy_temp); - u_lock_duration = account_policy_temp; - if (u_lock_duration != -1) { - u_lock_duration *= 60; - } - - pdb_get_account_policy(PDB_POLICY_RESET_COUNT_TIME, &account_policy_temp); - u_reset_time = account_policy_temp * 60; - - pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &account_policy_temp); - r->lockout_threshold = account_policy_temp; - - /* !AS ROOT */ - - unbecome_root(); - - unix_to_nt_time_abs(&r->lockout_duration, u_lock_duration); - unix_to_nt_time_abs(&r->lockout_window, u_reset_time); - - return NT_STATUS_OK; -} - -/******************************************************************* - ********************************************************************/ - -static NTSTATUS query_dom_info_12(TALLOC_CTX *mem_ctx, - struct samr_DomInfo12 *r) -{ - uint32_t account_policy_temp; - time_t u_lock_duration, u_reset_time; - - become_root(); - - /* AS ROOT !!! */ - - pdb_get_account_policy(PDB_POLICY_LOCK_ACCOUNT_DURATION, &account_policy_temp); - u_lock_duration = account_policy_temp; - if (u_lock_duration != -1) { - u_lock_duration *= 60; - } - - pdb_get_account_policy(PDB_POLICY_RESET_COUNT_TIME, &account_policy_temp); - u_reset_time = account_policy_temp * 60; - - pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &account_policy_temp); - r->lockout_threshold = account_policy_temp; - - /* !AS ROOT */ - - unbecome_root(); - - unix_to_nt_time_abs(&r->lockout_duration, u_lock_duration); - unix_to_nt_time_abs(&r->lockout_window, u_reset_time); - - return NT_STATUS_OK; -} - -/******************************************************************* - ********************************************************************/ - -static NTSTATUS query_dom_info_13(TALLOC_CTX *mem_ctx, - struct samr_DomInfo13 *r) -{ - time_t seq_num; - - become_root(); - - /* AS ROOT !!! */ - - if (!pdb_get_seq_num(&seq_num)) { - seq_num = time(NULL); - } - - /* !AS ROOT */ - - unbecome_root(); - - r->sequence_num = seq_num; - r->domain_create_time = 0; - r->modified_count_at_last_promotion = 0; - - return NT_STATUS_OK; -} - -/******************************************************************* - _samr_QueryDomainInfo - ********************************************************************/ - -NTSTATUS _samr_QueryDomainInfo(struct pipes_struct *p, - struct samr_QueryDomainInfo *r) -{ - NTSTATUS status = NT_STATUS_OK; - struct samr_domain_info *dinfo; - union samr_DomainInfo *dom_info; - - uint32_t acc_required; - - DEBUG(5,("_samr_QueryDomainInfo: %d\n", __LINE__)); - - switch (r->in.level) { - case 1: /* DomainPasswordInformation */ - case 12: /* DomainLockoutInformation */ - /* DOMAIN_READ_PASSWORD_PARAMETERS */ - acc_required = SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1; - break; - case 11: /* DomainGeneralInformation2 */ - /* DOMAIN_READ_PASSWORD_PARAMETERS | - * DOMAIN_READ_OTHER_PARAMETERS */ - acc_required = SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 | - SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2; - break; - case 2: /* DomainGeneralInformation */ - case 3: /* DomainLogoffInformation */ - case 4: /* DomainOemInformation */ - case 5: /* DomainReplicationInformation */ - case 6: /* DomainReplicationInformation */ - case 7: /* DomainServerRoleInformation */ - case 8: /* DomainModifiedInformation */ - case 9: /* DomainStateInformation */ - case 10: /* DomainUasInformation */ - case 13: /* DomainModifiedInformation2 */ - /* DOMAIN_READ_OTHER_PARAMETERS */ - acc_required = SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2; - break; - default: - return NT_STATUS_INVALID_INFO_CLASS; - } - - dinfo = policy_handle_find(p, r->in.domain_handle, - acc_required, NULL, - struct samr_domain_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - dom_info = TALLOC_ZERO_P(p->mem_ctx, union samr_DomainInfo); - if (!dom_info) { - return NT_STATUS_NO_MEMORY; - } - - switch (r->in.level) { - case 1: - status = query_dom_info_1(p->mem_ctx, &dom_info->info1); - break; - case 2: - status = query_dom_info_2(p->mem_ctx, &dom_info->general, dinfo); - break; - case 3: - status = query_dom_info_3(p->mem_ctx, &dom_info->info3); - break; - case 4: - status = query_dom_info_4(p->mem_ctx, &dom_info->oem); - break; - case 5: - status = query_dom_info_5(p->mem_ctx, &dom_info->info5); - break; - case 6: - status = query_dom_info_6(p->mem_ctx, &dom_info->info6); - break; - case 7: - status = query_dom_info_7(p->mem_ctx, &dom_info->info7); - break; - case 8: - status = query_dom_info_8(p->mem_ctx, &dom_info->info8); - break; - case 9: - status = query_dom_info_9(p->mem_ctx, &dom_info->info9); - break; - case 11: - status = query_dom_info_11(p->mem_ctx, &dom_info->general2, dinfo); - break; - case 12: - status = query_dom_info_12(p->mem_ctx, &dom_info->info12); - break; - case 13: - status = query_dom_info_13(p->mem_ctx, &dom_info->info13); - break; - default: - return NT_STATUS_INVALID_INFO_CLASS; - } - - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - *r->out.info = dom_info; - - DEBUG(5,("_samr_QueryDomainInfo: %d\n", __LINE__)); - - return status; -} - -/* W2k3 seems to use the same check for all 3 objects that can be created via - * SAMR, if you try to create for example "Dialup" as an alias it says - * "NT_STATUS_USER_EXISTS". This is racy, but we can't really lock the user - * database. */ - -static NTSTATUS can_create(TALLOC_CTX *mem_ctx, const char *new_name) -{ - enum lsa_SidType type; - bool result; - - DEBUG(10, ("Checking whether [%s] can be created\n", new_name)); - - become_root(); - /* Lookup in our local databases (LOOKUP_NAME_REMOTE not set) - * whether the name already exists */ - result = lookup_name(mem_ctx, new_name, LOOKUP_NAME_LOCAL, - NULL, NULL, NULL, &type); - unbecome_root(); - - if (!result) { - DEBUG(10, ("%s does not exist, can create it\n", new_name)); - return NT_STATUS_OK; - } - - DEBUG(5, ("trying to create %s, exists as %s\n", - new_name, sid_type_lookup(type))); - - if (type == SID_NAME_DOM_GRP) { - return NT_STATUS_GROUP_EXISTS; - } - if (type == SID_NAME_ALIAS) { - return NT_STATUS_ALIAS_EXISTS; - } - - /* Yes, the default is NT_STATUS_USER_EXISTS */ - return NT_STATUS_USER_EXISTS; -} - -/******************************************************************* - _samr_CreateUser2 - ********************************************************************/ - -NTSTATUS _samr_CreateUser2(struct pipes_struct *p, - struct samr_CreateUser2 *r) -{ - const char *account = NULL; - struct dom_sid sid; - uint32_t acb_info = r->in.acct_flags; - struct samr_domain_info *dinfo; - struct samr_user_info *uinfo; - NTSTATUS nt_status; - uint32 acc_granted; - struct security_descriptor *psd; - size_t sd_size; - /* check this, when giving away 'add computer to domain' privs */ - uint32 des_access = GENERIC_RIGHTS_USER_ALL_ACCESS; - bool can_add_account = False; - - /* Which privilege is needed to override the ACL? */ - enum sec_privilege needed_priv = SEC_PRIV_INVALID; - - dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_CREATE_USER, NULL, - struct samr_domain_info, &nt_status); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } - - if (sid_check_is_builtin(&dinfo->sid)) { - DEBUG(5,("_samr_CreateUser2: Refusing user create in BUILTIN\n")); - return NT_STATUS_ACCESS_DENIED; - } - - if (!(acb_info == ACB_NORMAL || acb_info == ACB_DOMTRUST || - acb_info == ACB_WSTRUST || acb_info == ACB_SVRTRUST)) { - /* Match Win2k, and return NT_STATUS_INVALID_PARAMETER if - this parameter is not an account type */ - return NT_STATUS_INVALID_PARAMETER; - } - - account = r->in.account_name->string; - if (account == NULL) { - return NT_STATUS_NO_MEMORY; - } - - nt_status = can_create(p->mem_ctx, account); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } - - /* determine which user right we need to check based on the acb_info */ - - if (geteuid() == sec_initial_uid()) { - can_add_account = true; - } else if (acb_info & ACB_WSTRUST) { - needed_priv = SEC_PRIV_MACHINE_ACCOUNT; - can_add_account = security_token_has_privilege(p->server_info->security_token, SEC_PRIV_MACHINE_ACCOUNT); - } else if (acb_info & ACB_NORMAL && - (account[strlen(account)-1] != '$')) { - /* usrmgr.exe (and net rpc trustdom grant) creates a normal user - account for domain trusts and changes the ACB flags later */ - needed_priv = SEC_PRIV_ADD_USERS; - can_add_account = security_token_has_privilege(p->server_info->security_token, SEC_PRIV_ADD_USERS); - } else if (lp_enable_privileges()) { - /* implicit assumption of a BDC or domain trust account here - * (we already check the flags earlier) */ - /* only Domain Admins can add a BDC or domain trust */ - can_add_account = nt_token_check_domain_rid( - p->server_info->security_token, - DOMAIN_RID_ADMINS ); - } - - DEBUG(5, ("_samr_CreateUser2: %s can add this account : %s\n", - uidtoname(p->server_info->utok.uid), - can_add_account ? "True":"False" )); - - if (!can_add_account) { - return NT_STATUS_ACCESS_DENIED; - } - - /********** BEGIN Admin BLOCK **********/ - - become_root(); - nt_status = pdb_create_user(p->mem_ctx, account, acb_info, - r->out.rid); - unbecome_root(); - - /********** END Admin BLOCK **********/ - - /* now check for failure */ - - if ( !NT_STATUS_IS_OK(nt_status) ) - return nt_status; - - /* Get the user's SID */ - - sid_compose(&sid, get_global_sam_sid(), *r->out.rid); - - map_max_allowed_access(p->server_info->security_token, - &p->server_info->utok, - &des_access); - - make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, - &sid, SAMR_USR_RIGHTS_WRITE_PW); - se_map_generic(&des_access, &usr_generic_mapping); - - /* - * JRA - TESTME. We just created this user so we - * had rights to create them. Do we need to check - * any further access on this object ? Can't we - * just assume we have all the rights we need ? - */ - - nt_status = access_check_object(psd, p->server_info->security_token, - needed_priv, SEC_PRIV_INVALID, - GENERIC_RIGHTS_USER_WRITE, des_access, - &acc_granted, "_samr_CreateUser2"); - - if ( !NT_STATUS_IS_OK(nt_status) ) { - return nt_status; - } - - uinfo = policy_handle_create(p, r->out.user_handle, acc_granted, - struct samr_user_info, &nt_status); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } - uinfo->sid = sid; - - /* After a "set" ensure we have no cached display info. */ - force_flush_samr_cache(&sid); - - *r->out.access_granted = acc_granted; - - return NT_STATUS_OK; -} - -/**************************************************************** -****************************************************************/ - -NTSTATUS _samr_CreateUser(struct pipes_struct *p, - struct samr_CreateUser *r) -{ - struct samr_CreateUser2 c; - uint32_t access_granted; - - c.in.domain_handle = r->in.domain_handle; - c.in.account_name = r->in.account_name; - c.in.acct_flags = ACB_NORMAL; - c.in.access_mask = r->in.access_mask; - c.out.user_handle = r->out.user_handle; - c.out.access_granted = &access_granted; - c.out.rid = r->out.rid; - - return _samr_CreateUser2(p, &c); -} - -/******************************************************************* - _samr_Connect - ********************************************************************/ - -NTSTATUS _samr_Connect(struct pipes_struct *p, - struct samr_Connect *r) -{ - struct samr_connect_info *info; - uint32_t acc_granted; - struct policy_handle hnd; - uint32 des_access = r->in.access_mask; - NTSTATUS status; - - /* Access check */ - - if (!pipe_access_check(p)) { - DEBUG(3, ("access denied to _samr_Connect\n")); - return NT_STATUS_ACCESS_DENIED; - } - - /* don't give away the farm but this is probably ok. The SAMR_ACCESS_ENUM_DOMAINS - was observed from a win98 client trying to enumerate users (when configured - user level access control on shares) --jerry */ - - map_max_allowed_access(p->server_info->security_token, - &p->server_info->utok, - &des_access); - - se_map_generic( &des_access, &sam_generic_mapping ); - - acc_granted = des_access & (SAMR_ACCESS_ENUM_DOMAINS - |SAMR_ACCESS_LOOKUP_DOMAIN); - - /* set up the SAMR connect_anon response */ - - info = policy_handle_create(p, &hnd, acc_granted, - struct samr_connect_info, - &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - *r->out.connect_handle = hnd; - return NT_STATUS_OK; -} - -/******************************************************************* - _samr_Connect2 - ********************************************************************/ - -NTSTATUS _samr_Connect2(struct pipes_struct *p, - struct samr_Connect2 *r) -{ - struct samr_connect_info *info = NULL; - struct policy_handle hnd; - struct security_descriptor *psd = NULL; - uint32 acc_granted; - uint32 des_access = r->in.access_mask; - NTSTATUS nt_status; - size_t sd_size; - const char *fn = "_samr_Connect2"; - - switch (p->opnum) { - case NDR_SAMR_CONNECT2: - fn = "_samr_Connect2"; - break; - case NDR_SAMR_CONNECT3: - fn = "_samr_Connect3"; - break; - case NDR_SAMR_CONNECT4: - fn = "_samr_Connect4"; - break; - case NDR_SAMR_CONNECT5: - fn = "_samr_Connect5"; - break; - } - - DEBUG(5,("%s: %d\n", fn, __LINE__)); - - /* Access check */ - - if (!pipe_access_check(p)) { - DEBUG(3, ("access denied to %s\n", fn)); - return NT_STATUS_ACCESS_DENIED; - } - - map_max_allowed_access(p->server_info->security_token, - &p->server_info->utok, - &des_access); - - make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &sam_generic_mapping, NULL, 0); - se_map_generic(&des_access, &sam_generic_mapping); - - nt_status = access_check_object(psd, p->server_info->security_token, - SEC_PRIV_INVALID, SEC_PRIV_INVALID, - 0, des_access, &acc_granted, fn); - - if ( !NT_STATUS_IS_OK(nt_status) ) - return nt_status; - - info = policy_handle_create(p, &hnd, acc_granted, - struct samr_connect_info, &nt_status); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } - - DEBUG(5,("%s: %d\n", fn, __LINE__)); - - *r->out.connect_handle = hnd; - return NT_STATUS_OK; -} - -/**************************************************************** - _samr_Connect3 -****************************************************************/ - -NTSTATUS _samr_Connect3(struct pipes_struct *p, - struct samr_Connect3 *r) -{ - struct samr_Connect2 c; - - c.in.system_name = r->in.system_name; - c.in.access_mask = r->in.access_mask; - c.out.connect_handle = r->out.connect_handle; - - return _samr_Connect2(p, &c); -} - -/******************************************************************* - _samr_Connect4 - ********************************************************************/ - -NTSTATUS _samr_Connect4(struct pipes_struct *p, - struct samr_Connect4 *r) -{ - struct samr_Connect2 c; - - c.in.system_name = r->in.system_name; - c.in.access_mask = r->in.access_mask; - c.out.connect_handle = r->out.connect_handle; - - return _samr_Connect2(p, &c); -} - -/******************************************************************* - _samr_Connect5 - ********************************************************************/ - -NTSTATUS _samr_Connect5(struct pipes_struct *p, - struct samr_Connect5 *r) -{ - NTSTATUS status; - struct samr_Connect2 c; - struct samr_ConnectInfo1 info1; - - info1.client_version = SAMR_CONNECT_AFTER_W2K; - info1.unknown2 = 0; - - c.in.system_name = r->in.system_name; - c.in.access_mask = r->in.access_mask; - c.out.connect_handle = r->out.connect_handle; - - *r->out.level_out = 1; - - status = _samr_Connect2(p, &c); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - r->out.info_out->info1 = info1; - - return NT_STATUS_OK; -} - -/********************************************************************** - _samr_LookupDomain - **********************************************************************/ - -NTSTATUS _samr_LookupDomain(struct pipes_struct *p, - struct samr_LookupDomain *r) -{ - NTSTATUS status; - struct samr_connect_info *info; - const char *domain_name; - struct dom_sid *sid = NULL; - - /* win9x user manager likes to use SAMR_ACCESS_ENUM_DOMAINS here. - Reverted that change so we will work with RAS servers again */ - - info = policy_handle_find(p, r->in.connect_handle, - SAMR_ACCESS_LOOKUP_DOMAIN, NULL, - struct samr_connect_info, - &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - domain_name = r->in.domain_name->string; - if (!domain_name) { - return NT_STATUS_INVALID_PARAMETER; - } - - sid = TALLOC_ZERO_P(p->mem_ctx, struct dom_sid2); - if (!sid) { - return NT_STATUS_NO_MEMORY; - } - - if (strequal(domain_name, builtin_domain_name())) { - sid_copy(sid, &global_sid_Builtin); - } else { - if (!secrets_fetch_domain_sid(domain_name, sid)) { - status = NT_STATUS_NO_SUCH_DOMAIN; - } - } - - DEBUG(2,("Returning domain sid for domain %s -> %s\n", domain_name, - sid_string_dbg(sid))); - - *r->out.sid = sid; - - return status; -} - -/********************************************************************** - _samr_EnumDomains - **********************************************************************/ - -NTSTATUS _samr_EnumDomains(struct pipes_struct *p, - struct samr_EnumDomains *r) -{ - NTSTATUS status; - struct samr_connect_info *info; - uint32_t num_entries = 2; - struct samr_SamEntry *entry_array = NULL; - struct samr_SamArray *sam; - - info = policy_handle_find(p, r->in.connect_handle, - SAMR_ACCESS_ENUM_DOMAINS, NULL, - struct samr_connect_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - sam = TALLOC_ZERO_P(p->mem_ctx, struct samr_SamArray); - if (!sam) { - return NT_STATUS_NO_MEMORY; - } - - entry_array = TALLOC_ZERO_ARRAY(p->mem_ctx, - struct samr_SamEntry, - num_entries); - if (!entry_array) { - return NT_STATUS_NO_MEMORY; - } - - entry_array[0].idx = 0; - init_lsa_String(&entry_array[0].name, get_global_sam_name()); - - entry_array[1].idx = 1; - init_lsa_String(&entry_array[1].name, "Builtin"); - - sam->count = num_entries; - sam->entries = entry_array; - - *r->out.sam = sam; - *r->out.num_entries = num_entries; - - return status; -} - -/******************************************************************* - _samr_OpenAlias - ********************************************************************/ - -NTSTATUS _samr_OpenAlias(struct pipes_struct *p, - struct samr_OpenAlias *r) -{ - struct dom_sid sid; - uint32 alias_rid = r->in.rid; - struct samr_alias_info *ainfo; - struct samr_domain_info *dinfo; - struct security_descriptor *psd = NULL; - uint32 acc_granted; - uint32 des_access = r->in.access_mask; - size_t sd_size; - NTSTATUS status; - - dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, NULL, - struct samr_domain_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - /* append the alias' RID to it */ - - if (!sid_compose(&sid, &dinfo->sid, alias_rid)) - return NT_STATUS_NO_SUCH_ALIAS; - - /*check if access can be granted as requested by client. */ - - map_max_allowed_access(p->server_info->security_token, - &p->server_info->utok, - &des_access); - - make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &ali_generic_mapping, NULL, 0); - se_map_generic(&des_access,&ali_generic_mapping); - - status = access_check_object(psd, p->server_info->security_token, - SEC_PRIV_ADD_USERS, SEC_PRIV_INVALID, - GENERIC_RIGHTS_ALIAS_ALL_ACCESS, - des_access, &acc_granted, "_samr_OpenAlias"); - - if ( !NT_STATUS_IS_OK(status) ) - return status; - - { - /* Check we actually have the requested alias */ - enum lsa_SidType type; - bool result; - gid_t gid; - - become_root(); - result = lookup_sid(NULL, &sid, NULL, NULL, &type); - unbecome_root(); - - if (!result || (type != SID_NAME_ALIAS)) { - return NT_STATUS_NO_SUCH_ALIAS; - } - - /* make sure there is a mapping */ - - if ( !sid_to_gid( &sid, &gid ) ) { - return NT_STATUS_NO_SUCH_ALIAS; - } - - } - - ainfo = policy_handle_create(p, r->out.alias_handle, acc_granted, - struct samr_alias_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - ainfo->sid = sid; - - return NT_STATUS_OK; -} - -/******************************************************************* - set_user_info_2 - ********************************************************************/ - -static NTSTATUS set_user_info_2(TALLOC_CTX *mem_ctx, - struct samr_UserInfo2 *id2, - struct samu *pwd) -{ - if (id2 == NULL) { - DEBUG(5,("set_user_info_2: NULL id2\n")); - return NT_STATUS_ACCESS_DENIED; - } - - copy_id2_to_sam_passwd(pwd, id2); - - return pdb_update_sam_account(pwd); -} - -/******************************************************************* - set_user_info_4 - ********************************************************************/ - -static NTSTATUS set_user_info_4(TALLOC_CTX *mem_ctx, - struct samr_UserInfo4 *id4, - struct samu *pwd) -{ - if (id4 == NULL) { - DEBUG(5,("set_user_info_2: NULL id4\n")); - return NT_STATUS_ACCESS_DENIED; - } - - copy_id4_to_sam_passwd(pwd, id4); - - return pdb_update_sam_account(pwd); -} - -/******************************************************************* - set_user_info_6 - ********************************************************************/ - -static NTSTATUS set_user_info_6(TALLOC_CTX *mem_ctx, - struct samr_UserInfo6 *id6, - struct samu *pwd) -{ - if (id6 == NULL) { - DEBUG(5,("set_user_info_6: NULL id6\n")); - return NT_STATUS_ACCESS_DENIED; - } - - copy_id6_to_sam_passwd(pwd, id6); - - return pdb_update_sam_account(pwd); -} - -/******************************************************************* - set_user_info_7 - ********************************************************************/ - -static NTSTATUS set_user_info_7(TALLOC_CTX *mem_ctx, - struct samr_UserInfo7 *id7, - struct samu *pwd) -{ - NTSTATUS rc; - - if (id7 == NULL) { - DEBUG(5, ("set_user_info_7: NULL id7\n")); - return NT_STATUS_ACCESS_DENIED; - } - - if (!id7->account_name.string) { - DEBUG(5, ("set_user_info_7: failed to get new username\n")); - return NT_STATUS_ACCESS_DENIED; - } - - /* check to see if the new username already exists. Note: we can't - reliably lock all backends, so there is potentially the - possibility that a user can be created in between this check and - the rename. The rename should fail, but may not get the - exact same failure status code. I think this is small enough - of a window for this type of operation and the results are - simply that the rename fails with a slightly different status - code (like UNSUCCESSFUL instead of ALREADY_EXISTS). */ - - rc = can_create(mem_ctx, id7->account_name.string); - - /* when there is nothing to change, we're done here */ - if (NT_STATUS_EQUAL(rc, NT_STATUS_USER_EXISTS) && - strequal(id7->account_name.string, pdb_get_username(pwd))) { - return NT_STATUS_OK; - } - if (!NT_STATUS_IS_OK(rc)) { - return rc; - } - - rc = pdb_rename_sam_account(pwd, id7->account_name.string); - - return rc; -} - -/******************************************************************* - set_user_info_8 - ********************************************************************/ - -static NTSTATUS set_user_info_8(TALLOC_CTX *mem_ctx, - struct samr_UserInfo8 *id8, - struct samu *pwd) -{ - if (id8 == NULL) { - DEBUG(5,("set_user_info_8: NULL id8\n")); - return NT_STATUS_ACCESS_DENIED; - } - - copy_id8_to_sam_passwd(pwd, id8); - - return pdb_update_sam_account(pwd); -} - -/******************************************************************* - set_user_info_10 - ********************************************************************/ - -static NTSTATUS set_user_info_10(TALLOC_CTX *mem_ctx, - struct samr_UserInfo10 *id10, - struct samu *pwd) -{ - if (id10 == NULL) { - DEBUG(5,("set_user_info_8: NULL id10\n")); - return NT_STATUS_ACCESS_DENIED; - } - - copy_id10_to_sam_passwd(pwd, id10); - - return pdb_update_sam_account(pwd); -} - -/******************************************************************* - set_user_info_11 - ********************************************************************/ - -static NTSTATUS set_user_info_11(TALLOC_CTX *mem_ctx, - struct samr_UserInfo11 *id11, - struct samu *pwd) -{ - if (id11 == NULL) { - DEBUG(5,("set_user_info_11: NULL id11\n")); - return NT_STATUS_ACCESS_DENIED; - } - - copy_id11_to_sam_passwd(pwd, id11); - - return pdb_update_sam_account(pwd); -} - -/******************************************************************* - set_user_info_12 - ********************************************************************/ - -static NTSTATUS set_user_info_12(TALLOC_CTX *mem_ctx, - struct samr_UserInfo12 *id12, - struct samu *pwd) -{ - if (id12 == NULL) { - DEBUG(5,("set_user_info_12: NULL id12\n")); - return NT_STATUS_ACCESS_DENIED; - } - - copy_id12_to_sam_passwd(pwd, id12); - - return pdb_update_sam_account(pwd); -} - -/******************************************************************* - set_user_info_13 - ********************************************************************/ - -static NTSTATUS set_user_info_13(TALLOC_CTX *mem_ctx, - struct samr_UserInfo13 *id13, - struct samu *pwd) -{ - if (id13 == NULL) { - DEBUG(5,("set_user_info_13: NULL id13\n")); - return NT_STATUS_ACCESS_DENIED; - } - - copy_id13_to_sam_passwd(pwd, id13); - - return pdb_update_sam_account(pwd); -} - -/******************************************************************* - set_user_info_14 - ********************************************************************/ - -static NTSTATUS set_user_info_14(TALLOC_CTX *mem_ctx, - struct samr_UserInfo14 *id14, - struct samu *pwd) -{ - if (id14 == NULL) { - DEBUG(5,("set_user_info_14: NULL id14\n")); - return NT_STATUS_ACCESS_DENIED; - } - - copy_id14_to_sam_passwd(pwd, id14); - - return pdb_update_sam_account(pwd); -} - -/******************************************************************* - set_user_info_16 - ********************************************************************/ - -static NTSTATUS set_user_info_16(TALLOC_CTX *mem_ctx, - struct samr_UserInfo16 *id16, - struct samu *pwd) -{ - if (id16 == NULL) { - DEBUG(5,("set_user_info_16: NULL id16\n")); - return NT_STATUS_ACCESS_DENIED; - } - - copy_id16_to_sam_passwd(pwd, id16); - - return pdb_update_sam_account(pwd); -} - -/******************************************************************* - set_user_info_17 - ********************************************************************/ - -static NTSTATUS set_user_info_17(TALLOC_CTX *mem_ctx, - struct samr_UserInfo17 *id17, - struct samu *pwd) -{ - if (id17 == NULL) { - DEBUG(5,("set_user_info_17: NULL id17\n")); - return NT_STATUS_ACCESS_DENIED; - } - - copy_id17_to_sam_passwd(pwd, id17); - - return pdb_update_sam_account(pwd); -} - -/******************************************************************* - set_user_info_18 - ********************************************************************/ - -static NTSTATUS set_user_info_18(struct samr_UserInfo18 *id18, - TALLOC_CTX *mem_ctx, - DATA_BLOB *session_key, - struct samu *pwd) -{ - if (id18 == NULL) { - DEBUG(2, ("set_user_info_18: id18 is NULL\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - if (id18->nt_pwd_active || id18->lm_pwd_active) { - if (!session_key->length) { - return NT_STATUS_NO_USER_SESSION_KEY; - } - } - - if (id18->nt_pwd_active) { - - DATA_BLOB in, out; - - in = data_blob_const(id18->nt_pwd.hash, 16); - out = data_blob_talloc_zero(mem_ctx, 16); - - sess_crypt_blob(&out, &in, session_key, false); - - if (!pdb_set_nt_passwd(pwd, out.data, PDB_CHANGED)) { - return NT_STATUS_ACCESS_DENIED; - } - - pdb_set_pass_last_set_time(pwd, time(NULL), PDB_CHANGED); - } - - if (id18->lm_pwd_active) { - - DATA_BLOB in, out; - - in = data_blob_const(id18->lm_pwd.hash, 16); - out = data_blob_talloc_zero(mem_ctx, 16); - - sess_crypt_blob(&out, &in, session_key, false); - - if (!pdb_set_lanman_passwd(pwd, out.data, PDB_CHANGED)) { - return NT_STATUS_ACCESS_DENIED; - } - - pdb_set_pass_last_set_time(pwd, time(NULL), PDB_CHANGED); - } - - copy_id18_to_sam_passwd(pwd, id18); - - return pdb_update_sam_account(pwd); -} - -/******************************************************************* - set_user_info_20 - ********************************************************************/ - -static NTSTATUS set_user_info_20(TALLOC_CTX *mem_ctx, - struct samr_UserInfo20 *id20, - struct samu *pwd) -{ - if (id20 == NULL) { - DEBUG(5,("set_user_info_20: NULL id20\n")); - return NT_STATUS_ACCESS_DENIED; - } - - copy_id20_to_sam_passwd(pwd, id20); - - return pdb_update_sam_account(pwd); -} - -/******************************************************************* - set_user_info_21 - ********************************************************************/ - -static NTSTATUS set_user_info_21(struct samr_UserInfo21 *id21, - TALLOC_CTX *mem_ctx, - DATA_BLOB *session_key, - struct samu *pwd) -{ - NTSTATUS status; - - if (id21 == NULL) { - DEBUG(5, ("set_user_info_21: NULL id21\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - if (id21->fields_present == 0) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (id21->fields_present & SAMR_FIELD_LAST_PWD_CHANGE) { - return NT_STATUS_ACCESS_DENIED; - } - - if (id21->fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) { - if (id21->nt_password_set) { - DATA_BLOB in, out; - - if ((id21->nt_owf_password.length != 16) || - (id21->nt_owf_password.size != 16)) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (!session_key->length) { - return NT_STATUS_NO_USER_SESSION_KEY; - } - - in = data_blob_const(id21->nt_owf_password.array, 16); - out = data_blob_talloc_zero(mem_ctx, 16); - - sess_crypt_blob(&out, &in, session_key, false); - - pdb_set_nt_passwd(pwd, out.data, PDB_CHANGED); - pdb_set_pass_last_set_time(pwd, time(NULL), PDB_CHANGED); - } - } - - if (id21->fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) { - if (id21->lm_password_set) { - DATA_BLOB in, out; - - if ((id21->lm_owf_password.length != 16) || - (id21->lm_owf_password.size != 16)) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (!session_key->length) { - return NT_STATUS_NO_USER_SESSION_KEY; - } - - in = data_blob_const(id21->lm_owf_password.array, 16); - out = data_blob_talloc_zero(mem_ctx, 16); - - sess_crypt_blob(&out, &in, session_key, false); - - pdb_set_lanman_passwd(pwd, out.data, PDB_CHANGED); - pdb_set_pass_last_set_time(pwd, time(NULL), PDB_CHANGED); - } - } - - /* we need to separately check for an account rename first */ - - if (id21->account_name.string && - (!strequal(id21->account_name.string, pdb_get_username(pwd)))) - { - - /* check to see if the new username already exists. Note: we can't - reliably lock all backends, so there is potentially the - possibility that a user can be created in between this check and - the rename. The rename should fail, but may not get the - exact same failure status code. I think this is small enough - of a window for this type of operation and the results are - simply that the rename fails with a slightly different status - code (like UNSUCCESSFUL instead of ALREADY_EXISTS). */ - - status = can_create(mem_ctx, id21->account_name.string); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = pdb_rename_sam_account(pwd, id21->account_name.string); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("set_user_info_21: failed to rename account: %s\n", - nt_errstr(status))); - return status; - } - - /* set the new username so that later - functions can work on the new account */ - pdb_set_username(pwd, id21->account_name.string, PDB_SET); - } - - copy_id21_to_sam_passwd("INFO_21", pwd, id21); - - /* - * The funny part about the previous two calls is - * that pwd still has the password hashes from the - * passdb entry. These have not been updated from - * id21. I don't know if they need to be set. --jerry - */ - - if ( IS_SAM_CHANGED(pwd, PDB_GROUPSID) ) { - status = pdb_set_unix_primary_group(mem_ctx, pwd); - if ( !NT_STATUS_IS_OK(status) ) { - return status; - } - } - - /* Don't worry about writing out the user account since the - primary group SID is generated solely from the user's Unix - primary group. */ - - /* write the change out */ - if(!NT_STATUS_IS_OK(status = pdb_update_sam_account(pwd))) { - return status; - } - - return NT_STATUS_OK; -} - -/******************************************************************* - set_user_info_23 - ********************************************************************/ - -static NTSTATUS set_user_info_23(TALLOC_CTX *mem_ctx, - struct samr_UserInfo23 *id23, - const char *rhost, - struct samu *pwd) -{ - char *plaintext_buf = NULL; - size_t len = 0; - uint32_t acct_ctrl; - NTSTATUS status; - - if (id23 == NULL) { - DEBUG(5, ("set_user_info_23: NULL id23\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - if (id23->info.fields_present == 0) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (id23->info.fields_present & SAMR_FIELD_LAST_PWD_CHANGE) { - return NT_STATUS_ACCESS_DENIED; - } - - if ((id23->info.fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) || - (id23->info.fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT)) { - - DEBUG(5, ("Attempting administrator password change (level 23) for user %s\n", - pdb_get_username(pwd))); - - if (!decode_pw_buffer(mem_ctx, - id23->password.data, - &plaintext_buf, - &len, - CH_UTF16)) { - return NT_STATUS_WRONG_PASSWORD; - } - - if (!pdb_set_plaintext_passwd (pwd, plaintext_buf)) { - return NT_STATUS_ACCESS_DENIED; - } - } - - copy_id23_to_sam_passwd(pwd, id23); - - acct_ctrl = pdb_get_acct_ctrl(pwd); - - /* if it's a trust account, don't update /etc/passwd */ - if ( ( (acct_ctrl & ACB_DOMTRUST) == ACB_DOMTRUST ) || - ( (acct_ctrl & ACB_WSTRUST) == ACB_WSTRUST) || - ( (acct_ctrl & ACB_SVRTRUST) == ACB_SVRTRUST) ) { - DEBUG(5, ("Changing trust account. Not updating /etc/passwd\n")); - } else if (plaintext_buf) { - /* update the UNIX password */ - if (lp_unix_password_sync() ) { - struct passwd *passwd; - if (pdb_get_username(pwd) == NULL) { - DEBUG(1, ("chgpasswd: User without name???\n")); - return NT_STATUS_ACCESS_DENIED; - } - - passwd = Get_Pwnam_alloc(pwd, pdb_get_username(pwd)); - if (passwd == NULL) { - DEBUG(1, ("chgpasswd: Username does not exist in system !?!\n")); - } - - if(!chgpasswd(pdb_get_username(pwd), rhost, - passwd, "", plaintext_buf, True)) { - return NT_STATUS_ACCESS_DENIED; - } - TALLOC_FREE(passwd); - } - } - - if (plaintext_buf) { - memset(plaintext_buf, '\0', strlen(plaintext_buf)); - } - - if (IS_SAM_CHANGED(pwd, PDB_GROUPSID) && - (!NT_STATUS_IS_OK(status = pdb_set_unix_primary_group(mem_ctx, - pwd)))) { - return status; - } - - if(!NT_STATUS_IS_OK(status = pdb_update_sam_account(pwd))) { - return status; - } - - return NT_STATUS_OK; -} - -/******************************************************************* - set_user_info_pw - ********************************************************************/ - -static bool set_user_info_pw(uint8 *pass, const char *rhost, struct samu *pwd) -{ - size_t len = 0; - char *plaintext_buf = NULL; - uint32 acct_ctrl; - - DEBUG(5, ("Attempting administrator password change for user %s\n", - pdb_get_username(pwd))); - - acct_ctrl = pdb_get_acct_ctrl(pwd); - - if (!decode_pw_buffer(talloc_tos(), - pass, - &plaintext_buf, - &len, - CH_UTF16)) { - return False; - } - - if (!pdb_set_plaintext_passwd (pwd, plaintext_buf)) { - return False; - } - - /* if it's a trust account, don't update /etc/passwd */ - if ( ( (acct_ctrl & ACB_DOMTRUST) == ACB_DOMTRUST ) || - ( (acct_ctrl & ACB_WSTRUST) == ACB_WSTRUST) || - ( (acct_ctrl & ACB_SVRTRUST) == ACB_SVRTRUST) ) { - DEBUG(5, ("Changing trust account or non-unix-user password, not updating /etc/passwd\n")); - } else { - /* update the UNIX password */ - if (lp_unix_password_sync()) { - struct passwd *passwd; - - if (pdb_get_username(pwd) == NULL) { - DEBUG(1, ("chgpasswd: User without name???\n")); - return False; - } - - passwd = Get_Pwnam_alloc(pwd, pdb_get_username(pwd)); - if (passwd == NULL) { - DEBUG(1, ("chgpasswd: Username does not exist in system !?!\n")); - } - - if(!chgpasswd(pdb_get_username(pwd), rhost, passwd, - "", plaintext_buf, True)) { - return False; - } - TALLOC_FREE(passwd); - } - } - - memset(plaintext_buf, '\0', strlen(plaintext_buf)); - - DEBUG(5,("set_user_info_pw: pdb_update_pwd()\n")); - - return True; -} - -/******************************************************************* - set_user_info_24 - ********************************************************************/ - -static NTSTATUS set_user_info_24(TALLOC_CTX *mem_ctx, - const char *rhost, - struct samr_UserInfo24 *id24, - struct samu *pwd) -{ - NTSTATUS status; - - if (id24 == NULL) { - DEBUG(5, ("set_user_info_24: NULL id24\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - if (!set_user_info_pw(id24->password.data, rhost, pwd)) { - return NT_STATUS_WRONG_PASSWORD; - } - - copy_id24_to_sam_passwd(pwd, id24); - - status = pdb_update_sam_account(pwd); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - return NT_STATUS_OK; -} - -/******************************************************************* - set_user_info_25 - ********************************************************************/ - -static NTSTATUS set_user_info_25(TALLOC_CTX *mem_ctx, - const char *rhost, - struct samr_UserInfo25 *id25, - struct samu *pwd) -{ - NTSTATUS status; - - if (id25 == NULL) { - DEBUG(5, ("set_user_info_25: NULL id25\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - if (id25->info.fields_present == 0) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (id25->info.fields_present & SAMR_FIELD_LAST_PWD_CHANGE) { - return NT_STATUS_ACCESS_DENIED; - } - - if ((id25->info.fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) || - (id25->info.fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT)) { - - if (!set_user_info_pw(id25->password.data, rhost, pwd)) { - return NT_STATUS_WRONG_PASSWORD; - } - } - - copy_id25_to_sam_passwd(pwd, id25); - - /* write the change out */ - if(!NT_STATUS_IS_OK(status = pdb_update_sam_account(pwd))) { - return status; - } - - /* - * We need to "pdb_update_sam_account" before the unix primary group - * is set, because the idealx scripts would also change the - * sambaPrimaryGroupSid using the ldap replace method. pdb_ldap uses - * the delete explicit / add explicit, which would then fail to find - * the previous primaryGroupSid value. - */ - - if ( IS_SAM_CHANGED(pwd, PDB_GROUPSID) ) { - status = pdb_set_unix_primary_group(mem_ctx, pwd); - if ( !NT_STATUS_IS_OK(status) ) { - return status; - } - } - - return NT_STATUS_OK; -} - -/******************************************************************* - set_user_info_26 - ********************************************************************/ - -static NTSTATUS set_user_info_26(TALLOC_CTX *mem_ctx, - const char *rhost, - struct samr_UserInfo26 *id26, - struct samu *pwd) -{ - NTSTATUS status; - - if (id26 == NULL) { - DEBUG(5, ("set_user_info_26: NULL id26\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - if (!set_user_info_pw(id26->password.data, rhost, pwd)) { - return NT_STATUS_WRONG_PASSWORD; - } - - copy_id26_to_sam_passwd(pwd, id26); - - status = pdb_update_sam_account(pwd); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - return NT_STATUS_OK; -} - -/************************************************************* -**************************************************************/ - -static uint32_t samr_set_user_info_map_fields_to_access_mask(uint32_t fields) -{ - uint32_t acc_required = 0; - - /* USER_ALL_USERNAME */ - if (fields & SAMR_FIELD_ACCOUNT_NAME) - acc_required |= SAMR_USER_ACCESS_SET_ATTRIBUTES; - /* USER_ALL_FULLNAME */ - if (fields & SAMR_FIELD_FULL_NAME) - acc_required |= SAMR_USER_ACCESS_SET_ATTRIBUTES; - /* USER_ALL_PRIMARYGROUPID */ - if (fields & SAMR_FIELD_PRIMARY_GID) - acc_required |= SAMR_USER_ACCESS_SET_ATTRIBUTES; - /* USER_ALL_HOMEDIRECTORY */ - if (fields & SAMR_FIELD_HOME_DIRECTORY) - acc_required |= SAMR_USER_ACCESS_SET_ATTRIBUTES; - /* USER_ALL_HOMEDIRECTORYDRIVE */ - if (fields & SAMR_FIELD_HOME_DRIVE) - acc_required |= SAMR_USER_ACCESS_SET_ATTRIBUTES; - /* USER_ALL_SCRIPTPATH */ - if (fields & SAMR_FIELD_LOGON_SCRIPT) - acc_required |= SAMR_USER_ACCESS_SET_ATTRIBUTES; - /* USER_ALL_PROFILEPATH */ - if (fields & SAMR_FIELD_PROFILE_PATH) - acc_required |= SAMR_USER_ACCESS_SET_ATTRIBUTES; - /* USER_ALL_ADMINCOMMENT */ - if (fields & SAMR_FIELD_COMMENT) - acc_required |= SAMR_USER_ACCESS_SET_ATTRIBUTES; - /* USER_ALL_WORKSTATIONS */ - if (fields & SAMR_FIELD_WORKSTATIONS) - acc_required |= SAMR_USER_ACCESS_SET_ATTRIBUTES; - /* USER_ALL_LOGONHOURS */ - if (fields & SAMR_FIELD_LOGON_HOURS) - acc_required |= SAMR_USER_ACCESS_SET_ATTRIBUTES; - /* USER_ALL_ACCOUNTEXPIRES */ - if (fields & SAMR_FIELD_ACCT_EXPIRY) - acc_required |= SAMR_USER_ACCESS_SET_ATTRIBUTES; - /* USER_ALL_USERACCOUNTCONTROL */ - if (fields & SAMR_FIELD_ACCT_FLAGS) - acc_required |= SAMR_USER_ACCESS_SET_ATTRIBUTES; - /* USER_ALL_PARAMETERS */ - if (fields & SAMR_FIELD_PARAMETERS) - acc_required |= SAMR_USER_ACCESS_SET_ATTRIBUTES; - /* USER_ALL_USERCOMMENT */ - if (fields & SAMR_FIELD_COMMENT) - acc_required |= SAMR_USER_ACCESS_SET_LOC_COM; - /* USER_ALL_COUNTRYCODE */ - if (fields & SAMR_FIELD_COUNTRY_CODE) - acc_required |= SAMR_USER_ACCESS_SET_LOC_COM; - /* USER_ALL_CODEPAGE */ - if (fields & SAMR_FIELD_CODE_PAGE) - acc_required |= SAMR_USER_ACCESS_SET_LOC_COM; - /* USER_ALL_NTPASSWORDPRESENT */ - if (fields & SAMR_FIELD_NT_PASSWORD_PRESENT) - acc_required |= SAMR_USER_ACCESS_SET_PASSWORD; - /* USER_ALL_LMPASSWORDPRESENT */ - if (fields & SAMR_FIELD_LM_PASSWORD_PRESENT) - acc_required |= SAMR_USER_ACCESS_SET_PASSWORD; - /* USER_ALL_PASSWORDEXPIRED */ - if (fields & SAMR_FIELD_EXPIRED_FLAG) - acc_required |= SAMR_USER_ACCESS_SET_PASSWORD; - - return acc_required; -} - -/******************************************************************* - samr_SetUserInfo - ********************************************************************/ - -NTSTATUS _samr_SetUserInfo(struct pipes_struct *p, - struct samr_SetUserInfo *r) -{ - struct samr_user_info *uinfo; - NTSTATUS status; - struct samu *pwd = NULL; - union samr_UserInfo *info = r->in.info; - uint32_t acc_required = 0; - uint32_t fields = 0; - bool ret; - - DEBUG(5,("_samr_SetUserInfo: %d\n", __LINE__)); - - /* This is tricky. A WinXP domain join sets - (SAMR_USER_ACCESS_SET_PASSWORD|SAMR_USER_ACCESS_SET_ATTRIBUTES|SAMR_USER_ACCESS_GET_ATTRIBUTES) - The MMC lusrmgr plugin includes these perms and more in the SamrOpenUser(). But the - standard Win32 API calls just ask for SAMR_USER_ACCESS_SET_PASSWORD in the SamrOpenUser(). - This should be enough for levels 18, 24, 25,& 26. Info level 23 can set more so - we'll use the set from the WinXP join as the basis. */ - - switch (r->in.level) { - case 2: /* UserPreferencesInformation */ - /* USER_WRITE_ACCOUNT | USER_WRITE_PREFERENCES */ - acc_required = SAMR_USER_ACCESS_SET_ATTRIBUTES | SAMR_USER_ACCESS_SET_LOC_COM; - break; - case 4: /* UserLogonHoursInformation */ - case 6: /* UserNameInformation */ - case 7: /* UserAccountNameInformation */ - case 8: /* UserFullNameInformation */ - case 9: /* UserPrimaryGroupInformation */ - case 10: /* UserHomeInformation */ - case 11: /* UserScriptInformation */ - case 12: /* UserProfileInformation */ - case 13: /* UserAdminCommentInformation */ - case 14: /* UserWorkStationsInformation */ - case 16: /* UserControlInformation */ - case 17: /* UserExpiresInformation */ - case 20: /* UserParametersInformation */ - /* USER_WRITE_ACCOUNT */ - acc_required = SAMR_USER_ACCESS_SET_ATTRIBUTES; - break; - case 18: /* UserInternal1Information */ - /* FIXME: gd, this is a guess */ - acc_required = SAMR_USER_ACCESS_SET_PASSWORD; - break; - case 21: /* UserAllInformation */ - fields = info->info21.fields_present; - acc_required = samr_set_user_info_map_fields_to_access_mask(fields); - break; - case 23: /* UserInternal4Information */ - fields = info->info23.info.fields_present; - acc_required = samr_set_user_info_map_fields_to_access_mask(fields); - break; - case 25: /* UserInternal4InformationNew */ - fields = info->info25.info.fields_present; - acc_required = samr_set_user_info_map_fields_to_access_mask(fields); - break; - case 24: /* UserInternal5Information */ - case 26: /* UserInternal5InformationNew */ - acc_required = SAMR_USER_ACCESS_SET_PASSWORD; - break; - default: - return NT_STATUS_INVALID_INFO_CLASS; - } - - uinfo = policy_handle_find(p, r->in.user_handle, acc_required, NULL, - struct samr_user_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - DEBUG(5, ("_samr_SetUserInfo: sid:%s, level:%d\n", - sid_string_dbg(&uinfo->sid), r->in.level)); - - if (info == NULL) { - DEBUG(5, ("_samr_SetUserInfo: NULL info level\n")); - return NT_STATUS_INVALID_INFO_CLASS; - } - - if (!(pwd = samu_new(NULL))) { - return NT_STATUS_NO_MEMORY; - } - - become_root(); - ret = pdb_getsampwsid(pwd, &uinfo->sid); - unbecome_root(); - - if (!ret) { - TALLOC_FREE(pwd); - return NT_STATUS_NO_SUCH_USER; - } - - /* ================ BEGIN Privilege BLOCK ================ */ - - become_root(); - - /* ok! user info levels (lots: see MSDEV help), off we go... */ - - switch (r->in.level) { - - case 2: - status = set_user_info_2(p->mem_ctx, - &info->info2, pwd); - break; - - case 4: - status = set_user_info_4(p->mem_ctx, - &info->info4, pwd); - break; - - case 6: - status = set_user_info_6(p->mem_ctx, - &info->info6, pwd); - break; - - case 7: - status = set_user_info_7(p->mem_ctx, - &info->info7, pwd); - break; - - case 8: - status = set_user_info_8(p->mem_ctx, - &info->info8, pwd); - break; - - case 10: - status = set_user_info_10(p->mem_ctx, - &info->info10, pwd); - break; - - case 11: - status = set_user_info_11(p->mem_ctx, - &info->info11, pwd); - break; - - case 12: - status = set_user_info_12(p->mem_ctx, - &info->info12, pwd); - break; - - case 13: - status = set_user_info_13(p->mem_ctx, - &info->info13, pwd); - break; - - case 14: - status = set_user_info_14(p->mem_ctx, - &info->info14, pwd); - break; - - case 16: - status = set_user_info_16(p->mem_ctx, - &info->info16, pwd); - break; - - case 17: - status = set_user_info_17(p->mem_ctx, - &info->info17, pwd); - break; - - case 18: - /* Used by AS/U JRA. */ - status = set_user_info_18(&info->info18, - p->mem_ctx, - &p->server_info->user_session_key, - pwd); - break; - - case 20: - status = set_user_info_20(p->mem_ctx, - &info->info20, pwd); - break; - - case 21: - status = set_user_info_21(&info->info21, - p->mem_ctx, - &p->server_info->user_session_key, - pwd); - break; - - case 23: - if (!p->server_info->user_session_key.length) { - status = NT_STATUS_NO_USER_SESSION_KEY; - } - arcfour_crypt_blob(info->info23.password.data, 516, - &p->server_info->user_session_key); - - dump_data(100, info->info23.password.data, 516); - - status = set_user_info_23(p->mem_ctx, - &info->info23, - p->client_id->name, - pwd); - break; - - case 24: - if (!p->server_info->user_session_key.length) { - status = NT_STATUS_NO_USER_SESSION_KEY; - } - arcfour_crypt_blob(info->info24.password.data, - 516, - &p->server_info->user_session_key); - - dump_data(100, info->info24.password.data, 516); - - status = set_user_info_24(p->mem_ctx, - p->client_id->name, - &info->info24, pwd); - break; - - case 25: - if (!p->server_info->user_session_key.length) { - status = NT_STATUS_NO_USER_SESSION_KEY; - } - encode_or_decode_arc4_passwd_buffer( - info->info25.password.data, - &p->server_info->user_session_key); - - dump_data(100, info->info25.password.data, 532); - - status = set_user_info_25(p->mem_ctx, - p->client_id->name, - &info->info25, pwd); - break; - - case 26: - if (!p->server_info->user_session_key.length) { - status = NT_STATUS_NO_USER_SESSION_KEY; - } - encode_or_decode_arc4_passwd_buffer( - info->info26.password.data, - &p->server_info->user_session_key); - - dump_data(100, info->info26.password.data, 516); - - status = set_user_info_26(p->mem_ctx, - p->client_id->name, - &info->info26, pwd); - break; - - default: - status = NT_STATUS_INVALID_INFO_CLASS; - } - - TALLOC_FREE(pwd); - - unbecome_root(); - - /* ================ END Privilege BLOCK ================ */ - - if (NT_STATUS_IS_OK(status)) { - force_flush_samr_cache(&uinfo->sid); - } - - return status; -} - -/******************************************************************* - _samr_SetUserInfo2 - ********************************************************************/ - -NTSTATUS _samr_SetUserInfo2(struct pipes_struct *p, - struct samr_SetUserInfo2 *r) -{ - struct samr_SetUserInfo q; - - q.in.user_handle = r->in.user_handle; - q.in.level = r->in.level; - q.in.info = r->in.info; - - return _samr_SetUserInfo(p, &q); -} - -/********************************************************************* - _samr_GetAliasMembership -*********************************************************************/ - -NTSTATUS _samr_GetAliasMembership(struct pipes_struct *p, - struct samr_GetAliasMembership *r) -{ - size_t num_alias_rids; - uint32 *alias_rids; - struct samr_domain_info *dinfo; - size_t i; - - NTSTATUS status; - - struct dom_sid *members; - - DEBUG(5,("_samr_GetAliasMembership: %d\n", __LINE__)); - - dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS - | SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, NULL, - struct samr_domain_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if (!sid_check_is_domain(&dinfo->sid) && - !sid_check_is_builtin(&dinfo->sid)) - return NT_STATUS_OBJECT_TYPE_MISMATCH; - - if (r->in.sids->num_sids) { - members = TALLOC_ARRAY(p->mem_ctx, struct dom_sid, r->in.sids->num_sids); - - if (members == NULL) - return NT_STATUS_NO_MEMORY; - } else { - members = NULL; - } - - for (i=0; iin.sids->num_sids; i++) - sid_copy(&members[i], r->in.sids->sids[i].sid); - - alias_rids = NULL; - num_alias_rids = 0; - - become_root(); - status = pdb_enum_alias_memberships(p->mem_ctx, &dinfo->sid, members, - r->in.sids->num_sids, - &alias_rids, &num_alias_rids); - unbecome_root(); - - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - r->out.rids->count = num_alias_rids; - r->out.rids->ids = alias_rids; - - if (r->out.rids->ids == NULL) { - /* Windows domain clients don't accept a NULL ptr here */ - r->out.rids->ids = talloc_zero(p->mem_ctx, uint32_t); - } - if (r->out.rids->ids == NULL) { - return NT_STATUS_NO_MEMORY; - } - - return NT_STATUS_OK; -} - -/********************************************************************* - _samr_GetMembersInAlias -*********************************************************************/ - -NTSTATUS _samr_GetMembersInAlias(struct pipes_struct *p, - struct samr_GetMembersInAlias *r) -{ - struct samr_alias_info *ainfo; - NTSTATUS status; - size_t i; - size_t num_sids = 0; - struct lsa_SidPtr *sids = NULL; - struct dom_sid *pdb_sids = NULL; - - ainfo = policy_handle_find(p, r->in.alias_handle, - SAMR_ALIAS_ACCESS_GET_MEMBERS, NULL, - struct samr_alias_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - DEBUG(10, ("sid is %s\n", sid_string_dbg(&ainfo->sid))); - - become_root(); - status = pdb_enum_aliasmem(&ainfo->sid, talloc_tos(), &pdb_sids, - &num_sids); - unbecome_root(); - - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if (num_sids) { - sids = TALLOC_ZERO_ARRAY(p->mem_ctx, struct lsa_SidPtr, num_sids); - if (sids == NULL) { - TALLOC_FREE(pdb_sids); - return NT_STATUS_NO_MEMORY; - } - } - - for (i = 0; i < num_sids; i++) { - sids[i].sid = dom_sid_dup(p->mem_ctx, &pdb_sids[i]); - if (!sids[i].sid) { - TALLOC_FREE(pdb_sids); - return NT_STATUS_NO_MEMORY; - } - } - - r->out.sids->num_sids = num_sids; - r->out.sids->sids = sids; - - TALLOC_FREE(pdb_sids); - - return NT_STATUS_OK; -} - -/********************************************************************* - _samr_QueryGroupMember -*********************************************************************/ - -NTSTATUS _samr_QueryGroupMember(struct pipes_struct *p, - struct samr_QueryGroupMember *r) -{ - struct samr_group_info *ginfo; - size_t i, num_members; - - uint32 *rid=NULL; - uint32 *attr=NULL; - - NTSTATUS status; - struct samr_RidAttrArray *rids = NULL; - - ginfo = policy_handle_find(p, r->in.group_handle, - SAMR_GROUP_ACCESS_GET_MEMBERS, NULL, - struct samr_group_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - rids = TALLOC_ZERO_P(p->mem_ctx, struct samr_RidAttrArray); - if (!rids) { - return NT_STATUS_NO_MEMORY; - } - - DEBUG(10, ("sid is %s\n", sid_string_dbg(&ginfo->sid))); - - if (!sid_check_is_in_our_domain(&ginfo->sid)) { - DEBUG(3, ("sid %s is not in our domain\n", - sid_string_dbg(&ginfo->sid))); - return NT_STATUS_NO_SUCH_GROUP; - } - - DEBUG(10, ("lookup on Domain SID\n")); - - become_root(); - status = pdb_enum_group_members(p->mem_ctx, &ginfo->sid, - &rid, &num_members); - unbecome_root(); - - if (!NT_STATUS_IS_OK(status)) - return status; - - if (num_members) { - attr=TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, num_members); - if (attr == NULL) { - return NT_STATUS_NO_MEMORY; - } - } else { - attr = NULL; - } - - for (i=0; icount = num_members; - rids->attributes = attr; - rids->rids = rid; - - *r->out.rids = rids; - - return NT_STATUS_OK; -} - -/********************************************************************* - _samr_AddAliasMember -*********************************************************************/ - -NTSTATUS _samr_AddAliasMember(struct pipes_struct *p, - struct samr_AddAliasMember *r) -{ - struct samr_alias_info *ainfo; - NTSTATUS status; - - ainfo = policy_handle_find(p, r->in.alias_handle, - SAMR_ALIAS_ACCESS_ADD_MEMBER, NULL, - struct samr_alias_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - DEBUG(10, ("sid is %s\n", sid_string_dbg(&ainfo->sid))); - - /******** BEGIN SeAddUsers BLOCK *********/ - - become_root(); - status = pdb_add_aliasmem(&ainfo->sid, r->in.sid); - unbecome_root(); - - /******** END SeAddUsers BLOCK *********/ - - if (NT_STATUS_IS_OK(status)) { - force_flush_samr_cache(&ainfo->sid); - } - - return status; -} - -/********************************************************************* - _samr_DeleteAliasMember -*********************************************************************/ - -NTSTATUS _samr_DeleteAliasMember(struct pipes_struct *p, - struct samr_DeleteAliasMember *r) -{ - struct samr_alias_info *ainfo; - NTSTATUS status; - - ainfo = policy_handle_find(p, r->in.alias_handle, - SAMR_ALIAS_ACCESS_REMOVE_MEMBER, NULL, - struct samr_alias_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - DEBUG(10, ("_samr_del_aliasmem:sid is %s\n", - sid_string_dbg(&ainfo->sid))); - - /******** BEGIN SeAddUsers BLOCK *********/ - - become_root(); - status = pdb_del_aliasmem(&ainfo->sid, r->in.sid); - unbecome_root(); - - /******** END SeAddUsers BLOCK *********/ - - if (NT_STATUS_IS_OK(status)) { - force_flush_samr_cache(&ainfo->sid); - } - - return status; -} - -/********************************************************************* - _samr_AddGroupMember -*********************************************************************/ - -NTSTATUS _samr_AddGroupMember(struct pipes_struct *p, - struct samr_AddGroupMember *r) -{ - struct samr_group_info *ginfo; - NTSTATUS status; - uint32 group_rid; - - ginfo = policy_handle_find(p, r->in.group_handle, - SAMR_GROUP_ACCESS_ADD_MEMBER, NULL, - struct samr_group_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - DEBUG(10, ("sid is %s\n", sid_string_dbg(&ginfo->sid))); - - if (!sid_peek_check_rid(get_global_sam_sid(), &ginfo->sid, - &group_rid)) { - return NT_STATUS_INVALID_HANDLE; - } - - /******** BEGIN SeAddUsers BLOCK *********/ - - become_root(); - status = pdb_add_groupmem(p->mem_ctx, group_rid, r->in.rid); - unbecome_root(); - - /******** END SeAddUsers BLOCK *********/ - - force_flush_samr_cache(&ginfo->sid); - - return status; -} - -/********************************************************************* - _samr_DeleteGroupMember -*********************************************************************/ - -NTSTATUS _samr_DeleteGroupMember(struct pipes_struct *p, - struct samr_DeleteGroupMember *r) - -{ - struct samr_group_info *ginfo; - NTSTATUS status; - uint32 group_rid; - - /* - * delete the group member named r->in.rid - * who is a member of the sid associated with the handle - * the rid is a user's rid as the group is a domain group. - */ - - ginfo = policy_handle_find(p, r->in.group_handle, - SAMR_GROUP_ACCESS_REMOVE_MEMBER, NULL, - struct samr_group_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if (!sid_peek_check_rid(get_global_sam_sid(), &ginfo->sid, - &group_rid)) { - return NT_STATUS_INVALID_HANDLE; - } - - /******** BEGIN SeAddUsers BLOCK *********/ - - become_root(); - status = pdb_del_groupmem(p->mem_ctx, group_rid, r->in.rid); - unbecome_root(); - - /******** END SeAddUsers BLOCK *********/ - - force_flush_samr_cache(&ginfo->sid); - - return status; -} - -/********************************************************************* - _samr_DeleteUser -*********************************************************************/ - -NTSTATUS _samr_DeleteUser(struct pipes_struct *p, - struct samr_DeleteUser *r) -{ - struct samr_user_info *uinfo; - NTSTATUS status; - struct samu *sam_pass=NULL; - bool ret; - - DEBUG(5, ("_samr_DeleteUser: %d\n", __LINE__)); - - uinfo = policy_handle_find(p, r->in.user_handle, - SEC_STD_DELETE, NULL, - struct samr_user_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if (!sid_check_is_in_our_domain(&uinfo->sid)) - return NT_STATUS_CANNOT_DELETE; - - /* check if the user exists before trying to delete */ - if ( !(sam_pass = samu_new( NULL )) ) { - return NT_STATUS_NO_MEMORY; - } - - become_root(); - ret = pdb_getsampwsid(sam_pass, &uinfo->sid); - unbecome_root(); - - if(!ret) { - DEBUG(5,("_samr_DeleteUser: User %s doesn't exist.\n", - sid_string_dbg(&uinfo->sid))); - TALLOC_FREE(sam_pass); - return NT_STATUS_NO_SUCH_USER; - } - - /******** BEGIN SeAddUsers BLOCK *********/ - - become_root(); - status = pdb_delete_user(p->mem_ctx, sam_pass); - unbecome_root(); - - /******** END SeAddUsers BLOCK *********/ - - if ( !NT_STATUS_IS_OK(status) ) { - DEBUG(5,("_samr_DeleteUser: Failed to delete entry for " - "user %s: %s.\n", pdb_get_username(sam_pass), - nt_errstr(status))); - TALLOC_FREE(sam_pass); - return status; - } - - - TALLOC_FREE(sam_pass); - - force_flush_samr_cache(&uinfo->sid); - - if (!close_policy_hnd(p, r->in.user_handle)) - return NT_STATUS_OBJECT_NAME_INVALID; - - ZERO_STRUCTP(r->out.user_handle); - - return NT_STATUS_OK; -} - -/********************************************************************* - _samr_DeleteDomainGroup -*********************************************************************/ - -NTSTATUS _samr_DeleteDomainGroup(struct pipes_struct *p, - struct samr_DeleteDomainGroup *r) -{ - struct samr_group_info *ginfo; - NTSTATUS status; - uint32 group_rid; - - DEBUG(5, ("samr_DeleteDomainGroup: %d\n", __LINE__)); - - ginfo = policy_handle_find(p, r->in.group_handle, - SEC_STD_DELETE, NULL, - struct samr_group_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - DEBUG(10, ("sid is %s\n", sid_string_dbg(&ginfo->sid))); - - if (!sid_peek_check_rid(get_global_sam_sid(), &ginfo->sid, - &group_rid)) { - return NT_STATUS_NO_SUCH_GROUP; - } - - /******** BEGIN SeAddUsers BLOCK *********/ - - become_root(); - status = pdb_delete_dom_group(p->mem_ctx, group_rid); - unbecome_root(); - - /******** END SeAddUsers BLOCK *********/ - - if ( !NT_STATUS_IS_OK(status) ) { - DEBUG(5,("_samr_DeleteDomainGroup: Failed to delete mapping " - "entry for group %s: %s\n", - sid_string_dbg(&ginfo->sid), - nt_errstr(status))); - return status; - } - - force_flush_samr_cache(&ginfo->sid); - - if (!close_policy_hnd(p, r->in.group_handle)) - return NT_STATUS_OBJECT_NAME_INVALID; - - return NT_STATUS_OK; -} - -/********************************************************************* - _samr_DeleteDomAlias -*********************************************************************/ - -NTSTATUS _samr_DeleteDomAlias(struct pipes_struct *p, - struct samr_DeleteDomAlias *r) -{ - struct samr_alias_info *ainfo; - NTSTATUS status; - - DEBUG(5, ("_samr_DeleteDomAlias: %d\n", __LINE__)); - - ainfo = policy_handle_find(p, r->in.alias_handle, - SEC_STD_DELETE, NULL, - struct samr_alias_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - DEBUG(10, ("sid is %s\n", sid_string_dbg(&ainfo->sid))); - - /* Don't let Windows delete builtin groups */ - - if ( sid_check_is_in_builtin( &ainfo->sid ) ) { - return NT_STATUS_SPECIAL_ACCOUNT; - } - - if (!sid_check_is_in_our_domain(&ainfo->sid)) - return NT_STATUS_NO_SUCH_ALIAS; - - DEBUG(10, ("lookup on Local SID\n")); - - /******** BEGIN SeAddUsers BLOCK *********/ - - become_root(); - /* Have passdb delete the alias */ - status = pdb_delete_alias(&ainfo->sid); - unbecome_root(); - - /******** END SeAddUsers BLOCK *********/ - - if ( !NT_STATUS_IS_OK(status)) - return status; - - force_flush_samr_cache(&ainfo->sid); - - if (!close_policy_hnd(p, r->in.alias_handle)) - return NT_STATUS_OBJECT_NAME_INVALID; - - return NT_STATUS_OK; -} - -/********************************************************************* - _samr_CreateDomainGroup -*********************************************************************/ - -NTSTATUS _samr_CreateDomainGroup(struct pipes_struct *p, - struct samr_CreateDomainGroup *r) - -{ - NTSTATUS status; - const char *name; - struct samr_domain_info *dinfo; - struct samr_group_info *ginfo; - - dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_CREATE_GROUP, NULL, - struct samr_domain_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if (!sid_check_is_domain(&dinfo->sid)) { - return NT_STATUS_ACCESS_DENIED; - } - - name = r->in.name->string; - if (name == NULL) { - return NT_STATUS_NO_MEMORY; - } - - status = can_create(p->mem_ctx, name); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - /******** BEGIN SeAddUsers BLOCK *********/ - - become_root(); - /* check that we successfully create the UNIX group */ - status = pdb_create_dom_group(p->mem_ctx, name, r->out.rid); - unbecome_root(); - - /******** END SeAddUsers BLOCK *********/ - - /* check if we should bail out here */ - - if ( !NT_STATUS_IS_OK(status) ) - return status; - - ginfo = policy_handle_create(p, r->out.group_handle, - GENERIC_RIGHTS_GROUP_ALL_ACCESS, - struct samr_group_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - sid_compose(&ginfo->sid, &dinfo->sid, *r->out.rid); - - force_flush_samr_cache(&dinfo->sid); - - return NT_STATUS_OK; -} - -/********************************************************************* - _samr_CreateDomAlias -*********************************************************************/ - -NTSTATUS _samr_CreateDomAlias(struct pipes_struct *p, - struct samr_CreateDomAlias *r) -{ - struct dom_sid info_sid; - const char *name = NULL; - struct samr_domain_info *dinfo; - struct samr_alias_info *ainfo; - gid_t gid; - NTSTATUS result; - - dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_CREATE_ALIAS, NULL, - struct samr_domain_info, &result); - if (!NT_STATUS_IS_OK(result)) { - return result; - } - - if (!sid_check_is_domain(&dinfo->sid)) { - return NT_STATUS_ACCESS_DENIED; - } - - name = r->in.alias_name->string; - - result = can_create(p->mem_ctx, name); - if (!NT_STATUS_IS_OK(result)) { - return result; - } - - /******** BEGIN SeAddUsers BLOCK *********/ - - become_root(); - /* Have passdb create the alias */ - result = pdb_create_alias(name, r->out.rid); - unbecome_root(); - - /******** END SeAddUsers BLOCK *********/ - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(10, ("pdb_create_alias failed: %s\n", - nt_errstr(result))); - return result; - } - - sid_compose(&info_sid, &dinfo->sid, *r->out.rid); - - if (!sid_to_gid(&info_sid, &gid)) { - DEBUG(10, ("Could not find alias just created\n")); - return NT_STATUS_ACCESS_DENIED; - } - - /* check if the group has been successfully created */ - if ( getgrgid(gid) == NULL ) { - DEBUG(10, ("getgrgid(%u) of just created alias failed\n", - (unsigned int)gid)); - return NT_STATUS_ACCESS_DENIED; - } - - ainfo = policy_handle_create(p, r->out.alias_handle, - GENERIC_RIGHTS_ALIAS_ALL_ACCESS, - struct samr_alias_info, &result); - if (!NT_STATUS_IS_OK(result)) { - return result; - } - ainfo->sid = info_sid; - - force_flush_samr_cache(&info_sid); - - return NT_STATUS_OK; -} - -/********************************************************************* - _samr_QueryGroupInfo -*********************************************************************/ - -NTSTATUS _samr_QueryGroupInfo(struct pipes_struct *p, - struct samr_QueryGroupInfo *r) -{ - struct samr_group_info *ginfo; - NTSTATUS status; - GROUP_MAP map; - union samr_GroupInfo *info = NULL; - bool ret; - uint32_t attributes = SE_GROUP_MANDATORY | - SE_GROUP_ENABLED_BY_DEFAULT | - SE_GROUP_ENABLED; - const char *group_name = NULL; - const char *group_description = NULL; - - ginfo = policy_handle_find(p, r->in.group_handle, - SAMR_GROUP_ACCESS_LOOKUP_INFO, NULL, - struct samr_group_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - become_root(); - ret = get_domain_group_from_sid(ginfo->sid, &map); - unbecome_root(); - if (!ret) - return NT_STATUS_INVALID_HANDLE; - - /* FIXME: map contains fstrings */ - group_name = talloc_strdup(r, map.nt_name); - group_description = talloc_strdup(r, map.comment); - - info = TALLOC_ZERO_P(p->mem_ctx, union samr_GroupInfo); - if (!info) { - return NT_STATUS_NO_MEMORY; - } - - switch (r->in.level) { - case 1: { - uint32 *members; - size_t num_members; - - become_root(); - status = pdb_enum_group_members( - p->mem_ctx, &ginfo->sid, &members, - &num_members); - unbecome_root(); - - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - info->all.name.string = group_name; - info->all.attributes = attributes; - info->all.num_members = num_members; - info->all.description.string = group_description; - break; - } - case 2: - info->name.string = group_name; - break; - case 3: - info->attributes.attributes = attributes; - break; - case 4: - info->description.string = group_description; - break; - case 5: { - /* - uint32 *members; - size_t num_members; - */ - - /* - become_root(); - status = pdb_enum_group_members( - p->mem_ctx, &ginfo->sid, &members, - &num_members); - unbecome_root(); - - if (!NT_STATUS_IS_OK(status)) { - return status; - } - */ - info->all2.name.string = group_name; - info->all2.attributes = attributes; - info->all2.num_members = 0; /* num_members - in w2k3 this is always 0 */ - info->all2.description.string = group_description; - - break; - } - default: - return NT_STATUS_INVALID_INFO_CLASS; - } - - *r->out.info = info; - - return NT_STATUS_OK; -} - -/********************************************************************* - _samr_SetGroupInfo -*********************************************************************/ - -NTSTATUS _samr_SetGroupInfo(struct pipes_struct *p, - struct samr_SetGroupInfo *r) -{ - struct samr_group_info *ginfo; - GROUP_MAP map; - NTSTATUS status; - bool ret; - - ginfo = policy_handle_find(p, r->in.group_handle, - SAMR_GROUP_ACCESS_SET_INFO, NULL, - struct samr_group_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - become_root(); - ret = get_domain_group_from_sid(ginfo->sid, &map); - unbecome_root(); - if (!ret) - return NT_STATUS_NO_SUCH_GROUP; - - switch (r->in.level) { - case 2: - fstrcpy(map.nt_name, r->in.info->name.string); - break; - case 3: - break; - case 4: - fstrcpy(map.comment, r->in.info->description.string); - break; - default: - return NT_STATUS_INVALID_INFO_CLASS; - } - - /******** BEGIN SeAddUsers BLOCK *********/ - - become_root(); - status = pdb_update_group_mapping_entry(&map); - unbecome_root(); - - /******** End SeAddUsers BLOCK *********/ - - if (NT_STATUS_IS_OK(status)) { - force_flush_samr_cache(&ginfo->sid); - } - - return status; -} - -/********************************************************************* - _samr_SetAliasInfo -*********************************************************************/ - -NTSTATUS _samr_SetAliasInfo(struct pipes_struct *p, - struct samr_SetAliasInfo *r) -{ - struct samr_alias_info *ainfo; - struct acct_info info; - NTSTATUS status; - - ainfo = policy_handle_find(p, r->in.alias_handle, - SAMR_ALIAS_ACCESS_SET_INFO, NULL, - struct samr_alias_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - /* get the current group information */ - - become_root(); - status = pdb_get_aliasinfo( &ainfo->sid, &info ); - unbecome_root(); - - if ( !NT_STATUS_IS_OK(status)) - return status; - - switch (r->in.level) { - case ALIASINFONAME: - { - fstring group_name; - - /* We currently do not support renaming groups in the - the BUILTIN domain. Refer to util_builtin.c to understand - why. The eventually needs to be fixed to be like Windows - where you can rename builtin groups, just not delete them */ - - if ( sid_check_is_in_builtin( &ainfo->sid ) ) { - return NT_STATUS_SPECIAL_ACCOUNT; - } - - /* There has to be a valid name (and it has to be different) */ - - if ( !r->in.info->name.string ) - return NT_STATUS_INVALID_PARAMETER; - - /* If the name is the same just reply "ok". Yes this - doesn't allow you to change the case of a group name. */ - - if ( strequal( r->in.info->name.string, info.acct_name ) ) - return NT_STATUS_OK; - - fstrcpy( info.acct_name, r->in.info->name.string); - - /* make sure the name doesn't already exist as a user - or local group */ - - fstr_sprintf( group_name, "%s\\%s", global_myname(), info.acct_name ); - status = can_create( p->mem_ctx, group_name ); - if ( !NT_STATUS_IS_OK( status ) ) - return status; - break; - } - case ALIASINFODESCRIPTION: - if (r->in.info->description.string) { - fstrcpy(info.acct_desc, - r->in.info->description.string); - } else { - fstrcpy( info.acct_desc, "" ); - } - break; - default: - return NT_STATUS_INVALID_INFO_CLASS; - } - - /******** BEGIN SeAddUsers BLOCK *********/ - - become_root(); - status = pdb_set_aliasinfo( &ainfo->sid, &info ); - unbecome_root(); - - /******** End SeAddUsers BLOCK *********/ - - if (NT_STATUS_IS_OK(status)) - force_flush_samr_cache(&ainfo->sid); - - return status; -} - -/**************************************************************** - _samr_GetDomPwInfo -****************************************************************/ - -NTSTATUS _samr_GetDomPwInfo(struct pipes_struct *p, - struct samr_GetDomPwInfo *r) -{ - uint32_t min_password_length = 0; - uint32_t password_properties = 0; - - /* Perform access check. Since this rpc does not require a - policy handle it will not be caught by the access checks on - SAMR_CONNECT or SAMR_CONNECT_ANON. */ - - if (!pipe_access_check(p)) { - DEBUG(3, ("access denied to _samr_GetDomPwInfo\n")); - return NT_STATUS_ACCESS_DENIED; - } - - become_root(); - pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_LEN, - &min_password_length); - pdb_get_account_policy(PDB_POLICY_USER_MUST_LOGON_TO_CHG_PASS, - &password_properties); - unbecome_root(); - - if (lp_check_password_script() && *lp_check_password_script()) { - password_properties |= DOMAIN_PASSWORD_COMPLEX; - } - - r->out.info->min_password_length = min_password_length; - r->out.info->password_properties = password_properties; - - return NT_STATUS_OK; -} - -/********************************************************************* - _samr_OpenGroup -*********************************************************************/ - -NTSTATUS _samr_OpenGroup(struct pipes_struct *p, - struct samr_OpenGroup *r) - -{ - struct dom_sid info_sid; - GROUP_MAP map; - struct samr_domain_info *dinfo; - struct samr_group_info *ginfo; - struct security_descriptor *psd = NULL; - uint32 acc_granted; - uint32 des_access = r->in.access_mask; - size_t sd_size; - NTSTATUS status; - bool ret; - - dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, NULL, - struct samr_domain_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - /*check if access can be granted as requested by client. */ - map_max_allowed_access(p->server_info->security_token, - &p->server_info->utok, - &des_access); - - make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &grp_generic_mapping, NULL, 0); - se_map_generic(&des_access,&grp_generic_mapping); - - status = access_check_object(psd, p->server_info->security_token, - SEC_PRIV_ADD_USERS, SEC_PRIV_INVALID, GENERIC_RIGHTS_GROUP_ALL_ACCESS, - des_access, &acc_granted, "_samr_OpenGroup"); - - if ( !NT_STATUS_IS_OK(status) ) - return status; - - /* this should not be hard-coded like this */ - - if (!sid_check_is_domain(&dinfo->sid)) { - return NT_STATUS_ACCESS_DENIED; - } - - sid_compose(&info_sid, &dinfo->sid, r->in.rid); - - DEBUG(10, ("_samr_OpenGroup:Opening SID: %s\n", - sid_string_dbg(&info_sid))); - - /* check if that group really exists */ - become_root(); - ret = get_domain_group_from_sid(info_sid, &map); - unbecome_root(); - if (!ret) - return NT_STATUS_NO_SUCH_GROUP; - - ginfo = policy_handle_create(p, r->out.group_handle, - acc_granted, - struct samr_group_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - ginfo->sid = info_sid; - - return NT_STATUS_OK; -} - -/********************************************************************* - _samr_RemoveMemberFromForeignDomain -*********************************************************************/ - -NTSTATUS _samr_RemoveMemberFromForeignDomain(struct pipes_struct *p, - struct samr_RemoveMemberFromForeignDomain *r) -{ - struct samr_domain_info *dinfo; - NTSTATUS result; - - DEBUG(5,("_samr_RemoveMemberFromForeignDomain: removing SID [%s]\n", - sid_string_dbg(r->in.sid))); - - /* Find the policy handle. Open a policy on it. */ - - dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, NULL, - struct samr_domain_info, &result); - if (!NT_STATUS_IS_OK(result)) { - return result; - } - - DEBUG(8, ("_samr_RemoveMemberFromForeignDomain: sid is %s\n", - sid_string_dbg(&dinfo->sid))); - - /* we can only delete a user from a group since we don't have - nested groups anyways. So in the latter case, just say OK */ - - /* TODO: The above comment nowadays is bogus. Since we have nested - * groups now, and aliases members are never reported out of the unix - * group membership, the "just say OK" makes this call a no-op. For - * us. This needs fixing however. */ - - /* I've only ever seen this in the wild when deleting a user from - * usrmgr.exe. domain_sid is the builtin domain, and the sid to delete - * is the user about to be deleted. I very much suspect this is the - * only application of this call. To verify this, let people report - * other cases. */ - - if (!sid_check_is_builtin(&dinfo->sid)) { - DEBUG(1,("_samr_RemoveMemberFromForeignDomain: domain_sid = %s, " - "global_sam_sid() = %s\n", - sid_string_dbg(&dinfo->sid), - sid_string_dbg(get_global_sam_sid()))); - DEBUGADD(1,("please report to samba-technical@samba.org!\n")); - return NT_STATUS_OK; - } - - force_flush_samr_cache(&dinfo->sid); - - result = NT_STATUS_OK; - - return result; -} - -/******************************************************************* - _samr_QueryDomainInfo2 - ********************************************************************/ - -NTSTATUS _samr_QueryDomainInfo2(struct pipes_struct *p, - struct samr_QueryDomainInfo2 *r) -{ - struct samr_QueryDomainInfo q; - - q.in.domain_handle = r->in.domain_handle; - q.in.level = r->in.level; - - q.out.info = r->out.info; - - return _samr_QueryDomainInfo(p, &q); -} - -/******************************************************************* - ********************************************************************/ - -static NTSTATUS set_dom_info_1(TALLOC_CTX *mem_ctx, - struct samr_DomInfo1 *r) -{ - time_t u_expire, u_min_age; - - u_expire = nt_time_to_unix_abs((NTTIME *)&r->max_password_age); - u_min_age = nt_time_to_unix_abs((NTTIME *)&r->min_password_age); - - pdb_set_account_policy(PDB_POLICY_MIN_PASSWORD_LEN, - (uint32_t)r->min_password_length); - pdb_set_account_policy(PDB_POLICY_PASSWORD_HISTORY, - (uint32_t)r->password_history_length); - pdb_set_account_policy(PDB_POLICY_USER_MUST_LOGON_TO_CHG_PASS, - (uint32_t)r->password_properties); - pdb_set_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, (int)u_expire); - pdb_set_account_policy(PDB_POLICY_MIN_PASSWORD_AGE, (int)u_min_age); - - return NT_STATUS_OK; -} - -/******************************************************************* - ********************************************************************/ - -static NTSTATUS set_dom_info_3(TALLOC_CTX *mem_ctx, - struct samr_DomInfo3 *r) -{ - time_t u_logout; - - u_logout = nt_time_to_unix_abs((NTTIME *)&r->force_logoff_time); - - pdb_set_account_policy(PDB_POLICY_TIME_TO_LOGOUT, (int)u_logout); - - return NT_STATUS_OK; -} - -/******************************************************************* - ********************************************************************/ - -static NTSTATUS set_dom_info_12(TALLOC_CTX *mem_ctx, - struct samr_DomInfo12 *r) -{ - time_t u_lock_duration, u_reset_time; - - u_lock_duration = nt_time_to_unix_abs((NTTIME *)&r->lockout_duration); - if (u_lock_duration != -1) { - u_lock_duration /= 60; - } - - u_reset_time = nt_time_to_unix_abs((NTTIME *)&r->lockout_window)/60; - - pdb_set_account_policy(PDB_POLICY_LOCK_ACCOUNT_DURATION, (int)u_lock_duration); - pdb_set_account_policy(PDB_POLICY_RESET_COUNT_TIME, (int)u_reset_time); - pdb_set_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, - (uint32_t)r->lockout_threshold); - - return NT_STATUS_OK; -} - -/******************************************************************* - _samr_SetDomainInfo - ********************************************************************/ - -NTSTATUS _samr_SetDomainInfo(struct pipes_struct *p, - struct samr_SetDomainInfo *r) -{ - struct samr_domain_info *dinfo; - NTSTATUS status; - uint32_t acc_required = 0; - - DEBUG(5,("_samr_SetDomainInfo: %d\n", __LINE__)); - - switch (r->in.level) { - case 1: /* DomainPasswordInformation */ - case 12: /* DomainLockoutInformation */ - /* DOMAIN_WRITE_PASSWORD_PARAMETERS */ - acc_required = SAMR_DOMAIN_ACCESS_SET_INFO_1; - break; - case 3: /* DomainLogoffInformation */ - case 4: /* DomainOemInformation */ - /* DOMAIN_WRITE_OTHER_PARAMETERS */ - acc_required = SAMR_DOMAIN_ACCESS_SET_INFO_2; - break; - case 6: /* DomainReplicationInformation */ - case 9: /* DomainStateInformation */ - case 7: /* DomainServerRoleInformation */ - /* DOMAIN_ADMINISTER_SERVER */ - acc_required = SAMR_DOMAIN_ACCESS_SET_INFO_3; - break; - default: - return NT_STATUS_INVALID_INFO_CLASS; - } - - dinfo = policy_handle_find(p, r->in.domain_handle, - acc_required, NULL, - struct samr_domain_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - DEBUG(5,("_samr_SetDomainInfo: level: %d\n", r->in.level)); - - switch (r->in.level) { - case 1: - status = set_dom_info_1(p->mem_ctx, &r->in.info->info1); - break; - case 3: - status = set_dom_info_3(p->mem_ctx, &r->in.info->info3); - break; - case 4: - break; - case 6: - break; - case 7: - break; - case 9: - break; - case 12: - status = set_dom_info_12(p->mem_ctx, &r->in.info->info12); - break; - default: - return NT_STATUS_INVALID_INFO_CLASS; - } - - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - DEBUG(5,("_samr_SetDomainInfo: %d\n", __LINE__)); - - return NT_STATUS_OK; -} - -/**************************************************************** - _samr_GetDisplayEnumerationIndex -****************************************************************/ - -NTSTATUS _samr_GetDisplayEnumerationIndex(struct pipes_struct *p, - struct samr_GetDisplayEnumerationIndex *r) -{ - struct samr_domain_info *dinfo; - uint32_t max_entries = (uint32_t) -1; - uint32_t enum_context = 0; - int i; - uint32_t num_account = 0; - struct samr_displayentry *entries = NULL; - NTSTATUS status; - - DEBUG(5,("_samr_GetDisplayEnumerationIndex: %d\n", __LINE__)); - - dinfo = policy_handle_find(p, r->in.domain_handle, - SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL, - struct samr_domain_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if ((r->in.level < 1) || (r->in.level > 3)) { - DEBUG(0,("_samr_GetDisplayEnumerationIndex: " - "Unknown info level (%u)\n", - r->in.level)); - return NT_STATUS_INVALID_INFO_CLASS; - } - - become_root(); - - /* The following done as ROOT. Don't return without unbecome_root(). */ - - switch (r->in.level) { - case 1: - if (dinfo->disp_info->users == NULL) { - dinfo->disp_info->users = pdb_search_users( - dinfo->disp_info, ACB_NORMAL); - if (dinfo->disp_info->users == NULL) { - unbecome_root(); - return NT_STATUS_ACCESS_DENIED; - } - DEBUG(10,("_samr_GetDisplayEnumerationIndex: " - "starting user enumeration at index %u\n", - (unsigned int)enum_context)); - } else { - DEBUG(10,("_samr_GetDisplayEnumerationIndex: " - "using cached user enumeration at index %u\n", - (unsigned int)enum_context)); - } - num_account = pdb_search_entries(dinfo->disp_info->users, - enum_context, max_entries, - &entries); - break; - case 2: - if (dinfo->disp_info->machines == NULL) { - dinfo->disp_info->machines = pdb_search_users( - dinfo->disp_info, ACB_WSTRUST|ACB_SVRTRUST); - if (dinfo->disp_info->machines == NULL) { - unbecome_root(); - return NT_STATUS_ACCESS_DENIED; - } - DEBUG(10,("_samr_GetDisplayEnumerationIndex: " - "starting machine enumeration at index %u\n", - (unsigned int)enum_context)); - } else { - DEBUG(10,("_samr_GetDisplayEnumerationIndex: " - "using cached machine enumeration at index %u\n", - (unsigned int)enum_context)); - } - num_account = pdb_search_entries(dinfo->disp_info->machines, - enum_context, max_entries, - &entries); - break; - case 3: - if (dinfo->disp_info->groups == NULL) { - dinfo->disp_info->groups = pdb_search_groups( - dinfo->disp_info); - if (dinfo->disp_info->groups == NULL) { - unbecome_root(); - return NT_STATUS_ACCESS_DENIED; - } - DEBUG(10,("_samr_GetDisplayEnumerationIndex: " - "starting group enumeration at index %u\n", - (unsigned int)enum_context)); - } else { - DEBUG(10,("_samr_GetDisplayEnumerationIndex: " - "using cached group enumeration at index %u\n", - (unsigned int)enum_context)); - } - num_account = pdb_search_entries(dinfo->disp_info->groups, - enum_context, max_entries, - &entries); - break; - default: - unbecome_root(); - smb_panic("info class changed"); - break; - } - - unbecome_root(); - - /* Ensure we cache this enumeration. */ - set_disp_info_cache_timeout(dinfo->disp_info, DISP_INFO_CACHE_TIMEOUT); - - DEBUG(10,("_samr_GetDisplayEnumerationIndex: looking for :%s\n", - r->in.name->string)); - - for (i=0; iin.name->string)) { - DEBUG(10,("_samr_GetDisplayEnumerationIndex: " - "found %s at idx %d\n", - r->in.name->string, i)); - *r->out.idx = i; - return NT_STATUS_OK; - } - } - - /* assuming account_name lives at the very end */ - *r->out.idx = num_account; - - return NT_STATUS_NO_MORE_ENTRIES; -} - -/**************************************************************** - _samr_GetDisplayEnumerationIndex2 -****************************************************************/ - -NTSTATUS _samr_GetDisplayEnumerationIndex2(struct pipes_struct *p, - struct samr_GetDisplayEnumerationIndex2 *r) -{ - struct samr_GetDisplayEnumerationIndex q; - - q.in.domain_handle = r->in.domain_handle; - q.in.level = r->in.level; - q.in.name = r->in.name; - - q.out.idx = r->out.idx; - - return _samr_GetDisplayEnumerationIndex(p, &q); -} - -/**************************************************************** - _samr_RidToSid -****************************************************************/ - -NTSTATUS _samr_RidToSid(struct pipes_struct *p, - struct samr_RidToSid *r) -{ - struct samr_domain_info *dinfo; - NTSTATUS status; - struct dom_sid sid; - - dinfo = policy_handle_find(p, r->in.domain_handle, - 0, NULL, - struct samr_domain_info, &status); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if (!sid_compose(&sid, &dinfo->sid, r->in.rid)) { - return NT_STATUS_NO_MEMORY; - } - - *r->out.sid = dom_sid_dup(p->mem_ctx, &sid); - if (!*r->out.sid) { - return NT_STATUS_NO_MEMORY; - } - - return NT_STATUS_OK; -} - -/**************************************************************** -****************************************************************/ - -static enum samr_ValidationStatus samr_ValidatePassword_Change(TALLOC_CTX *mem_ctx, - const struct samr_PwInfo *dom_pw_info, - const struct samr_ValidatePasswordReq2 *req, - struct samr_ValidatePasswordRepCtr *rep) -{ - NTSTATUS status; - - if (req->password.string == NULL) { - return SAMR_VALIDATION_STATUS_SUCCESS; - } - if (strlen(req->password.string) < dom_pw_info->min_password_length) { - ZERO_STRUCT(rep->info); - return SAMR_VALIDATION_STATUS_PWD_TOO_SHORT; - } - if (dom_pw_info->password_properties & DOMAIN_PASSWORD_COMPLEX) { - status = check_password_complexity(req->account.string, - req->password.string, - NULL); - if (!NT_STATUS_IS_OK(status)) { - ZERO_STRUCT(rep->info); - return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH; - } - } - - return SAMR_VALIDATION_STATUS_SUCCESS; -} - -/**************************************************************** -****************************************************************/ - -static enum samr_ValidationStatus samr_ValidatePassword_Reset(TALLOC_CTX *mem_ctx, - const struct samr_PwInfo *dom_pw_info, - const struct samr_ValidatePasswordReq3 *req, - struct samr_ValidatePasswordRepCtr *rep) -{ - NTSTATUS status; - - if (req->password.string == NULL) { - return SAMR_VALIDATION_STATUS_SUCCESS; - } - if (strlen(req->password.string) < dom_pw_info->min_password_length) { - ZERO_STRUCT(rep->info); - return SAMR_VALIDATION_STATUS_PWD_TOO_SHORT; - } - if (dom_pw_info->password_properties & DOMAIN_PASSWORD_COMPLEX) { - status = check_password_complexity(req->account.string, - req->password.string, - NULL); - if (!NT_STATUS_IS_OK(status)) { - ZERO_STRUCT(rep->info); - return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH; - } - } - - return SAMR_VALIDATION_STATUS_SUCCESS; -} - -/**************************************************************** - _samr_ValidatePassword -****************************************************************/ - -NTSTATUS _samr_ValidatePassword(struct pipes_struct *p, - struct samr_ValidatePassword *r) -{ - union samr_ValidatePasswordRep *rep; - NTSTATUS status; - struct samr_GetDomPwInfo pw; - struct samr_PwInfo dom_pw_info; - - if (r->in.level < 1 || r->in.level > 3) { - return NT_STATUS_INVALID_INFO_CLASS; - } - - pw.in.domain_name = NULL; - pw.out.info = &dom_pw_info; - - status = _samr_GetDomPwInfo(p, &pw); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - rep = talloc_zero(p->mem_ctx, union samr_ValidatePasswordRep); - if (!rep) { - return NT_STATUS_NO_MEMORY; - } - - switch (r->in.level) { - case 1: - status = NT_STATUS_NOT_SUPPORTED; - break; - case 2: - rep->ctr2.status = samr_ValidatePassword_Change(p->mem_ctx, - &dom_pw_info, - &r->in.req->req2, - &rep->ctr2); - break; - case 3: - rep->ctr3.status = samr_ValidatePassword_Reset(p->mem_ctx, - &dom_pw_info, - &r->in.req->req3, - &rep->ctr3); - break; - default: - status = NT_STATUS_INVALID_INFO_CLASS; - break; - } - - if (!NT_STATUS_IS_OK(status)) { - talloc_free(rep); - return status; - } - - *r->out.rep = rep; - - return NT_STATUS_OK; -} - -/**************************************************************** -****************************************************************/ - -NTSTATUS _samr_Shutdown(struct pipes_struct *p, - struct samr_Shutdown *r) -{ - p->rng_fault_state = true; - return NT_STATUS_NOT_IMPLEMENTED; -} - -/**************************************************************** -****************************************************************/ - -NTSTATUS _samr_SetMemberAttributesOfGroup(struct pipes_struct *p, - struct samr_SetMemberAttributesOfGroup *r) -{ - p->rng_fault_state = true; - return NT_STATUS_NOT_IMPLEMENTED; -} - -/**************************************************************** -****************************************************************/ - -NTSTATUS _samr_TestPrivateFunctionsDomain(struct pipes_struct *p, - struct samr_TestPrivateFunctionsDomain *r) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -/**************************************************************** -****************************************************************/ - -NTSTATUS _samr_TestPrivateFunctionsUser(struct pipes_struct *p, - struct samr_TestPrivateFunctionsUser *r) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -/**************************************************************** -****************************************************************/ - -NTSTATUS _samr_AddMultipleMembersToAlias(struct pipes_struct *p, - struct samr_AddMultipleMembersToAlias *r) -{ - p->rng_fault_state = true; - return NT_STATUS_NOT_IMPLEMENTED; -} - -/**************************************************************** -****************************************************************/ - -NTSTATUS _samr_RemoveMultipleMembersFromAlias(struct pipes_struct *p, - struct samr_RemoveMultipleMembersFromAlias *r) -{ - p->rng_fault_state = true; - return NT_STATUS_NOT_IMPLEMENTED; -} - -/**************************************************************** -****************************************************************/ - -NTSTATUS _samr_SetBootKeyInformation(struct pipes_struct *p, - struct samr_SetBootKeyInformation *r) -{ - p->rng_fault_state = true; - return NT_STATUS_NOT_IMPLEMENTED; -} - -/**************************************************************** -****************************************************************/ - -NTSTATUS _samr_GetBootKeyInformation(struct pipes_struct *p, - struct samr_GetBootKeyInformation *r) -{ - p->rng_fault_state = true; - return NT_STATUS_NOT_IMPLEMENTED; -} - -/**************************************************************** -****************************************************************/ - -NTSTATUS _samr_SetDsrmPassword(struct pipes_struct *p, - struct samr_SetDsrmPassword *r) -{ - p->rng_fault_state = true; - return NT_STATUS_NOT_IMPLEMENTED; -} -- cgit