static NTSTATUS check_samba4_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **server_info) { TALLOC_CTX *frame = talloc_stackframe(); struct netr_SamInfo3 *info3 = NULL; NTSTATUS nt_status; struct auth_user_info_dc *user_info_dc; struct auth4_context *auth4_context; struct loadparm_context *lp_ctx; lp_ctx = loadparm_init_s3(frame, loadparm_s3_context()); if (lp_ctx == NULL) { DEBUG(10, ("loadparm_init_s3 failed\n")); talloc_free(frame); return NT_STATUS_INVALID_SERVER_STATE; } /* We create a private tevent context here to avoid nested loops in * the s3 one, as that may not be expected */ nt_status = auth_context_create(mem_ctx, s4_event_context_init(frame), NULL, lp_ctx, &auth4_context); NT_STATUS_NOT_OK_RETURN(nt_status); nt_status = auth_context_set_challenge(auth4_context, auth_context->challenge.data, "auth_samba4"); NT_STATUS_NOT_OK_RETURN_AND_FREE(nt_status, auth4_context); nt_status = auth_check_password(auth4_context, auth4_context, user_info, &user_info_dc); NT_STATUS_NOT_OK_RETURN_AND_FREE(nt_status, auth4_context); nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx, user_info_dc, &info3); if (NT_STATUS_IS_OK(nt_status)) { /* We need the strings from the server_info to be valid as long as the info3 is around */ talloc_steal(info3, user_info_dc); } talloc_free(auth4_context); if (!NT_STATUS_IS_OK(nt_status)) { goto done; } nt_status = make_server_info_info3(mem_ctx, user_info->client.account_name, user_info->mapped.domain_name, server_info, info3); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(10, ("make_server_info_info3 failed: %s\n", nt_errstr(nt_status))); TALLOC_FREE(frame); return nt_status; } nt_status = NT_STATUS_OK; done: TALLOC_FREE(frame); return nt_status; }
_PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, /* Optional, if you don't want privilages */ struct ldb_context *sam_ctx, /* Optional, if you don't want local groups */ struct auth_user_info_dc *user_info_dc, uint32_t session_info_flags, struct auth_session_info **_session_info) { struct auth_session_info *session_info; NTSTATUS nt_status; unsigned int i, num_sids = 0; const char *filter; struct dom_sid *sids = NULL; const struct dom_sid *anonymous_sid, *system_sid; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); session_info = talloc_zero(tmp_ctx, struct auth_session_info); NT_STATUS_HAVE_NO_MEMORY_AND_FREE(session_info, tmp_ctx); session_info->info = talloc_reference(session_info, user_info_dc->info); session_info->torture = talloc_zero(session_info, struct auth_user_info_torture); NT_STATUS_HAVE_NO_MEMORY_AND_FREE(session_info->torture, tmp_ctx); session_info->torture->num_dc_sids = user_info_dc->num_sids; session_info->torture->dc_sids = talloc_reference(session_info, user_info_dc->sids); NT_STATUS_HAVE_NO_MEMORY_AND_FREE(session_info->torture->dc_sids, tmp_ctx); /* unless set otherwise, the session key is the user session * key from the auth subsystem */ session_info->session_key = data_blob_talloc(session_info, user_info_dc->user_session_key.data, user_info_dc->user_session_key.length); if (!session_info->session_key.data && session_info->session_key.length) { NT_STATUS_HAVE_NO_MEMORY_AND_FREE(session_info->session_key.data, tmp_ctx); } anonymous_sid = dom_sid_parse_talloc(tmp_ctx, SID_NT_ANONYMOUS); NT_STATUS_HAVE_NO_MEMORY_AND_FREE(anonymous_sid, tmp_ctx); system_sid = dom_sid_parse_talloc(tmp_ctx, SID_NT_SYSTEM); NT_STATUS_HAVE_NO_MEMORY_AND_FREE(system_sid, tmp_ctx); sids = talloc_array(tmp_ctx, struct dom_sid, user_info_dc->num_sids); NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sids, tmp_ctx); if (!sids) { talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } num_sids = user_info_dc->num_sids; for (i=0; i < user_info_dc->num_sids; i++) { sids[i] = user_info_dc->sids[i]; } if (user_info_dc->num_sids > PRIMARY_USER_SID_INDEX && dom_sid_equal(anonymous_sid, &user_info_dc->sids[PRIMARY_USER_SID_INDEX])) { /* Don't expand nested groups of system, anonymous etc*/ } else if (user_info_dc->num_sids > PRIMARY_USER_SID_INDEX && dom_sid_equal(system_sid, &user_info_dc->sids[PRIMARY_USER_SID_INDEX])) { /* Don't expand nested groups of system, anonymous etc*/ } else if (sam_ctx) { filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))", GROUP_TYPE_BUILTIN_LOCAL_GROUP); /* Search for each group in the token */ for (i = 0; i < user_info_dc->num_sids; i++) { char *sid_string; const char *sid_dn; DATA_BLOB sid_blob; sid_string = dom_sid_string(tmp_ctx, &user_info_dc->sids[i]); NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sid_string, user_info_dc); sid_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", sid_string); talloc_free(sid_string); NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sid_dn, user_info_dc); sid_blob = data_blob_string_const(sid_dn); /* This function takes in memberOf values and expands * them, as long as they meet the filter - so only * builtin groups * * We already have the SID in the token, so set * 'only childs' flag to true */ nt_status = dsdb_expand_nested_groups(sam_ctx, &sid_blob, true, filter, tmp_ctx, &sids, &num_sids); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(tmp_ctx); return nt_status; } } } nt_status = security_token_create(session_info, lp_ctx, num_sids, sids, session_info_flags, &session_info->security_token); NT_STATUS_NOT_OK_RETURN_AND_FREE(nt_status, tmp_ctx); session_info->credentials = NULL; talloc_steal(mem_ctx, session_info); *_session_info = session_info; talloc_free(tmp_ctx); return NT_STATUS_OK; }