diff options
-rw-r--r-- | source3/include/rpc_samr.h | 164 | ||||
-rw-r--r-- | source3/rpc_server/srv_samr_nt.c | 723 |
2 files changed, 766 insertions, 121 deletions
diff --git a/source3/include/rpc_samr.h b/source3/include/rpc_samr.h index 1bb7a87b35..9df3e7fe19 100644 --- a/source3/include/rpc_samr.h +++ b/source3/include/rpc_samr.h @@ -145,6 +145,170 @@ SamrTestPrivateFunctionsUser #define SAMR_CONNECT 0x39 #define SAMR_SET_USERINFO 0x3A +//Access bits to the SAM-object +#define SAMR_ACCESS_UNKNOWN_1 0x00000001 +#define SAMR_ACCESS_SHUTDOWN_SERVER 0x00000002 +#define SAMR_ACCESS_UNKNOWN_4 0x00000004 +#define SAMR_ACCESS_UNKNOWN_8 0x00000008 +#define SAMR_ACCESS_ENUM_DOMAINS 0x00000010 +#define SAMR_ACCESS_OPEN_DOMAIN 0x00000020 + +#define SAMR_ALL_ACCESS ( STANDARD_RIGHTS_REQUIRED_ACCESS | \ + SAMR_ACCESS_OPEN_DOMAIN | \ + SAMR_ACCESS_ENUM_DOMAINS | \ + SAMR_ACCESS_UNKNOWN_8 | \ + SAMR_ACCESS_UNKNOWN_4 | \ + SAMR_ACCESS_SHUTDOWN_SERVER | \ + SAMR_ACCESS_UNKNOWN_1 ) + +#define SAMR_READ ( STANDARD_RIGHTS_READ_ACCESS | \ + SAMR_ACCESS_ENUM_DOMAINS ) + +#define SAMR_WRITE ( STANDARD_RIGHTS_WRITE_ACCESS | \ + SAMR_ACCESS_UNKNOWN_8 | \ + SAMR_ACCESS_UNKNOWN_4 | \ + SAMR_ACCESS_SHUTDOWN_SERVER ) + +#define SAMR_EXECUTE ( STANDARD_RIGHTS_EXECUTE_ACCESS | \ + SAMR_ACCESS_OPEN_DOMAIN | \ + SAMR_ACCESS_UNKNOWN_1 ) + +//Access bits to Domain-objects +#define DOMAIN_ACCESS_LOOKUP_INFO_1 0x000000001 +#define DOMAIN_ACCESS_SET_INFO_1 0x000000002 +#define DOMAIN_ACCESS_LOOKUP_INFO_2 0x000000004 +#define DOMAIN_ACCESS_SET_INFO_2 0x000000008 +#define DOMAIN_ACCESS_CREATE_USER 0x000000010 +#define DOMAIN_ACCESS_CREATE_GROUP 0x000000020 +#define DOMAIN_ACCESS_CREATE_ALIAS 0x000000040 +#define DOMAIN_ACCESS_UNKNOWN_80 0x000000080 +#define DOMAIN_ACCESS_ENUM_ACCOUNTS 0x000000100 +#define DOMAIN_ACCESS_OPEN_ACCOUNT 0x000000200 +#define DOMAIN_ACCESS_SET_INFO_3 0x000000400 + +#define DOMAIN_ALL_ACCESS ( STANDARD_RIGHTS_REQUIRED_ACCESS | \ + DOMAIN_ACCESS_SET_INFO_3 | \ + DOMAIN_ACCESS_OPEN_ACCOUNT | \ + DOMAIN_ACCESS_ENUM_ACCOUNTS | \ + DOMAIN_ACCESS_UNKNOWN_80 | \ + DOMAIN_ACCESS_CREATE_ALIAS | \ + DOMAIN_ACCESS_CREATE_GROUP | \ + DOMAIN_ACCESS_CREATE_USER | \ + DOMAIN_ACCESS_SET_INFO_2 | \ + DOMAIN_ACCESS_LOOKUP_INFO_2 | \ + DOMAIN_ACCESS_SET_INFO_1 | \ + DOMAIN_ACCESS_LOOKUP_INFO_1 ) + +#define DOMAIN_READ ( STANDARD_RIGHTS_READ_ACCESS | \ + DOMAIN_ACCESS_UNKNOWN_80 | \ + DOMAIN_ACCESS_LOOKUP_INFO_2 ) + +#define DOMAIN_WRITE ( STANDARD_RIGHTS_WRITE_ACCESS | \ + DOMAIN_ACCESS_SET_INFO_3 | \ + DOMAIN_ACCESS_CREATE_ALIAS | \ + DOMAIN_ACCESS_CREATE_GROUP | \ + DOMAIN_ACCESS_CREATE_USER | \ + DOMAIN_ACCESS_SET_INFO_2 | \ + DOMAIN_ACCESS_SET_INFO_1 ) + +#define DOMAIN_EXECUTE ( STANDARD_RIGHTS_EXECUTE_ACCESS | \ + DOMAIN_ACCESS_OPEN_ACCOUNT | \ + DOMAIN_ACCESS_ENUM_ACCOUNTS | \ + DOMAIN_ACCESS_LOOKUP_INFO_1 ) + +//Access bits to User-objects +#define USER_ACCESS_GET_NAME_ETC 0x000000001 +#define USER_ACCESS_GET_LOCALE 0x000000002 +#define USER_ACCESS_SET_LOC_COM 0x000000004 +#define USER_ACCESS_GET_LOGONINFO 0x000000008 +#define USER_ACCESS_UNKNOWN_10 0x000000010 +#define USER_ACCESS_SET_ATTRIBUTES 0x000000020 +#define USER_ACCESS_CHANGE_PASSWORD 0x000000040 +#define USER_ACCESS_SET_PASSWORD 0x000000080 +#define USER_ACCESS_GET_GROUPS 0x000000100 +#define USER_ACCESS_UNKNOWN_200 0x000000200 +#define USER_ACCESS_UNKNOWN_400 0x000000400 + +#define USER_ALL_ACCESS ( STANDARD_RIGHTS_REQUIRED_ACCESS | \ + USER_ACCESS_UNKNOWN_400 | \ + USER_ACCESS_UNKNOWN_200 | \ + USER_ACCESS_GET_GROUPS | \ + USER_ACCESS_SET_PASSWORD | \ + USER_ACCESS_CHANGE_PASSWORD | \ + USER_ACCESS_SET_ATTRIBUTES | \ + USER_ACCESS_UNKNOWN_10 | \ + USER_ACCESS_GET_LOGONINFO | \ + USER_ACCESS_SET_LOC_COM | \ + USER_ACCESS_GET_LOCALE | \ + USER_ACCESS_GET_NAME_ETC ) + +#define USER_READ ( STANDARD_RIGHTS_READ_ACCESS | \ + USER_ACCESS_UNKNOWN_200 | \ + USER_ACCESS_GET_GROUPS | \ + USER_ACCESS_UNKNOWN_10 | \ + USER_ACCESS_GET_LOGONINFO | \ + USER_ACCESS_GET_LOCALE ) + +#define USER_WRITE ( STANDARD_RIGHTS_WRITE_ACCESS | \ + USER_ACCESS_CHANGE_PASSWORD | \ + USER_ACCESS_SET_LOC_COM ) + +#define USER_EXECUTE ( STANDARD_RIGHTS_EXECUTE_ACCESS | \ + USER_ACCESS_CHANGE_PASSWORD | \ + USER_ACCESS_GET_NAME_ETC ) + +//Access bits to Group-objects +#define GROUP_ACCESS_LOOKUP_INFO 0x00000001 +#define GROUP_ACCESS_SET_INFO 0x00000002 +#define GROUP_ACCESS_ADD_MEMBER 0x00000004 +#define GROUP_ACCESS_REMOVE_MEMBER 0x00000008 +#define GROUP_ACCESS_GET_MEMBERS 0x00000010 + +#define GROUP_ALL_ACCESS ( STANDARD_RIGHTS_REQUIRED_ACCESS | \ + GROUP_ACCESS_GET_MEMBERS | \ + GROUP_ACCESS_REMOVE_MEMBER | \ + GROUP_ACCESS_ADD_MEMBER | \ + GROUP_ACCESS_SET_INFO | \ + GROUP_ACCESS_LOOKUP_INFO ) + +#define GROUP_READ ( STANDARD_RIGHTS_READ_ACCESS | \ + GROUP_ACCESS_GET_MEMBERS ) + +#define GROUP_WRITE ( STANDARD_RIGHTS_WRITE_ACCESS | \ + GROUP_ACCESS_REMOVE_MEMBER | \ + GROUP_ACCESS_ADD_MEMBER | \ + GROUP_ACCESS_SET_INFO ) + +#define GROUP_EXECUTE ( STANDARD_RIGHTS_EXECUTE_ACCESS | \ + GROUP_ACCESS_LOOKUP_INFO ) + +//Access bits to Alias-objects +#define ALIAS_ACCESS_ADD_MEMBER 0x00000001 +#define ALIAS_ACCESS_REMOVE_MEMBER 0x00000002 +#define ALIAS_ACCESS_GET_MEMBERS 0x00000004 +#define ALIAS_ACCESS_LOOKUP_INFO 0x00000008 +#define ALIAS_ACCESS_SET_INFO 0x00000010 + +#define ALIAS_ALL_ACCESS ( STANDARD_RIGHTS_REQUIRED_ACCESS | \ + ALIAS_ACCESS_GET_MEMBERS | \ + ALIAS_ACCESS_REMOVE_MEMBER | \ + ALIAS_ACCESS_ADD_MEMBER | \ + ALIAS_ACCESS_SET_INFO | \ + ALIAS_ACCESS_LOOKUP_INFO ) + +#define ALIAS_READ ( STANDARD_RIGHTS_READ_ACCESS | \ + ALIAS_ACCESS_GET_MEMBERS ) + +#define ALIAS_WRITE ( STANDARD_RIGHTS_WRITE_ACCESS | \ + ALIAS_ACCESS_REMOVE_MEMBER | \ + ALIAS_ACCESS_ADD_MEMBER | \ + ALIAS_ACCESS_SET_INFO ) + +#define ALIAS_EXECUTE ( STANDARD_RIGHTS_EXECUTE_ACCESS | \ + ALIAS_ACCESS_LOOKUP_INFO ) + + + typedef struct _DISP_USER_INFO { SAM_ACCOUNT *sam; diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 9393917cde..7a23a55b2a 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -54,11 +54,69 @@ struct samr_info { /* for use by the \PIPE\samr policy */ DOM_SID sid; uint32 status; /* some sort of flag. best to record it. comes from opnum 0x39 */ + uint32 acc_granted; DISP_INFO disp_info; TALLOC_CTX *mem_ctx; }; +struct generic_mapping sam_generic_mapping = {SAMR_READ, SAMR_WRITE, SAMR_EXECUTE, SAMR_ALL_ACCESS}; +struct generic_mapping dom_generic_mapping = {DOMAIN_READ, DOMAIN_WRITE, DOMAIN_EXECUTE, DOMAIN_ALL_ACCESS}; +struct generic_mapping usr_generic_mapping = {USER_READ, USER_WRITE, USER_EXECUTE, USER_ALL_ACCESS}; +struct generic_mapping grp_generic_mapping = {GROUP_READ, GROUP_WRITE, GROUP_EXECUTE, GROUP_ALL_ACCESS}; +struct generic_mapping ali_generic_mapping = {ALIAS_READ, ALIAS_WRITE, ALIAS_EXECUTE, ALIAS_ALL_ACCESS}; + +static NTSTATUS samr_make_dom_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *d_size); + + +/******************************************************************* + Checks if access to an object should be granted, and returns that + level of access for further checks. +********************************************************************/ + +NTSTATUS access_check_samr_object(SEC_DESC *psd, NT_USER_TOKEN *nt_user_token, uint32 des_access, + uint32 *acc_granted, const char *debug) +{ + NTSTATUS status = NT_STATUS_ACCESS_DENIED; + + if (!se_access_check(psd, nt_user_token, des_access, acc_granted, &status)) { + 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")); + status = NT_STATUS_OK; + } + else { + DEBUG(2,("%s: ACCESS DENIED (requested: %#010x)\n", + debug, des_access)); + } + } + return status; +} + +/******************************************************************* + Checks if access to a function can be granted +********************************************************************/ + +NTSTATUS access_check_samr_function(uint32 acc_granted, uint32 acc_required, const char *debug) +{ + DEBUG(5,("%s: access check ((granted: %#010x; required: %#010x)\n", + debug, acc_granted, acc_required)); + if ((acc_granted & acc_required) != acc_required) { + if (geteuid() == sec_initial_uid()) { + DEBUG(4,("%s: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n", + debug, acc_granted, acc_required)); + DEBUGADD(4,("but overwritten by euid == 0\n")); + return NT_STATUS_OK; + } + DEBUG(2,("%s: ACCESS DENIED (granted: %#010x; required: %#010x)\n", + debug, acc_granted, acc_required)); + return NT_STATUS_ACCESS_DENIED; + } + return NT_STATUS_OK; +} + + /******************************************************************* Create a samr_info struct. ********************************************************************/ @@ -276,17 +334,37 @@ NTSTATUS _samr_close_hnd(pipes_struct *p, SAMR_Q_CLOSE_HND *q_u, SAMR_R_CLOSE_HN NTSTATUS _samr_open_domain(pipes_struct *p, SAMR_Q_OPEN_DOMAIN *q_u, SAMR_R_OPEN_DOMAIN *r_u) { - struct samr_info *info; + struct samr_info *info; + SEC_DESC *psd = NULL; + uint32 acc_granted; + uint32 des_access = q_u->flags; + size_t sd_size; + NTSTATUS status; r_u->status = NT_STATUS_OK; /* find the connection policy handle. */ - if (!find_policy_by_hnd(p, &q_u->pol, NULL)) + if (!find_policy_by_hnd(p, &q_u->pol, (void**)&info)) return NT_STATUS_INVALID_HANDLE; + if (!NT_STATUS_IS_OK(status = access_check_samr_function(info->acc_granted, SAMR_ACCESS_OPEN_DOMAIN,"_samr_open_domain"))) { + return status; + } + + /*check if access can be granted as requested by client. */ + samr_make_dom_obj_sd(p->mem_ctx, &psd, &sd_size); + se_map_generic(&des_access,&dom_generic_mapping); + + if (!NT_STATUS_IS_OK(status = + access_check_samr_object(psd, p->pipe_user.nt_user_token, + des_access, &acc_granted, "_samr_open_domain"))) { + return status; + } + /* associate the domain SID with the (unique) handle. */ if ((info = get_samr_info_by_sid(&q_u->dom_sid.sid))==NULL) return NT_STATUS_NO_MEMORY; + info->acc_granted = acc_granted; /* get a (unique) handle. open a policy on it. */ if (!create_policy_hnd(p, &r_u->domain_pol, free_samr_info, (void *)info)) @@ -326,11 +404,90 @@ NTSTATUS _samr_get_usrdom_pwinfo(pipes_struct *p, SAMR_Q_GET_USRDOM_PWINFO *q_u, return r_u->status; } + +/******************************************************************* + samr_make_sam_obj_sd + ********************************************************************/ + +static NTSTATUS samr_make_sam_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size) +{ + extern DOM_SID global_sid_World; + DOM_SID adm_sid; + DOM_SID act_sid; + + SEC_ACE ace[3]; + SEC_ACCESS mask; + + SEC_ACL *psa = NULL; + + sid_copy(&adm_sid, &global_sid_Builtin); + sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS); + + sid_copy(&act_sid, &global_sid_Builtin); + sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS); + + /*basic access for every one*/ + init_sec_access(&mask, SAMR_EXECUTE | SAMR_READ); + init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + /*full access for builtin aliases Administrators and Account Operators*/ + init_sec_access(&mask, SAMR_ALL_ACCESS); + init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL) + return NT_STATUS_NO_MEMORY; + + if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, sd_size)) == NULL) + return NT_STATUS_NO_MEMORY; + + return NT_STATUS_OK; +} + +/******************************************************************* + samr_make_dom_obj_sd + ********************************************************************/ + +static NTSTATUS samr_make_dom_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size) +{ + extern DOM_SID global_sid_World; + DOM_SID adm_sid; + DOM_SID act_sid; + + SEC_ACE ace[3]; + SEC_ACCESS mask; + + SEC_ACL *psa = NULL; + + sid_copy(&adm_sid, &global_sid_Builtin); + sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS); + + sid_copy(&act_sid, &global_sid_Builtin); + sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS); + + /*basic access for every one*/ + init_sec_access(&mask, DOMAIN_EXECUTE | DOMAIN_READ); + init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + /*full access for builtin aliases Administrators and Account Operators*/ + init_sec_access(&mask, DOMAIN_ALL_ACCESS); + init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL) + return NT_STATUS_NO_MEMORY; + + if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, sd_size)) == NULL) + return NT_STATUS_NO_MEMORY; + + return NT_STATUS_OK; +} + /******************************************************************* samr_make_usr_obj_sd ********************************************************************/ -static NTSTATUS samr_make_usr_obj_sd(TALLOC_CTX *ctx, SEC_DESC_BUF **buf, DOM_SID *usr_sid) +static NTSTATUS samr_make_usr_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size, DOM_SID *usr_sid) { extern DOM_SID global_sid_World; DOM_SID adm_sid; @@ -340,8 +497,6 @@ static NTSTATUS samr_make_usr_obj_sd(TALLOC_CTX *ctx, SEC_DESC_BUF **buf, DOM_SI SEC_ACCESS mask; SEC_ACL *psa = NULL; - SEC_DESC *psd = NULL; - size_t sd_size; sid_copy(&adm_sid, &global_sid_Builtin); sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS); @@ -349,29 +504,107 @@ static NTSTATUS samr_make_usr_obj_sd(TALLOC_CTX *ctx, SEC_DESC_BUF **buf, DOM_SI sid_copy(&act_sid, &global_sid_Builtin); sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS); - init_sec_access(&mask, 0x2035b); + /*basic access for every one*/ + init_sec_access(&mask, USER_EXECUTE | USER_READ); init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - init_sec_access(&mask, 0xf07ff); + /*full access for builtin aliases Administrators and Account Operators*/ + init_sec_access(&mask, USER_ALL_ACCESS); init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - init_sec_access(&mask,0x20044); + /*extended access for the user*/ + init_sec_access(&mask,READ_CONTROL_ACCESS | USER_ACCESS_CHANGE_PASSWORD | USER_ACCESS_SET_LOC_COM); init_sec_ace(&ace[3], usr_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - if((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 4, ace)) == NULL) + if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 4, ace)) == NULL) return NT_STATUS_NO_MEMORY; - if((psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, &sd_size)) == NULL) + if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, sd_size)) == NULL) + return NT_STATUS_NO_MEMORY; + + return NT_STATUS_OK; +} + +/******************************************************************* + samr_make_grp_obj_sd + ********************************************************************/ + +static NTSTATUS samr_make_grp_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size) +{ + extern DOM_SID global_sid_World; + DOM_SID adm_sid; + DOM_SID act_sid; + + SEC_ACE ace[3]; + SEC_ACCESS mask; + + SEC_ACL *psa = NULL; + + sid_copy(&adm_sid, &global_sid_Builtin); + sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS); + + sid_copy(&act_sid, &global_sid_Builtin); + sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS); + + /*basic access for every one*/ + init_sec_access(&mask, GROUP_EXECUTE | GROUP_READ); + init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + /*full access for builtin aliases Administrators and Account Operators*/ + init_sec_access(&mask, GROUP_ALL_ACCESS); + init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL) return NT_STATUS_NO_MEMORY; - if((*buf = make_sec_desc_buf(ctx, sd_size, psd)) == NULL) + if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, sd_size)) == NULL) return NT_STATUS_NO_MEMORY; return NT_STATUS_OK; } -static BOOL get_lsa_policy_samr_sid(pipes_struct *p, POLICY_HND *pol, DOM_SID *sid) +/******************************************************************* + samr_make_ali_obj_sd + ********************************************************************/ + +static NTSTATUS samr_make_ali_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size) +{ + extern DOM_SID global_sid_World; + DOM_SID adm_sid; + DOM_SID act_sid; + + SEC_ACE ace[3]; + SEC_ACCESS mask; + + SEC_ACL *psa = NULL; + + sid_copy(&adm_sid, &global_sid_Builtin); + sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS); + + sid_copy(&act_sid, &global_sid_Builtin); + sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS); + + /*basic access for every one*/ + init_sec_access(&mask, ALIAS_EXECUTE | ALIAS_READ); + init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + /*full access for builtin aliases Administrators and Account Operators*/ + init_sec_access(&mask, ALIAS_ALL_ACCESS); + init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL) + return NT_STATUS_NO_MEMORY; + + if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, sd_size)) == NULL) + return NT_STATUS_NO_MEMORY; + + return NT_STATUS_OK; +} + +static BOOL get_lsa_policy_samr_sid(pipes_struct *p, POLICY_HND *pol, DOM_SID *sid, uint32 *acc_granted) { struct samr_info *info = NULL; @@ -383,6 +616,7 @@ static BOOL get_lsa_policy_samr_sid(pipes_struct *p, POLICY_HND *pol, DOM_SID *s return False; *sid = info->sid; + *acc_granted = info->acc_granted; return True; } @@ -394,17 +628,52 @@ NTSTATUS _samr_query_sec_obj(pipes_struct *p, SAMR_Q_QUERY_SEC_OBJ *q_u, SAMR_R_ { DOM_SID pol_sid; fstring str_sid; + SEC_DESC * psd = NULL; + size_t sd_size; + uint32 acc_granted; r_u->status = NT_STATUS_OK; /* Get the SID. */ - - if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &pol_sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &pol_sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; + + DEBUG(10,("_samr_query_sec_obj: querying security on SID: %s\n", sid_to_string(str_sid, &pol_sid))); - r_u->status = samr_make_usr_obj_sd(p->mem_ctx, &r_u->buf, &pol_sid); + /* Check what typ of SID is beeing queried (e.g Domain SID, User SID, Group SID) */ + + /* To query the security of the SAM it self an invalid SID with S-0-0 is passed to this function */ + if (pol_sid.sid_rev_num == 0) + { + DEBUG(5,("_samr_query_sec_obj: querying security on SAM\n")); + r_u->status = samr_make_sam_obj_sd(p->mem_ctx, &psd, &sd_size); + } + else if (sid_equal(&pol_sid,get_global_sam_sid())) //check if it is our domain SID + + { + DEBUG(5,("_samr_query_sec_obj: querying security on Domain with SID: %s\n", sid_to_string(str_sid, &pol_sid))); + r_u->status = samr_make_dom_obj_sd(p->mem_ctx, &psd, &sd_size); + } + else if (sid_equal(&pol_sid,&global_sid_Builtin)) //check if it is the Builtin Domain + { + /* TODO: Builtin probably needs a different SD with restricted write access*/ + DEBUG(5,("_samr_query_sec_obj: querying security on Builtin Domain with SID: %s\n", sid_to_string(str_sid, &pol_sid))); + r_u->status = samr_make_dom_obj_sd(p->mem_ctx, &psd, &sd_size); + } + else if (sid_check_is_in_our_domain(&pol_sid) || + sid_check_is_in_builtin(&pol_sid)) + { + /* TODO: different SDs have to be generated for aliases groups and users. + Currently all three get a default user SD */ + DEBUG(10,("_samr_query_sec_obj: querying security on Object with SID: %s\n", sid_to_string(str_sid, &pol_sid))); + r_u->status = samr_make_usr_obj_sd(p->mem_ctx, &psd,&sd_size, &pol_sid); + } + else return NT_STATUS_OBJECT_TYPE_MISMATCH; + + if ((r_u->buf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL) + return NT_STATUS_NO_MEMORY; if (NT_STATUS_IS_OK(r_u->status)) r_u->ptr = 1; @@ -496,9 +765,14 @@ NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u, if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; - if (!get_lsa_policy_samr_sid(p, &q_u->pol, &domain_sid)) - return NT_STATUS_INVALID_HANDLE; + domain_sid = info->sid; + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted, + DOMAIN_ACCESS_ENUM_ACCOUNTS, + "_samr_enum_dom_users"))) { + return r_u->status; + } + DEBUG(5,("_samr_enum_dom_users: %d\n", __LINE__)); become_root(); @@ -782,11 +1056,16 @@ NTSTATUS _samr_enum_dom_groups(pipes_struct *p, SAMR_Q_ENUM_DOM_GROUPS *q_u, SAM DOMAIN_GRP *grp=NULL; uint32 num_entries; DOM_SID sid; + uint32 acc_granted; r_u->status = NT_STATUS_OK; - if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_ENUM_ACCOUNTS, "_samr_enum_dom_groups"))) { + return r_u->status; + } DEBUG(5,("samr_reply_enum_dom_groups: %d\n", __LINE__)); @@ -814,12 +1093,17 @@ NTSTATUS _samr_enum_dom_aliases(pipes_struct *p, SAMR_Q_ENUM_DOM_ALIASES *q_u, S fstring sid_str; DOM_SID sid; NTSTATUS status; + uint32 acc_granted; r_u->status = NT_STATUS_OK; - if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_ENUM_ACCOUNTS, "_samr_enum_dom_aliases"))) { + return r_u->status; + } + sid_to_string(sid_str, &sid); DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str)); @@ -867,8 +1151,7 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; - if (!get_lsa_policy_samr_sid(p, &q_u->domain_pol, &domain_sid)) - return NT_STATUS_INVALID_HANDLE; + domain_sid = info->sid; /* * calculate how many entries we will return. @@ -1036,22 +1319,26 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, NTSTATUS _samr_query_aliasinfo(pipes_struct *p, SAMR_Q_QUERY_ALIASINFO *q_u, SAMR_R_QUERY_ALIASINFO *r_u) { - struct samr_info *info = NULL; + DOM_SID sid; GROUP_MAP map; + uint32 acc_granted; r_u->status = NT_STATUS_OK; DEBUG(5,("_samr_query_aliasinfo: %d\n", __LINE__)); /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) + if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, ALIAS_ACCESS_LOOKUP_INFO, "_samr_query_aliasinfo"))) { + return r_u->status; + } - if (!sid_check_is_in_our_domain(&info->sid) && - !sid_check_is_in_builtin(&info->sid)) + if (!sid_check_is_in_our_domain(&sid) && + !sid_check_is_in_builtin(&sid)) return NT_STATUS_OBJECT_TYPE_MISMATCH; - if(!get_local_group_from_sid(info->sid, &map, MAPPING_WITHOUT_PRIV)) + if (!get_local_group_from_sid(sid, &map, MAPPING_WITHOUT_PRIV)) return NT_STATUS_NO_SUCH_ALIAS; switch (q_u->switch_level) { @@ -1148,6 +1435,7 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO int num_rids = q_u->num_names2; DOM_SID pol_sid; fstring sid_str; + uint32 acc_granted; r_u->status = NT_STATUS_OK; @@ -1156,10 +1444,14 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO ZERO_ARRAY(rid); ZERO_ARRAY(type); - if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid)) { + if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid, &acc_granted)) { init_samr_r_lookup_names(p->mem_ctx, r_u, 0, NULL, NULL, NT_STATUS_OBJECT_TYPE_MISMATCH); return r_u->status; } + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, 0, "_samr_lookup_names"))) { /* Don't know the acc_bits yet */ + return r_u->status; + } if (num_rids > MAX_SAM_ENTRIES) { num_rids = MAX_SAM_ENTRIES; @@ -1303,13 +1595,14 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK DOM_SID pol_sid; int num_rids = q_u->num_rids1; int i; + uint32 acc_granted; r_u->status = NT_STATUS_OK; DEBUG(5,("_samr_lookup_rids: %d\n", __LINE__)); /* find the policy handle. open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; if (num_rids > MAX_SAM_ENTRIES) { @@ -1371,27 +1664,40 @@ NTSTATUS _api_samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN POLICY_HND domain_pol = q_u->domain_pol; POLICY_HND *user_pol = &r_u->user_pol; struct samr_info *info = NULL; + SEC_DESC *psd = NULL; + uint32 acc_granted; + uint32 des_access = q_u->access_mask; + size_t sd_size; BOOL ret; NTSTATUS nt_status; r_u->status = NT_STATUS_OK; - /* find the domain policy handle. */ - if (!find_policy_by_hnd(p, &domain_pol, NULL)) + /* find the domain policy handle and get domain SID / access bits in the domain policy. */ + if (!get_lsa_policy_samr_sid(p, &domain_pol, &sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; + + if (!NT_STATUS_IS_OK(nt_status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_OPEN_ACCOUNT, "_samr_open_user"))) { + return nt_status; + } nt_status = pdb_init_sam_talloc(p->mem_ctx, &sampass); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } - /* Get the domain SID stored in the domain policy */ - if(!get_lsa_policy_samr_sid(p, &domain_pol, &sid)) - return NT_STATUS_INVALID_HANDLE; - /* append the user's RID to it */ - if(!sid_append_rid(&sid, q_u->user_rid)) + if (!sid_append_rid(&sid, q_u->user_rid)) return NT_STATUS_NO_SUCH_USER; + + /* check if access can be granted as requested by client. */ + samr_make_usr_obj_sd(p->mem_ctx, &psd, &sd_size, &sid); + se_map_generic(&des_access, &usr_generic_mapping); + if (!NT_STATUS_IS_OK(nt_status = + access_check_samr_object(psd, p->pipe_user.nt_user_token, + des_access, &acc_granted, "_samr_open_user"))) { + return nt_status; + } become_root(); ret=pdb_getsampwsid(sampass, &sid); @@ -1404,9 +1710,10 @@ NTSTATUS _api_samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN pdb_free_sam(&sampass); - /* associate the user's SID with the new handle. */ + /* associate the user's SID and access bits with the new handle. */ if ((info = get_samr_info_by_sid(&sid)) == NULL) return NT_STATUS_NO_MEMORY; + info->acc_granted = acc_granted; /* get a (unique) handle. open a policy on it. */ if (!create_policy_hnd(p, user_pol, free_samr_info, (void *)info)) @@ -1685,9 +1992,10 @@ NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, SAMR_R_QUERY_USERGROUPS *r_u) { SAM_ACCOUNT *sam_pass=NULL; + DOM_SID sid; DOM_GID *gids = NULL; int num_groups = 0; - struct samr_info *info = NULL; + uint32 acc_granted; BOOL ret; /* @@ -1707,16 +2015,20 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S DEBUG(5,("_samr_query_usergroups: %d\n", __LINE__)); /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) + if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, USER_ACCESS_GET_GROUPS, "_samr_query_usergroups"))) { + return r_u->status; + } - if (!sid_check_is_in_our_domain(&info->sid)) + if (!sid_check_is_in_our_domain(&sid)) return NT_STATUS_OBJECT_TYPE_MISMATCH; pdb_init_sam(&sam_pass); become_root(); - ret = pdb_getsampwsid(sam_pass, &info->sid); + ret = pdb_getsampwsid(sam_pass, &sid); unbecome_root(); if (ret == False) { @@ -1866,11 +2178,19 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_ BOOL ret; NTSTATUS nt_status; struct passwd *pw; + uint32 acc_granted; + SEC_DESC *psd; + size_t sd_size; + uint32 des_access; - /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, &dom_pol, NULL)) + /* Get the domain SID stored in the domain policy */ + if (!get_lsa_policy_samr_sid(p, &dom_pol, &sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; + if (!NT_STATUS_IS_OK(nt_status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_CREATE_USER, "_samr_create_user"))) { + return nt_status; + } + /* find the account: tell the caller if it exists. lkclXXXX i have *no* idea if this is a problem or not or even if you are supposed to construct a different @@ -1939,7 +2259,7 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_ else pstrcpy(add_script, lp_adduser_script()); - if(*add_script) { + if (*add_script) { int add_ret; all_string_sub(add_script, "%u", account, sizeof(account)); add_ret = smbrun(add_script,NULL); @@ -1988,6 +2308,14 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_ /* Get the user's SID */ sid_copy(&sid, pdb_get_user_sid(sam_pass)); + samr_make_usr_obj_sd(p->mem_ctx, &psd, &sd_size, &sid); + se_map_generic(&des_access, &usr_generic_mapping); + if (!NT_STATUS_IS_OK(nt_status = + access_check_samr_object(psd, p->pipe_user.nt_user_token, + des_access, &acc_granted, "_samr_create_user"))) { + return nt_status; + } + /* associate the user's SID with the new handle. */ if ((info = get_samr_info_by_sid(&sid)) == NULL) { pdb_free_sam(&sam_pass); @@ -1996,6 +2324,7 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_ ZERO_STRUCTP(info); info->sid = sid; + info->acc_granted = acc_granted; /* get a (unique) handle. open a policy on it. */ if (!create_policy_hnd(p, user_pol, free_samr_info, (void *)info)) { @@ -2019,29 +2348,29 @@ NTSTATUS _samr_connect_anon(pipes_struct *p, SAMR_Q_CONNECT_ANON *q_u, SAMR_R_CO { struct samr_info *info = NULL; - /* Access check */ + /* Access check */ - if (!pipe_access_check(p)) { - DEBUG(3, ("access denied to samr_connect_anon\n")); - r_u->status = NT_STATUS_ACCESS_DENIED; - return r_u->status; - } + if (!pipe_access_check(p)) { + DEBUG(3, ("access denied to samr_connect_anon\n")); + r_u->status = NT_STATUS_ACCESS_DENIED; + return r_u->status; + } - /* set up the SAMR connect_anon response */ + /* set up the SAMR connect_anon response */ - r_u->status = NT_STATUS_OK; + r_u->status = NT_STATUS_OK; - /* associate the user's SID with the new handle. */ - if ((info = get_samr_info_by_sid(NULL)) == NULL) - return NT_STATUS_NO_MEMORY; + /* associate the user's SID with the new handle. */ + if ((info = get_samr_info_by_sid(NULL)) == NULL) + return NT_STATUS_NO_MEMORY; - info->status = q_u->unknown_0; + info->status = q_u->unknown_0; - /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info)) - return NT_STATUS_OBJECT_NAME_NOT_FOUND; + /* get a (unique) handle. open a policy on it. */ + if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info)) + return NT_STATUS_OBJECT_NAME_NOT_FOUND; - return r_u->status; + return r_u->status; } /******************************************************************* @@ -2051,32 +2380,47 @@ NTSTATUS _samr_connect_anon(pipes_struct *p, SAMR_Q_CONNECT_ANON *q_u, SAMR_R_CO NTSTATUS _samr_connect(pipes_struct *p, SAMR_Q_CONNECT *q_u, SAMR_R_CONNECT *r_u) { struct samr_info *info = NULL; + SEC_DESC *psd = NULL; + uint32 acc_granted; + uint32 des_access = q_u->access_mask; + size_t sd_size; + NTSTATUS nt_status; - DEBUG(5,("_samr_connect: %d\n", __LINE__)); - /* Access check */ + DEBUG(5,("_samr_connect: %d\n", __LINE__)); - if (!pipe_access_check(p)) { - DEBUG(3, ("access denied to samr_connect\n")); - r_u->status = NT_STATUS_ACCESS_DENIED; - return r_u->status; - } + /* Access check */ - r_u->status = NT_STATUS_OK; + if (!pipe_access_check(p)) { + DEBUG(3, ("access denied to samr_connect\n")); + r_u->status = NT_STATUS_ACCESS_DENIED; + return r_u->status; + } + + samr_make_sam_obj_sd(p->mem_ctx, &psd, &sd_size); + se_map_generic(&des_access, &sam_generic_mapping); + if (!NT_STATUS_IS_OK(nt_status = + access_check_samr_object(psd, p->pipe_user.nt_user_token, + des_access, &acc_granted, "_samr_connect"))) { + return nt_status; + } + + r_u->status = NT_STATUS_OK; - /* associate the user's SID with the new handle. */ + /* associate the user's SID and access granted with the new handle. */ if ((info = get_samr_info_by_sid(NULL)) == NULL) - return NT_STATUS_NO_MEMORY; + return NT_STATUS_NO_MEMORY; - info->status = q_u->access_mask; + info->acc_granted = acc_granted; + info->status = q_u->access_mask; - /* get a (unique) handle. open a policy on it. */ - if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info)) - return NT_STATUS_OBJECT_NAME_NOT_FOUND; + /* get a (unique) handle. open a policy on it. */ + if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info)) + return NT_STATUS_OBJECT_NAME_NOT_FOUND; - DEBUG(5,("_samr_connect: %d\n", __LINE__)); + DEBUG(5,("_samr_connect: %d\n", __LINE__)); - return r_u->status; + return r_u->status; } /********************************************************************** @@ -2085,14 +2429,19 @@ NTSTATUS _samr_connect(pipes_struct *p, SAMR_Q_CONNECT *q_u, SAMR_R_CONNECT *r_u NTSTATUS _samr_lookup_domain(pipes_struct *p, SAMR_Q_LOOKUP_DOMAIN *q_u, SAMR_R_LOOKUP_DOMAIN *r_u) { + struct samr_info *info; fstring domain_name; DOM_SID sid; r_u->status = NT_STATUS_OK; - if (!find_policy_by_hnd(p, &q_u->connect_pol, NULL)) + if (!find_policy_by_hnd(p, &q_u->connect_pol, (void**)&info)) return NT_STATUS_INVALID_HANDLE; + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted, SAMR_ACCESS_OPEN_DOMAIN, "_samr_lookup_domain"))) { + return r_u->status; + } + rpcstr_pull(domain_name, q_u->uni_domain.buffer, sizeof(domain_name), q_u->uni_domain.uni_str_len*2, 0); ZERO_STRUCT(sid); @@ -2152,11 +2501,19 @@ static BOOL make_enum_domains(TALLOC_CTX *ctx, SAM_ENTRY **pp_sam, NTSTATUS _samr_enum_domains(pipes_struct *p, SAMR_Q_ENUM_DOMAINS *q_u, SAMR_R_ENUM_DOMAINS *r_u) { + struct samr_info *info; uint32 num_entries = 2; fstring dom[2]; char *name; r_u->status = NT_STATUS_OK; + + if (!find_policy_by_hnd(p, &q_u->pol, (void**)&info)) + return NT_STATUS_INVALID_HANDLE; + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted, SAMR_ACCESS_ENUM_DOMAINS, "_samr_enum_domains"))) { + return r_u->status; + } switch (lp_server_role()) { case ROLE_DOMAIN_PDC: @@ -2189,21 +2546,35 @@ NTSTATUS _api_samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OP POLICY_HND domain_pol = q_u->dom_pol; uint32 alias_rid = q_u->rid_alias; POLICY_HND *alias_pol = &r_u->pol; - struct samr_info *info = NULL; + struct samr_info *info = NULL; + SEC_DESC *psd = NULL; + uint32 acc_granted; + uint32 des_access = q_u->access_mask; + size_t sd_size; + NTSTATUS status; r_u->status = NT_STATUS_OK; - /* get the domain policy. */ - if (!find_policy_by_hnd(p, &domain_pol, NULL)) - return NT_STATUS_INVALID_HANDLE; - - /* Get the domain SID stored in the domain policy */ - if(!get_lsa_policy_samr_sid(p, &domain_pol, &sid)) + /* find the domain policy and get the SID / access bits stored in the domain policy */ + if (!get_lsa_policy_samr_sid(p, &domain_pol, &sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; + + if (!NT_STATUS_IS_OK(status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_OPEN_ACCOUNT, "_samr_open_alias"))) { + return status; + } /* append the alias' RID to it */ - if(!sid_append_rid(&sid, alias_rid)) + if (!sid_append_rid(&sid, alias_rid)) return NT_STATUS_NO_SUCH_USER; + + /*check if access can be granted as requested by client. */ + samr_make_ali_obj_sd(p->mem_ctx, &psd, &sd_size); + se_map_generic(&des_access,&ali_generic_mapping); + if (!NT_STATUS_IS_OK(status = + access_check_samr_object(psd, p->pipe_user.nt_user_token, + des_access, &acc_granted, "_samr_open_alias"))) { + return status; + } /* * we should check if the rid really exist !!! @@ -2213,6 +2584,8 @@ NTSTATUS _api_samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OP /* associate the user's SID with the new handle. */ if ((info = get_samr_info_by_sid(&sid)) == NULL) return NT_STATUS_NO_MEMORY; + + info->acc_granted = acc_granted; /* get a (unique) handle. open a policy on it. */ if (!create_policy_hnd(p, alias_pol, free_samr_info, (void *)info)) @@ -2486,15 +2859,22 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE POLICY_HND *pol = &q_u->pol; uint16 switch_value = q_u->switch_value; SAM_USERINFO_CTR *ctr = q_u->ctr; + uint32 acc_granted; + uint32 acc_required; DEBUG(5, ("_samr_set_userinfo: %d\n", __LINE__)); r_u->status = NT_STATUS_OK; /* find the policy handle. open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, pol, &sid)) + if (!get_lsa_policy_samr_sid(p, pol, &sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; - + + acc_required = USER_ACCESS_SET_LOC_COM | USER_ACCESS_SET_ATTRIBUTES; /* This is probably wrong */ + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, acc_required, "_samr_set_userinfo"))) { + return r_u->status; + } + DEBUG(5, ("_samr_set_userinfo: sid:%s, level:%d\n", sid_string_static(&sid), switch_value)); if (ctr == NULL) { @@ -2564,14 +2944,21 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_ SAM_USERINFO_CTR *ctr = q_u->ctr; POLICY_HND *pol = &q_u->pol; uint16 switch_value = q_u->switch_value; + uint32 acc_granted; + uint32 acc_required; DEBUG(5, ("samr_reply_set_userinfo2: %d\n", __LINE__)); r_u->status = NT_STATUS_OK; /* find the policy handle. open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, pol, &sid)) + if (!get_lsa_policy_samr_sid(p, pol, &sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; + + acc_required = USER_ACCESS_SET_LOC_COM | USER_ACCESS_SET_ATTRIBUTES; /* This is probably wrong */ + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, acc_required, "_samr_set_userinfo2"))) { + return r_u->status; + } DEBUG(5, ("samr_reply_set_userinfo2: sid:%s\n", sid_string_static(&sid))); @@ -2638,6 +3025,10 @@ NTSTATUS _samr_query_useraliases(pipes_struct *p, SAMR_Q_QUERY_USERALIASES *q_u, /* find the policy handle. open a policy on it. */ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted, USER_ACCESS_GET_GROUPS, "_samr_query_useraliases"))) { + return r_u->status; + } if (!sid_check_is_domain(&info->sid) && !sid_check_is_builtin(&info->sid)) @@ -2702,11 +3093,16 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_ SAM_ACCOUNT *sam_user = NULL; BOOL check; + uint32 acc_granted; /* find the policy handle. open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; - + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, ALIAS_ACCESS_GET_MEMBERS, "_samr_query_aliasmem"))) { + return r_u->status; + } + sid_copy(&als_sid, &alias_sid); sid_to_string(alias_sid_str, &alias_sid); sid_split_rid(&alias_sid, &alias_rid); @@ -2798,12 +3194,16 @@ NTSTATUS _samr_query_groupmem(pipes_struct *p, SAMR_Q_QUERY_GROUPMEM *q_u, SAMR_ SAM_ACCOUNT *sam_user = NULL; BOOL check; - + uint32 acc_granted; /* find the policy handle. open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; - + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, GROUP_ACCESS_GET_MEMBERS, "_samr_query_groupmem"))) { + return r_u->status; + } + /* todo: change to use sid_compare_front */ sid_split_rid(&group_sid, &group_rid); @@ -2886,11 +3286,16 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD NTSTATUS ret; SAM_ACCOUNT *sam_user = NULL; BOOL check; + uint32 acc_granted; /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; - + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, ALIAS_ACCESS_ADD_MEMBER, "_samr_add_aliasmem"))) { + return r_u->status; + } + sid_to_string(alias_sid_str, &alias_sid); DEBUG(10, ("sid is %s\n", alias_sid_str)); @@ -2969,11 +3374,16 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE fstring grp_name; GROUP_MAP map; SAM_ACCOUNT *sam_pass=NULL; + uint32 acc_granted; /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; - + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, ALIAS_ACCESS_REMOVE_MEMBER, "_samr_del_aliasmem"))) { + return r_u->status; + } + sid_to_string(alias_sid_str, &alias_sid); DEBUG(10, ("_samr_del_aliasmem:sid is %s\n", alias_sid_str)); @@ -3035,10 +3445,15 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD NTSTATUS ret; SAM_ACCOUNT *sam_user; BOOL check; + uint32 acc_granted; /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, GROUP_ACCESS_ADD_MEMBER, "_samr_add_groupmem"))) { + return r_u->status; + } sid_to_string(group_sid_str, &group_sid); DEBUG(10, ("sid is %s\n", group_sid_str)); @@ -3116,6 +3531,7 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE GROUP_MAP map; fstring grp_name; struct group *grp; + uint32 acc_granted; /* * delete the group member named q_u->rid @@ -3124,16 +3540,20 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE */ /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; - - if(!sid_check_is_in_our_domain(&group_sid)) + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, GROUP_ACCESS_REMOVE_MEMBER, "_samr_del_groupmem"))) { + return r_u->status; + } + + if (!sid_check_is_in_our_domain(&group_sid)) return NT_STATUS_NO_SUCH_GROUP; sid_copy(&user_sid, get_global_sam_sid()); sid_append_rid(&user_sid, q_u->rid); - if(!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV)) + if (!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV)) return NT_STATUS_NO_SUCH_GROUP; if ((grp=getgrgid(map.gid)) == NULL) @@ -3144,14 +3564,14 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE /* check if the user exists before trying to remove it from the group */ pdb_init_sam(&sam_pass); - if(!pdb_getsampwsid(sam_pass, &user_sid)) { + if (!pdb_getsampwsid(sam_pass, &user_sid)) { DEBUG(5,("User %s doesn't exist.\n", pdb_get_username(sam_pass))); pdb_free_sam(&sam_pass); return NT_STATUS_NO_SUCH_USER; } /* if the user is not in the group */ - if(!user_in_group_list(pdb_get_username(sam_pass), grp_name)) { + if (!user_in_group_list(pdb_get_username(sam_pass), grp_name)) { pdb_free_sam(&sam_pass); return NT_STATUS_MEMBER_NOT_IN_GROUP; } @@ -3159,7 +3579,7 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE smb_delete_user_group(grp_name, pdb_get_username(sam_pass)); /* check if the user has been removed then ... */ - if(user_in_group_list(pdb_get_username(sam_pass), grp_name)) { + if (user_in_group_list(pdb_get_username(sam_pass), grp_name)) { pdb_free_sam(&sam_pass); return NT_STATUS_ACCESS_DENIED; /* don't know what to reply else */ } @@ -3195,13 +3615,18 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM { DOM_SID user_sid; SAM_ACCOUNT *sam_pass=NULL; + uint32 acc_granted; DEBUG(5, ("_samr_delete_dom_user: %d\n", __LINE__)); /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &user_sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &user_sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; - + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DELETE_ACCESS, "_samr_delete_dom_user"))) { + return r_u->status; + } + if (!sid_check_is_in_our_domain(&user_sid)) return NT_STATUS_CANNOT_DELETE; @@ -3249,13 +3674,18 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S gid_t gid; struct group *grp; GROUP_MAP map; + uint32 acc_granted; DEBUG(5, ("samr_delete_dom_group: %d\n", __LINE__)); /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; - + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DELETE_ACCESS, "_samr_delete_dom_group"))) { + return r_u->status; + } + sid_copy(&dom_sid, &group_sid); sid_to_string(group_sid_str, &dom_sid); sid_split_rid(&dom_sid, &group_rid); @@ -3306,13 +3736,18 @@ NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, S gid_t gid; struct group *grp; GROUP_MAP map; + uint32 acc_granted; DEBUG(5, ("_samr_delete_dom_alias: %d\n", __LINE__)); /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; - + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DELETE_ACCESS, "_samr_delete_dom_alias"))) { + return r_u->status; + } + sid_copy(&dom_sid, &alias_sid); sid_to_string(alias_sid_str, &dom_sid); sid_split_rid(&dom_sid, &alias_rid); @@ -3363,13 +3798,18 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S struct group *grp; struct samr_info *info; PRIVILEGE_SET priv_set; + uint32 acc_granted; init_privilege(&priv_set); /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->pol, &dom_sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->pol, &dom_sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; - + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_CREATE_GROUP, "_samr_create_dom_group"))) { + return r_u->status; + } + if (!sid_equal(&dom_sid, get_global_sam_sid())) return NT_STATUS_ACCESS_DENIED; @@ -3421,13 +3861,18 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S struct group *grp; struct samr_info *info; PRIVILEGE_SET priv_set; + uint32 acc_granted; init_privilege(&priv_set); /* Find the policy handle. Open a policy on it. */ - if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &dom_sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &dom_sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; - + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_CREATE_ALIAS, "_samr_create_alias"))) { + return r_u->status; + } + if (!sid_equal(&dom_sid, get_global_sam_sid())) return NT_STATUS_ACCESS_DENIED; @@ -3480,10 +3925,15 @@ NTSTATUS _samr_query_groupinfo(pipes_struct *p, SAMR_Q_QUERY_GROUPINFO *q_u, SAM uid_t *uid=NULL; int num_uids=0; GROUP_INFO_CTR *ctr; + uint32 acc_granted; - if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; - + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, GROUP_ACCESS_LOOKUP_INFO, "_samr_query_groupinfo"))) { + return r_u->status; + } + if (!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV)) return NT_STATUS_INVALID_HANDLE; @@ -3527,10 +3977,15 @@ NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_ DOM_SID group_sid; GROUP_MAP map; GROUP_INFO_CTR *ctr; + uint32 acc_granted; - if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; - + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, GROUP_ACCESS_SET_INFO, "_samr_set_groupinfo"))) { + return r_u->status; + } + if (!get_domain_group_from_sid(group_sid, &map, MAPPING_WITH_PRIV)) return NT_STATUS_NO_SUCH_GROUP; @@ -3569,10 +4024,15 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_ DOM_SID group_sid; GROUP_MAP map; ALIAS_INFO_CTR *ctr; + uint32 acc_granted; - if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &group_sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &group_sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; - + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, ALIAS_ACCESS_SET_INFO, "_samr_set_aliasinfo"))) { + return r_u->status; + } + if (!get_local_group_from_sid(group_sid, &map, MAPPING_WITH_PRIV)) return NT_STATUS_NO_SUCH_GROUP; @@ -3628,10 +4088,29 @@ NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_G DOM_SID info_sid; GROUP_MAP map; struct samr_info *info; + SEC_DESC *psd = NULL; + uint32 acc_granted; + uint32 des_access; + size_t sd_size; + NTSTATUS status; fstring sid_string; - if (!get_lsa_policy_samr_sid(p, &q_u->domain_pol, &sid)) + if (!get_lsa_policy_samr_sid(p, &q_u->domain_pol, &sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; + + if (!NT_STATUS_IS_OK(status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_OPEN_ACCOUNT, "_samr_open_group"))) { + return status; + } + + /*check if access can be granted as requested by client. */ + samr_make_grp_obj_sd(p->mem_ctx, &psd, &sd_size); + se_map_generic(&des_access,&grp_generic_mapping); + if (!NT_STATUS_IS_OK(status = + access_check_samr_object(psd, p->pipe_user.nt_user_token, + des_access, &acc_granted, "_samr_open_group"))) { + return status; + } + /* this should not be hard-coded like this */ if (!sid_equal(&sid, get_global_sam_sid())) @@ -3643,6 +4122,8 @@ NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_G if ((info = get_samr_info_by_sid(&info_sid)) == NULL) return NT_STATUS_NO_MEMORY; + + info->acc_granted = acc_granted; DEBUG(10, ("_samr_open_group:Opening SID: %s\n", sid_string)); |