static bool token_contains_name(TALLOC_CTX *mem_ctx, const char *username, const char *domain, const char *sharename, const struct nt_user_token *token, const char *name) { const char *prefix; DOM_SID sid; enum lsa_SidType type; struct smbd_server_connection *sconn = smbd_server_conn; if (username != NULL) { name = talloc_sub_basic(mem_ctx, username, domain, name); } if (sharename != NULL) { name = talloc_string_sub(mem_ctx, name, "%S", sharename); } if (name == NULL) { /* This is too security sensitive, better panic than return a * result that might be interpreted in a wrong way. */ smb_panic("substitutions failed"); } /* check to see is we already have a SID */ if ( string_to_sid( &sid, name ) ) { DEBUG(5,("token_contains_name: Checking for SID [%s] in token\n", name)); return nt_token_check_sid( &sid, token ); } if (!do_group_checks(&name, &prefix)) { if (!lookup_name_smbconf(mem_ctx, name, LOOKUP_NAME_ALL, NULL, NULL, &sid, &type)) { DEBUG(5, ("lookup_name %s failed\n", name)); return False; } if (type != SID_NAME_USER) { DEBUG(5, ("%s is a %s, expected a user\n", name, sid_type_lookup(type))); return False; } return nt_token_check_sid(&sid, token); } for (/* initialized above */ ; *prefix != '\0'; prefix++) { if (*prefix == '+') { if (!lookup_name_smbconf(mem_ctx, name, LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP, NULL, NULL, &sid, &type)) { DEBUG(5, ("lookup_name %s failed\n", name)); return False; } if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) && (type != SID_NAME_WKN_GRP)) { DEBUG(5, ("%s is a %s, expected a group\n", name, sid_type_lookup(type))); return False; } if (nt_token_check_sid(&sid, token)) { return True; } continue; } if (*prefix == '&') { if (username) { if (user_in_netgroup(sconn, username, name)) { return True; } } continue; } smb_panic("got invalid prefix from do_groups_check"); } return False; }
static NTSTATUS find_forced_group(bool force_user, int snum, const char *username, DOM_SID *pgroup_sid, gid_t *pgid) { NTSTATUS result = NT_STATUS_NO_SUCH_GROUP; TALLOC_CTX *frame = talloc_stackframe(); DOM_SID group_sid; enum lsa_SidType type; char *groupname; bool user_must_be_member = False; gid_t gid; groupname = talloc_strdup(talloc_tos(), lp_force_group(snum)); if (groupname == NULL) { DEBUG(1, ("talloc_strdup failed\n")); result = NT_STATUS_NO_MEMORY; goto done; } if (groupname[0] == '+') { user_must_be_member = True; groupname += 1; } groupname = talloc_string_sub(talloc_tos(), groupname, "%S", lp_servicename(snum)); if (groupname == NULL) { DEBUG(1, ("talloc_string_sub failed\n")); result = NT_STATUS_NO_MEMORY; goto done; } if (!lookup_name_smbconf(talloc_tos(), groupname, LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP, NULL, NULL, &group_sid, &type)) { DEBUG(10, ("lookup_name_smbconf(%s) failed\n", groupname)); goto done; } if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) && (type != SID_NAME_WKN_GRP)) { DEBUG(10, ("%s is a %s, not a group\n", groupname, sid_type_lookup(type))); goto done; } if (!sid_to_gid(&group_sid, &gid)) { DEBUG(10, ("sid_to_gid(%s) for %s failed\n", sid_string_dbg(&group_sid), groupname)); goto done; } /* * If the user has been forced and the forced group starts with a '+', * then we only set the group to be the forced group if the forced * user is a member of that group. Otherwise, the meaning of the '+' * would be ignored. */ if (force_user && user_must_be_member) { if (user_in_group_sid(username, &group_sid)) { sid_copy(pgroup_sid, &group_sid); *pgid = gid; DEBUG(3,("Forced group %s for member %s\n", groupname, username)); } else { DEBUG(0,("find_forced_group: forced user %s is not a member " "of forced group %s. Disallowing access.\n", username, groupname )); result = NT_STATUS_MEMBER_NOT_IN_GROUP; goto done; } } else { sid_copy(pgroup_sid, &group_sid); *pgid = gid; DEBUG(3,("Forced group %s\n", groupname)); } result = NT_STATUS_OK; done: TALLOC_FREE(frame); return result; }
NTSTATUS passwd_to_SamInfo3(TALLOC_CTX *mem_ctx, const char *unix_username, const struct passwd *pwd, struct netr_SamInfo3 **pinfo3, struct extra_auth_info *extra) { struct netr_SamInfo3 *info3; NTSTATUS status; TALLOC_CTX *tmp_ctx; const char *domain_name = NULL; const char *user_name = NULL; struct dom_sid domain_sid; struct dom_sid user_sid; struct dom_sid group_sid; enum lsa_SidType type; uint32_t num_sids = 0; struct dom_sid *user_sids = NULL; bool is_null; bool ok; tmp_ctx = talloc_stackframe(); ok = lookup_name_smbconf(tmp_ctx, unix_username, LOOKUP_NAME_ALL, &domain_name, &user_name, &user_sid, &type); if (!ok) { status = NT_STATUS_NO_SUCH_USER; goto done; } if (type != SID_NAME_USER) { status = NT_STATUS_NO_SUCH_USER; goto done; } ok = winbind_lookup_usersids(tmp_ctx, &user_sid, &num_sids, &user_sids); /* Check if winbind is running */ if (ok) { /* * Winbind is running and the first element of the user_sids * is the primary group. */ if (num_sids > 0) { group_sid = user_sids[0]; } } else { /* * Winbind is not running, try to create the group_sid from the * passwd group id. */ /* * This can lead to a primary group of S-1-22-2-XX which * will be rejected by other Samba code. */ gid_to_sid(&group_sid, pwd->pw_gid); } /* * If we are a unix group, or a wellknown/builtin alias, * set the group_sid to the * 'Domain Users' RID of 513 which will always resolve to a * name. */ if (sid_check_is_in_unix_groups(&group_sid) || sid_check_is_in_builtin(&group_sid) || sid_check_is_in_wellknown_domain(&group_sid)) { if (sid_check_is_in_unix_users(&user_sid)) { sid_compose(&group_sid, get_global_sam_sid(), DOMAIN_RID_USERS); } else { sid_copy(&domain_sid, &user_sid); sid_split_rid(&domain_sid, NULL); sid_compose(&group_sid, &domain_sid, DOMAIN_RID_USERS); } } /* Make sure we have a valid group sid */ is_null = is_null_sid(&group_sid); if (is_null) { status = NT_STATUS_NO_SUCH_USER; goto done; } /* Construct a netr_SamInfo3 from the information we have */ info3 = talloc_zero(tmp_ctx, struct netr_SamInfo3); if (!info3) { status = NT_STATUS_NO_MEMORY; goto done; } info3->base.account_name.string = talloc_strdup(info3, unix_username); if (info3->base.account_name.string == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } ZERO_STRUCT(domain_sid); status = SamInfo3_handle_sids(unix_username, &user_sid, &group_sid, info3, &domain_sid, extra); if (!NT_STATUS_IS_OK(status)) { goto done; } info3->base.domain_sid = dom_sid_dup(info3, &domain_sid); if (info3->base.domain_sid == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } ok = sid_peek_check_rid(&domain_sid, &group_sid, &info3->base.primary_gid); if (!ok) { DEBUG(1, ("The primary group domain sid(%s) does not " "match the domain sid(%s) for %s(%s)\n", sid_string_dbg(&group_sid), sid_string_dbg(&domain_sid), unix_username, sid_string_dbg(&user_sid))); status = NT_STATUS_INVALID_SID; goto done; } info3->base.acct_flags = ACB_NORMAL; if (num_sids) { status = group_sids_to_info3(info3, user_sids, num_sids); if (!NT_STATUS_IS_OK(status)) { goto done; } } *pinfo3 = talloc_steal(mem_ctx, info3); status = NT_STATUS_OK; done: talloc_free(tmp_ctx); return status; }