BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2) { /* Trivial case */ if (!s1 && !s2) { return True; } if (!s1 || !s2) { return False; } /* Check top level stuff */ if (s1->type != s2->type || s1->flags != s2->flags || s1->access_mask != s2->access_mask) { return False; } /* Check SID */ if (!sid_equal(&s1->trustee, &s2->trustee)) { return False; } return True; }
bool non_mappable_sid(DOM_SID *sid) { DOM_SID dom; uint32 rid; sid_copy(&dom, sid); sid_split_rid(&dom, &rid); if (sid_equal(&dom, &global_sid_Builtin)) return True; if (sid_equal(&dom, &global_sid_NT_Authority)) return True; return False; }
NTSTATUS idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) { struct idmap_methods *map = remote_map; DOM_SID tmp_sid; if (proxyonly) return NT_STATUS_UNSUCCESSFUL; DEBUG(10, ("idmap_set_mapping: Set %s to %s %lu\n", sid_string_static(sid), ((id_type & ID_TYPEMASK) == ID_USERID) ? "UID" : "GID", ((id_type & ID_TYPEMASK) == ID_USERID) ? (unsigned long)id.uid : (unsigned long)id.gid)); if ( (NT_STATUS_IS_OK(cache_map-> get_sid_from_id(&tmp_sid, id, id_type | ID_QUERY_ONLY))) && sid_equal(sid, &tmp_sid) ) { /* Nothing to do, we already have that mapping */ DEBUG(10, ("idmap_set_mapping: Mapping already there\n")); return NT_STATUS_OK; } if (map == NULL) { /* Ok, we don't have a authoritative remote mapping. So update our local cache only. */ map = cache_map; } return map->set_mapping(sid, id, id_type); }
BOOL map_domain_sid_to_name(DOM_SID *sid, fstring nt_domain) { fstring sid_str; int i = 0; sid_to_string(sid_str, sid); if (!sid_name_map_initialized) init_sid_name_map(); DEBUG(5,("map_domain_sid_to_name: %s\n", sid_str)); if (nt_domain == NULL) return False; while (sid_name_map[i].sid != NULL) { sid_to_string(sid_str, sid_name_map[i].sid); DEBUG(5,("map_domain_sid_to_name: compare: %s\n", sid_str)); if (sid_equal(sid_name_map[i].sid, sid)) { fstrcpy(nt_domain, sid_name_map[i].name); DEBUG(5,("map_domain_sid_to_name: found '%s'\n", nt_domain)); return True; } i++; } DEBUG(5,("map_domain_sid_to_name: mapping for %s not found\n", sid_str)); return False; }
BOOL lookup_known_rid(DOM_SID *sid, uint32 rid, char *name, enum SID_NAME_USE *psid_name_use) { int i = 0; struct sid_name_map_info *psnm; if (!sid_name_map_initialized) init_sid_name_map(); for(i = 0; sid_name_map[i].sid != NULL; i++) { psnm = &sid_name_map[i]; if(sid_equal(psnm->sid, sid)) { int j; for(j = 0; psnm->known_users && psnm->known_users[j].known_user_name != NULL; j++) { if(rid == psnm->known_users[j].rid) { DEBUG(5,("lookup_builtin_rid: rid = %u, domain = '%s', user = '******'\n", (unsigned int)rid, psnm->name, psnm->known_users[j].known_user_name )); fstrcpy( name, psnm->known_users[j].known_user_name); *psid_name_use = psnm->known_users[j].sid_name_use; return True; } } } } return False; }
BOOL sid_check_is_in_our_domain(const DOM_SID *sid) { DOM_SID dom_sid; uint32 rid; sid_copy(&dom_sid, sid); sid_split_rid(&dom_sid, &rid); return sid_equal(&dom_sid, get_global_sam_sid()); }
BOOL sid_check_is_in_builtin(const DOM_SID *sid) { DOM_SID dom_sid; uint32 rid; sid_copy(&dom_sid, sid); sid_split_rid(&dom_sid, &rid); return sid_equal(&dom_sid, &global_sid_Builtin); }
BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace) { size_t i; for (i = 0; i < token->num_sids; i++) { if (sid_equal(&ace->trustee, &token->user_sids[i])) return True; } return False; }
bool token_sid_in_ace(const NT_USER_TOKEN *token, const struct security_ace *ace) { size_t i; for (i = 0; i < token->num_sids; i++) { if (sid_equal(&ace->trustee, &token->user_sids[i])) return true; } return false; }
/** * Turn SID into UID/GID and setup a struct ifs_identity */ static bool onefs_sid_to_identity(const struct dom_sid *sid, struct ifs_identity *id, bool is_group) { enum ifs_identity_type type = IFS_ID_TYPE_LAST+1; uid_t uid = 0; gid_t gid = 0; if (!sid || sid_equal(sid, &global_sid_NULL)) type = IFS_ID_TYPE_NULL; else if (sid_equal(sid, &global_sid_World)) type = IFS_ID_TYPE_EVERYONE; else if (sid_equal(sid, &global_sid_Creator_Owner)) type = IFS_ID_TYPE_CREATOR_OWNER; else if (sid_equal(sid, &global_sid_Creator_Group)) type = IFS_ID_TYPE_CREATOR_GROUP; else if (is_group) { if (!sid_to_gid(sid, &gid)) return false; type = IFS_ID_TYPE_GID; } else { if (sid_to_uid(sid, &uid)) type = IFS_ID_TYPE_UID; else if (sid_to_gid(sid, &gid)) type = IFS_ID_TYPE_GID; else return false; } if (aclu_initialize_identity(id, type, uid, gid, is_group)) { DEBUG(3, ("Call to aclu_initialize_identity failed! id=%x, " "type=%d, uid=%u, gid=%u, is_group=%d\n", (unsigned int)id, type, uid, gid, is_group)); return false; } return true; }
/* this function searches up to IDMAP_LDAP_MAX_IDS entries * in maps for a match */ static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid) { int i; for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) { if (maps[i] == NULL) { /* end of the run */ return NULL; } if (sid_equal(maps[i]->sid, sid)) { return maps[i]; } } return NULL; }
/* add a SID to the list of SIDs for a right */ NTSTATUS privilege_add_account_right(const char *right, DOM_SID *sid) { NTSTATUS status; DOM_SID *current_sids; uint32 current_count; int i; status = privilege_lock_right(right); if (!NT_STATUS_IS_OK(status)) { return status; } status = privilege_enum_account_with_right(right, ¤t_count, ¤t_sids); if (!NT_STATUS_IS_OK(status)) { privilege_unlock_right(right); return status; } /* maybe that SID is already listed? this is not an error */ for (i=0;i<current_count;i++) { if (sid_equal(¤t_sids[i], sid)) { privilege_unlock_right(right); free(current_sids); return NT_STATUS_OK; } } /* add it in */ current_sids = Realloc(current_sids, sizeof(current_sids[0]) * (current_count+1)); if (!current_sids) { privilege_unlock_right(right); return NT_STATUS_NO_MEMORY; } sid_copy(¤t_sids[current_count], sid); current_count++; status = privilege_set_accounts_with_right(right, current_count, current_sids); free(current_sids); privilege_unlock_right(right); return status; }
enum winbindd_result winbindd_lookupsid(struct winbindd_cli_state *state) { extern DOM_SID global_sid_Builtin; enum SID_NAME_USE type; DOM_SID sid, tmp_sid; uint32 rid; fstring name; fstring dom_name; /* Ensure null termination */ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state->pid, state->request.data.sid)); /* Lookup sid from PDC using lsa_lookup_sids() */ if (!string_to_sid(&sid, state->request.data.sid)) { DEBUG(5, ("%s not a SID\n", state->request.data.sid)); return WINBINDD_ERROR; } /* Don't look up BUILTIN sids */ sid_copy(&tmp_sid, &sid); sid_split_rid(&tmp_sid, &rid); if (sid_equal(&tmp_sid, &global_sid_Builtin)) { return WINBINDD_ERROR; } /* Lookup the sid */ if (!winbindd_lookup_name_by_sid(&sid, dom_name, name, &type)) { return WINBINDD_ERROR; } fstrcpy(state->response.data.name.dom_name, dom_name); fstrcpy(state->response.data.name.name, name); state->response.data.name.type = type; return WINBINDD_OK; }
/* remove a SID from the list of SIDs for a right */ NTSTATUS privilege_remove_account_right(const char *right, DOM_SID *sid) { NTSTATUS status; DOM_SID *current_sids; uint32 current_count; int i; status = privilege_lock_right(right); if (!NT_STATUS_IS_OK(status)) { return status; } status = privilege_enum_account_with_right(right, ¤t_count, ¤t_sids); if (!NT_STATUS_IS_OK(status)) { privilege_unlock_right(right); return status; } for (i=0;i<current_count;i++) { if (sid_equal(¤t_sids[i], sid)) { /* found it - so remove it */ if (current_count-i > 1) { memmove(¤t_sids[i], ¤t_sids[i+1], sizeof(current_sids[0]) * ((current_count-i)-1)); } current_count--; status = privilege_set_accounts_with_right(right, current_count, current_sids); free(current_sids); privilege_unlock_right(right); return status; } } /* removing a right that you don't have is not an error */ safe_free(current_sids); privilege_unlock_right(right); return NT_STATUS_OK; }
/* an internal function for checking if a SID has a right */ static BOOL privilege_sid_has_right(DOM_SID *sid, const char *right) { NTSTATUS status; uint32 count; DOM_SID *sids; int i; status = privilege_enum_account_with_right(right, &count, &sids); if (!NT_STATUS_IS_OK(status)) { return False; } for (i=0;i<count;i++) { if (sid_equal(sid, &sids[i])) { free(sids); return True; } } safe_free(sids); return False; }
BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type) { if (!name_type) return False; *name_type = SID_NAME_UNKNOWN; /* Check if this is our own sid. This should perhaps be done by winbind? For the moment handle it here. */ if (sid->num_auths == 5) { DOM_SID tmp_sid; uint32 rid; sid_copy(&tmp_sid, sid); sid_split_rid(&tmp_sid, &rid); if (sid_equal(&global_sam_sid, &tmp_sid)) { return map_domain_sid_to_name(&tmp_sid, dom_name) && local_lookup_rid(rid, name, name_type); } } if (!winbind_lookup_sid(sid, dom_name, name, name_type)) { fstring sid_str; DOM_SID tmp_sid; uint32 rid; DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying local.\n", sid_to_string(sid_str, sid) )); sid_copy(&tmp_sid, sid); sid_split_rid(&tmp_sid, &rid); return map_domain_sid_to_name(&tmp_sid, dom_name) && lookup_known_rid(&tmp_sid, rid, name, name_type); } return True; }
static bool sid_in_ignore_list(struct dom_sid * sid, int snum) { const char ** sid_list = NULL; struct dom_sid match; sid_list = lp_parm_string_list(snum, PARM_ONEFS_TYPE, PARM_UNMAPPABLE_SIDS_IGNORE_LIST, PARM_UNMAPPABLE_SIDS_IGNORE_LIST_DEFAULT); /* Fast path a NULL list */ if (!sid_list || *sid_list == NULL) return false; while (*sid_list) { if (string_to_sid(&match, *sid_list)) if (sid_equal(sid, &match)) return true; sid_list++; } return false; }
void del_sid_from_array(const DOM_SID *sid, DOM_SID **sids, size_t *num) { DOM_SID *sid_list = *sids; size_t i; for ( i=0; i<*num; i++ ) { /* if we find the SID, then decrement the count and break out of the loop */ if ( sid_equal(sid, &sid_list[i]) ) { *num -= 1; break; } } /* This loop will copy the remainder of the array if i < num of sids ni the array */ for ( ; i<*num; i++ ) sid_copy( &sid_list[i], &sid_list[i+1] ); return; }
BOOL sid_check_is_builtin(const DOM_SID *sid) { return sid_equal(sid, &global_sid_Builtin); }
bool sid_check_is_unix_groups(const DOM_SID *sid) { return sid_equal(sid, &global_sid_Unix_Groups); }
bool sid_check_is_unix_users(const DOM_SID *sid) { return sid_equal(sid, &global_sid_Unix_Users); }
static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, NET_USER_INFO_3 *info3, const char *group_sid) { DOM_SID required_membership_sid; DOM_SID *all_sids; size_t num_all_sids = (2 + info3->num_groups2 + info3->num_other_sids); size_t i, j = 0; /* Parse the 'required group' SID */ if (!group_sid || !group_sid[0]) { /* NO sid supplied, all users may access */ return NT_STATUS_OK; } if (!string_to_sid(&required_membership_sid, group_sid)) { DEBUG(0, ("check_info3_in_group: could not parse %s as a SID!", group_sid)); return NT_STATUS_INVALID_PARAMETER; } all_sids = talloc(mem_ctx, sizeof(DOM_SID) * num_all_sids); if (!all_sids) return NT_STATUS_NO_MEMORY; /* and create (by appending rids) the 'domain' sids */ sid_copy(&all_sids[0], &(info3->dom_sid.sid)); if (!sid_append_rid(&all_sids[0], info3->user_rid)) { DEBUG(3,("could not append user's primary RID 0x%x\n", info3->user_rid)); return NT_STATUS_INVALID_PARAMETER; } j++; sid_copy(&all_sids[1], &(info3->dom_sid.sid)); if (!sid_append_rid(&all_sids[1], info3->group_rid)) { DEBUG(3,("could not append additional group rid 0x%x\n", info3->group_rid)); return NT_STATUS_INVALID_PARAMETER; } j++; for (i = 0; i < info3->num_groups2; i++) { sid_copy(&all_sids[j], &(info3->dom_sid.sid)); if (!sid_append_rid(&all_sids[j], info3->gids[j].g_rid)) { DEBUG(3,("could not append additional group rid 0x%x\n", info3->gids[j].g_rid)); return NT_STATUS_INVALID_PARAMETER; } j++; } /* Copy 'other' sids. We need to do sid filtering here to prevent possible elevation of privileges. See: http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp */ for (i = 0; i < info3->num_other_sids; i++) { sid_copy(&all_sids[info3->num_groups2 + i + 2], &info3->other_sids[j].sid); j++; } for (i = 0; i < j; i++) { fstring sid1, sid2; DEBUG(10, ("User has SID: %s\n", sid_to_string(sid1, &all_sids[i]))); if (sid_equal(&required_membership_sid, &all_sids[i])) { DEBUG(10, ("SID %s matches %s - user permitted to authenticate!\n", sid_to_string(sid1, &required_membership_sid), sid_to_string(sid2, &all_sids[i]))); return NT_STATUS_OK; } } /* Do not distinguish this error from a wrong username/pw */ return NT_STATUS_LOGON_FAILURE; }
/* dump sam database via samsync rpc calls */ NTSTATUS rpc_vampire_internals(struct net_context *c, const DOM_SID *domain_sid, const char *domain_name, struct cli_state *cli, struct rpc_pipe_client *pipe_hnd, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS result; struct samsync_context *ctx = NULL; if (!sid_equal(domain_sid, get_global_sam_sid())) { d_printf("Cannot import users from %s at this time, " "as the current domain:\n\t%s: %s\nconflicts " "with the remote domain\n\t%s: %s\n" "Perhaps you need to set: \n\n\tsecurity=user\n\t" "workgroup=%s\n\n in your smb.conf?\n", domain_name, get_global_sam_name(), sid_string_dbg(get_global_sam_sid()), domain_name, sid_string_dbg(domain_sid), domain_name); return NT_STATUS_UNSUCCESSFUL; } result = libnet_samsync_init_context(mem_ctx, domain_sid, &ctx); if (!NT_STATUS_IS_OK(result)) { return result; } ctx->mode = NET_SAMSYNC_MODE_FETCH_PASSDB; ctx->cli = pipe_hnd; ctx->ops = &libnet_samsync_passdb_ops; ctx->domain_name = domain_name; ctx->force_full_replication = c->opt_force_full_repl ? true : false; ctx->clean_old_entries = c->opt_clean_old_entries ? true : false; parse_samsync_partial_replication_objects(ctx, argc, argv, &ctx->single_object_replication, &ctx->objects, &ctx->num_objects); /* fetch domain */ result = libnet_samsync(SAM_DATABASE_DOMAIN, ctx); if (!NT_STATUS_IS_OK(result) && ctx->error_message) { d_fprintf(stderr, "%s\n", ctx->error_message); goto fail; } if (ctx->result_message) { d_fprintf(stdout, "%s\n", ctx->result_message); } /* fetch builtin */ ctx->domain_sid = sid_dup_talloc(mem_ctx, &global_sid_Builtin); ctx->domain_sid_str = sid_string_talloc(mem_ctx, ctx->domain_sid); result = libnet_samsync(SAM_DATABASE_BUILTIN, ctx); if (!NT_STATUS_IS_OK(result) && ctx->error_message) { d_fprintf(stderr, "%s\n", ctx->error_message); goto fail; } if (ctx->result_message) { d_fprintf(stdout, "%s\n", ctx->result_message); } fail: TALLOC_FREE(ctx); return result; }
BOOL sid_check_is_domain(const DOM_SID *sid) { return sid_equal(sid, get_global_sam_sid()); }
static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx, struct NetLocalGroupAddMembers *add, struct NetLocalGroupDelMembers *del, struct NetLocalGroupSetMembers *set) { struct NetLocalGroupAddMembers *r = NULL; struct cli_state *cli = NULL; struct rpc_pipe_client *pipe_cli = NULL; struct rpc_pipe_client *lsa_pipe = NULL; NTSTATUS status; WERROR werr; struct lsa_String lsa_account_name; struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle; struct dom_sid2 *domain_sid = NULL; struct dom_sid *member_sids = NULL; int i = 0, k = 0; struct LOCALGROUP_MEMBERS_INFO_0 *info0 = NULL; struct LOCALGROUP_MEMBERS_INFO_3 *info3 = NULL; struct dom_sid *add_sids = NULL; struct dom_sid *del_sids = NULL; size_t num_add_sids = 0; size_t num_del_sids = 0; if ((!add && !del && !set) || (add && del && set)) { return WERR_INVALID_PARAM; } if (add) { r = add; } if (del) { r = (struct NetLocalGroupAddMembers *)del; } if (set) { r = (struct NetLocalGroupAddMembers *)set; } if (!r->in.group_name) { return WERR_INVALID_PARAM; } switch (r->in.level) { case 0: case 3: break; default: return WERR_UNKNOWN_LEVEL; } if (r->in.total_entries == 0 || !r->in.buffer) { return WERR_INVALID_PARAM; } ZERO_STRUCT(connect_handle); ZERO_STRUCT(builtin_handle); ZERO_STRUCT(domain_handle); ZERO_STRUCT(alias_handle); member_sids = TALLOC_ZERO_ARRAY(ctx, struct dom_sid, r->in.total_entries); W_ERROR_HAVE_NO_MEMORY(member_sids); switch (r->in.level) { case 0: info0 = (struct LOCALGROUP_MEMBERS_INFO_0 *)r->in.buffer; for (i=0; i < r->in.total_entries; i++) { sid_copy(&member_sids[i], (struct dom_sid *)info0[i].lgrmi0_sid); } break; case 3: info3 = (struct LOCALGROUP_MEMBERS_INFO_3 *)r->in.buffer; break; default: break; } if (r->in.level == 3) { werr = libnetapi_open_pipe(ctx, r->in.server_name, &ndr_table_lsarpc.syntax_id, &cli, &lsa_pipe); if (!W_ERROR_IS_OK(werr)) { goto done; } for (i=0; i < r->in.total_entries; i++) { status = libnetapi_lsa_lookup_names3(ctx, lsa_pipe, info3[i].lgrmi3_domainandname, &member_sids[i]); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } } TALLOC_FREE(lsa_pipe); } werr = libnetapi_open_pipe(ctx, r->in.server_name, &ndr_table_samr.syntax_id, &cli, &pipe_cli); if (!W_ERROR_IS_OK(werr)) { goto done; } werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli, SAMR_ACCESS_LOOKUP_DOMAIN | SAMR_ACCESS_ENUM_DOMAINS, SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, &connect_handle, &builtin_handle); if (!W_ERROR_IS_OK(werr)) { goto done; } init_lsa_String(&lsa_account_name, r->in.group_name); status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli, &builtin_handle, r->in.group_name, SAMR_ALIAS_ACCESS_ADD_MEMBER | SAMR_ALIAS_ACCESS_REMOVE_MEMBER | SAMR_ALIAS_ACCESS_GET_MEMBERS | SAMR_ALIAS_ACCESS_LOOKUP_INFO, &alias_handle); if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_builtin_handle(ctx, &builtin_handle); } if (NT_STATUS_IS_OK(status)) { goto modify_membership; } werr = libnetapi_samr_open_domain(ctx, pipe_cli, SAMR_ACCESS_ENUM_DOMAINS | SAMR_ACCESS_LOOKUP_DOMAIN, SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, &connect_handle, &domain_handle, &domain_sid); if (!W_ERROR_IS_OK(werr)) { goto done; } status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli, &domain_handle, r->in.group_name, SAMR_ALIAS_ACCESS_ADD_MEMBER | SAMR_ALIAS_ACCESS_REMOVE_MEMBER | SAMR_ALIAS_ACCESS_GET_MEMBERS | SAMR_ALIAS_ACCESS_LOOKUP_INFO, &alias_handle); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_domain_handle(ctx, &domain_handle); } modify_membership: if (add) { for (i=0; i < r->in.total_entries; i++) { status = add_sid_to_array_unique(ctx, &member_sids[i], &add_sids, &num_add_sids); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } } } if (del) { for (i=0; i < r->in.total_entries; i++) { status = add_sid_to_array_unique(ctx, &member_sids[i], &del_sids, &num_del_sids); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } } } if (set) { struct lsa_SidArray current_sids; status = rpccli_samr_GetMembersInAlias(pipe_cli, ctx, &alias_handle, ¤t_sids); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } /* add list */ for (i=0; i < r->in.total_entries; i++) { bool already_member = false; for (k=0; k < current_sids.num_sids; k++) { if (sid_equal(&member_sids[i], current_sids.sids[k].sid)) { already_member = true; break; } } if (!already_member) { status = add_sid_to_array_unique(ctx, &member_sids[i], &add_sids, &num_add_sids); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } } } /* del list */ for (k=0; k < current_sids.num_sids; k++) { bool keep_member = false; for (i=0; i < r->in.total_entries; i++) { if (sid_equal(&member_sids[i], current_sids.sids[k].sid)) { keep_member = true; break; } } if (!keep_member) { status = add_sid_to_array_unique(ctx, current_sids.sids[k].sid, &del_sids, &num_del_sids); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } } } } /* add list */ for (i=0; i < num_add_sids; i++) { status = rpccli_samr_AddAliasMember(pipe_cli, ctx, &alias_handle, &add_sids[i]); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } } /* del list */ for (i=0; i < num_del_sids; i++) { status = rpccli_samr_DeleteAliasMember(pipe_cli, ctx, &alias_handle, &del_sids[i]); if (!NT_STATUS_IS_OK(status)) { werr = ntstatus_to_werror(status); goto done; } } werr = WERR_OK; done: if (!cli) { return werr; } if (is_valid_policy_hnd(&alias_handle)) { rpccli_samr_Close(pipe_cli, ctx, &alias_handle); } if (ctx->disable_policy_handle_cache) { libnetapi_samr_close_domain_handle(ctx, &domain_handle); libnetapi_samr_close_builtin_handle(ctx, &builtin_handle); libnetapi_samr_close_connect_handle(ctx, &connect_handle); } return werr; }
static BOOL pdb_generate_sam_sid(void) { DOM_SID domain_sid; char *fname = NULL; BOOL is_dc = False; if(global_sam_sid==NULL) if(!(global_sam_sid=(DOM_SID *)malloc(sizeof(DOM_SID)))) return False; generate_wellknown_sids(); switch (lp_server_role()) { case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: is_dc = True; break; default: is_dc = False; break; } if (is_dc) { if (secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) { sid_copy(global_sam_sid, &domain_sid); return True; } } if (secrets_fetch_domain_sid(global_myname(), global_sam_sid)) { /* We got our sid. If not a pdc/bdc, we're done. */ if (!is_dc) return True; if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) { /* No domain sid and we're a pdc/bdc. Store it */ if (!secrets_store_domain_sid(lp_workgroup(), global_sam_sid)) { DEBUG(0,("pdb_generate_sam_sid: Can't store domain SID as a pdc/bdc.\n")); return False; } return True; } if (!sid_equal(&domain_sid, global_sam_sid)) { /* Domain name sid doesn't match global sam sid. Re-store domain sid as 'local' sid. */ DEBUG(0,("pdb_generate_sam_sid: Mismatched SIDs as a pdc/bdc.\n")); if (!secrets_store_domain_sid(global_myname(), &domain_sid)) { DEBUG(0,("pdb_generate_sam_sid: Can't re-store domain SID for local sid as PDC/BDC.\n")); return False; } return True; } return True; } /* check for an old MACHINE.SID file for backwards compatibility */ asprintf(&fname, "%s/MACHINE.SID", lp_private_dir()); if (read_sid_from_file(fname, global_sam_sid)) { /* remember it for future reference and unlink the old MACHINE.SID */ if (!secrets_store_domain_sid(global_myname(), global_sam_sid)) { DEBUG(0,("pdb_generate_sam_sid: Failed to store SID from file.\n")); SAFE_FREE(fname); return False; } unlink(fname); if (is_dc) { if (!secrets_store_domain_sid(lp_workgroup(), global_sam_sid)) { DEBUG(0,("pdb_generate_sam_sid: Failed to store domain SID from file.\n")); SAFE_FREE(fname); return False; } } /* Stored the old sid from MACHINE.SID successfully.*/ SAFE_FREE(fname); return True; } SAFE_FREE(fname); /* we don't have the SID in secrets.tdb, we will need to generate one and save it */ generate_random_sid(global_sam_sid); if (!secrets_store_domain_sid(global_myname(), global_sam_sid)) { DEBUG(0,("pdb_generate_sam_sid: Failed to store generated machine SID.\n")); return False; } if (is_dc) { if (!secrets_store_domain_sid(lp_workgroup(), global_sam_sid)) { DEBUG(0,("pdb_generate_sam_sid: Failed to store generated domain SID.\n")); return False; } } return True; }
bool sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2) { /* Trivial case */ if (!s1 && !s2) { goto done; } if (!s1 || !s2) { return False; } /* Check top level stuff */ if (s1->revision != s2->revision) { DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n", s1->revision, s2->revision)); return False; } if (s1->type!= s2->type) { DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n", s1->type, s2->type)); return False; } /* Check owner and group */ if (!sid_equal(s1->owner_sid, s2->owner_sid)) { DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n", sid_string_dbg(s1->owner_sid), sid_string_dbg(s2->owner_sid))); return False; } if (!sid_equal(s1->group_sid, s2->group_sid)) { DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n", sid_string_dbg(s1->group_sid), sid_string_dbg(s2->group_sid))); return False; } /* Check ACLs present in one but not the other */ if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) || (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) { DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n")); return False; } /* Sigh - we have to do it the hard way by iterating over all the ACEs in the ACLs */ if (!sec_acl_equal(s1->dacl, s2->dacl) || !sec_acl_equal(s1->sacl, s2->sacl)) { DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n")); return False; } done: DEBUG(10, ("sec_desc_equal(): secdescs are identical\n")); return True; }
/******************************************************************* gets a domain user's groups ********************************************************************/ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, uint32 **prids, DOM_SID *q_sid) { SAM_ACCOUNT *sam_pass=NULL; int i, cur_rid=0; gid_t gid; gid_t *groups = NULL; int num_groups; GROUP_MAP map; DOM_SID tmp_sid; fstring user_name; fstring str_domsid, str_qsid; uint32 rid,grid; uint32 *rids=NULL, *new_rids=NULL; gid_t winbind_gid_low, winbind_gid_high; BOOL ret; BOOL winbind_groups_exist; /* * this code is far from perfect. * first it enumerates the full /etc/group and that can be slow. * second, it works only with users' SIDs * whereas the day we support nested groups, it will have to * support both users's SIDs and domain groups' SIDs * * having our own ldap backend would be so much faster ! * we're far from that, but hope one day ;-) JFM. */ *prids=NULL; *numgroups=0; winbind_groups_exist = lp_idmap_gid(&winbind_gid_low, &winbind_gid_high); DEBUG(10,("get_alias_user_groups: looking if SID %s is a member of groups in the SID domain %s\n", sid_to_string(str_qsid, q_sid), sid_to_string(str_domsid, sid))); pdb_init_sam(&sam_pass); become_root(); ret = pdb_getsampwsid(sam_pass, q_sid); unbecome_root(); if (ret == False) { pdb_free_sam(&sam_pass); return NT_STATUS_NO_SUCH_USER; } fstrcpy(user_name, pdb_get_username(sam_pass)); grid=pdb_get_group_rid(sam_pass); if (!NT_STATUS_IS_OK(sid_to_gid(pdb_get_group_sid(sam_pass), &gid))) { /* this should never happen */ DEBUG(2,("get_alias_user_groups: sid_to_gid failed!\n")); pdb_free_sam(&sam_pass); return NT_STATUS_UNSUCCESSFUL; } become_root(); /* on some systems this must run as root */ num_groups = getgroups_user(user_name, &groups); unbecome_root(); if (num_groups == -1) { /* this should never happen */ DEBUG(2,("get_alias_user_groups: getgroups_user failed\n")); pdb_free_sam(&sam_pass); return NT_STATUS_UNSUCCESSFUL; } for (i=0;i<num_groups;i++) { if (!get_group_from_gid(groups[i], &map)) { DEBUG(10,("get_alias_user_groups: gid %d. not found\n", (int)groups[i])); continue; } /* if it's not an alias, continue */ if (map.sid_name_use != SID_NAME_ALIAS) { DEBUG(10,("get_alias_user_groups: not returing %s, not an ALIAS group.\n", map.nt_name)); continue; } sid_copy(&tmp_sid, &map.sid); sid_split_rid(&tmp_sid, &rid); /* if the sid is not in the correct domain, continue */ if (!sid_equal(&tmp_sid, sid)) { DEBUG(10,("get_alias_user_groups: not returing %s, not in the domain SID.\n", map.nt_name)); continue; } /* Don't return winbind groups as they are not local! */ if (winbind_groups_exist && (groups[i] >= winbind_gid_low) && (groups[i] <= winbind_gid_high)) { DEBUG(10,("get_alias_user_groups: not returing %s, not local.\n", map.nt_name)); continue; } /* Don't return user private groups... */ if (Get_Pwnam(map.nt_name) != 0) { DEBUG(10,("get_alias_user_groups: not returing %s, clashes with user.\n", map.nt_name)); continue; } new_rids=(uint32 *)Realloc(rids, sizeof(uint32)*(cur_rid+1)); if (new_rids==NULL) { DEBUG(10,("get_alias_user_groups: could not realloc memory\n")); pdb_free_sam(&sam_pass); free(groups); return NT_STATUS_NO_MEMORY; } rids=new_rids; sid_peek_rid(&map.sid, &(rids[cur_rid])); cur_rid++; break; } if(num_groups) free(groups); /* now check for the user's gid (the primary group rid) */ for (i=0; i<cur_rid && grid!=rids[i]; i++) ; /* the user's gid is already there */ if (i!=cur_rid) { DEBUG(10,("get_alias_user_groups: user is already in the list. good.\n")); goto done; } DEBUG(10,("get_alias_user_groups: looking for gid %d of user %s\n", (int)gid, user_name)); if(!get_group_from_gid(gid, &map)) { DEBUG(0,("get_alias_user_groups: gid of user %s doesn't exist. Check your " "/etc/passwd and /etc/group files\n", user_name)); goto done; } /* the primary group isn't an alias */ if (map.sid_name_use!=SID_NAME_ALIAS) { DEBUG(10,("get_alias_user_groups: not returing %s, not an ALIAS group.\n", map.nt_name)); goto done; } sid_copy(&tmp_sid, &map.sid); sid_split_rid(&tmp_sid, &rid); /* if the sid is not in the correct domain, continue */ if (!sid_equal(&tmp_sid, sid)) { DEBUG(10,("get_alias_user_groups: not returing %s, not in the domain SID.\n", map.nt_name)); goto done; } /* Don't return winbind groups as they are not local! */ if (winbind_groups_exist && (gid >= winbind_gid_low) && (gid <= winbind_gid_high)) { DEBUG(10,("get_alias_user_groups: not returing %s, not local.\n", map.nt_name )); goto done; } /* Don't return user private groups... */ if (Get_Pwnam(map.nt_name) != 0) { DEBUG(10,("get_alias_user_groups: not returing %s, clashes with user.\n", map.nt_name )); goto done; } new_rids=(uint32 *)Realloc(rids, sizeof(uint32)*(cur_rid+1)); if (new_rids==NULL) { DEBUG(10,("get_alias_user_groups: could not realloc memory\n")); pdb_free_sam(&sam_pass); return NT_STATUS_NO_MEMORY; } rids=new_rids; sid_peek_rid(&map.sid, &(rids[cur_rid])); cur_rid++; done: *prids=rids; *numgroups=cur_rid; pdb_free_sam(&sam_pass); return NT_STATUS_OK; }
bool is_null_sid(const DOM_SID *sid) { static const DOM_SID null_sid = {0}; return sid_equal(sid, &null_sid); }
static int change_share_sec(TALLOC_CTX *mem_ctx, const char *sharename, char *the_acl, enum acl_mode mode) { SEC_DESC *sd = NULL; SEC_DESC *old = NULL; size_t sd_size = 0; uint32 i, j; if (mode != SMB_ACL_SET) { if (!(old = get_share_security( mem_ctx, sharename, &sd_size )) ) { fprintf(stderr, "Unable to retrieve permissions for share [%s]\n", sharename); return -1; } } if ( (mode != SMB_ACL_VIEW) && !(sd = parse_acl_string(mem_ctx, the_acl, &sd_size )) ) { fprintf( stderr, "Failed to parse acl\n"); return -1; } switch (mode) { case SMB_ACL_VIEW: sec_desc_print( stdout, old); return 0; case SMB_ACL_DELETE: for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) { bool found = False; for (j=0;old->dacl && j<old->dacl->num_aces;j++) { if (sec_ace_equal(&sd->dacl->aces[i], &old->dacl->aces[j])) { uint32 k; for (k=j; k<old->dacl->num_aces-1;k++) { old->dacl->aces[k] = old->dacl->aces[k+1]; } old->dacl->num_aces--; found = True; break; } } if (!found) { printf("ACL for ACE:"); print_ace(stdout, &sd->dacl->aces[i]); printf(" not found\n"); } } break; case SMB_ACL_MODIFY: for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) { bool found = False; for (j=0;old->dacl && j<old->dacl->num_aces;j++) { if (sid_equal(&sd->dacl->aces[i].trustee, &old->dacl->aces[j].trustee)) { old->dacl->aces[j] = sd->dacl->aces[i]; found = True; } } if (!found) { printf("ACL for SID %s not found\n", sid_string_tos(&sd->dacl->aces[i].trustee)); } } if (sd->owner_sid) { old->owner_sid = sd->owner_sid; } if (sd->group_sid) { old->group_sid = sd->group_sid; } break; case SMB_ACL_ADD: for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) { add_ace(mem_ctx, &old->dacl, &sd->dacl->aces[i]); } break; case SMB_ACL_SET: old = sd; break; } /* Denied ACE entries must come before allowed ones */ sort_acl(old->dacl); if ( !set_share_security( sharename, old ) ) { fprintf( stderr, "Failed to store acl for share [%s]\n", sharename ); return 2; } return 0; }