diff options
Diffstat (limited to 'source4/auth/session.c')
-rw-r--r-- | source4/auth/session.c | 147 |
1 files changed, 142 insertions, 5 deletions
diff --git a/source4/auth/session.c b/source4/auth/session.c index 03d1c91054..7817195727 100644 --- a/source4/auth/session.c +++ b/source4/auth/session.c @@ -49,9 +49,71 @@ _PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, { struct auth_session_info *session_info; NTSTATUS nt_status; + unsigned int i, num_groupSIDs = 0; + const char *account_sid_string; + const char *account_sid_dn; + DATA_BLOB account_sid_blob; + const char *primary_group_string; + const char *primary_group_dn; + DATA_BLOB primary_group_blob; - session_info = talloc(mem_ctx, struct auth_session_info); - NT_STATUS_HAVE_NO_MEMORY(session_info); + const char *filter; + + struct dom_sid **groupSIDs = NULL; + const struct dom_sid *dom_sid; + bool is_enterprise_dc = false; + + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + + if (!auth_context->sam_ctx) { + DEBUG(0, ("No SAM available, cannot determine local groups\n")); + return NT_STATUS_INVALID_SYSTEM_SERVICE; + } + + /* For now, we don't have trusted domains, so we do a very + * simple check to see that the user's SID is in *this* + * domain, and then trust the user account control. When we + * get trusted domains, we should check it's a trusted domain + * in this forest. This elaborate check is to try and avoid a + * nasty security bug if we forget about this later... */ + + if (server_info->acct_flags & ACB_SVRTRUST) { + dom_sid = samdb_domain_sid(auth_context->sam_ctx); + if (dom_sid) { + if (dom_sid_in_domain(dom_sid, server_info->account_sid)) { + is_enterprise_dc = true; + } else { + DEBUG(2, ("DC %s is not in our domain. " + "It will not have Enterprise Domain Controllers membership on this server", + server_info->account_name)); + } + } else { + DEBUG(2, ("Could not obtain local domain SID, " + "so can not determine if DC %s is a DC of this domain. " + "It will not have Enterprise Domain Controllers membership", + server_info->account_name)); + } + } + + groupSIDs = talloc_array(tmp_ctx, struct dom_sid *, server_info->n_domain_groups); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(groupSIDs, tmp_ctx); + if (!groupSIDs) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + + num_groupSIDs = server_info->n_domain_groups; + + for (i=0; i < server_info->n_domain_groups; i++) { + groupSIDs[i] = server_info->domain_groups[i]; + } + + filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))", + GROUP_TYPE_BUILTIN_LOCAL_GROUP); + + session_info = talloc(tmp_ctx, struct auth_session_info); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(session_info, tmp_ctx); session_info->server_info = talloc_reference(session_info, server_info); @@ -59,19 +121,94 @@ _PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, * key from the auth subsystem */ session_info->session_key = server_info->user_session_key; + /* Search for each group in the token */ + + /* Expands the account SID - this function takes in + * memberOf-like values, so we fake one up with the + * <SID=S-...> format of DN and then let it expand + * them, as long as they meet the filter - so only + * builtin groups + * + * We already have the primary group in the token, so set + * 'only childs' flag to true + */ + account_sid_string = dom_sid_string(tmp_ctx, server_info->account_sid); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(account_sid_string, server_info); + + account_sid_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", account_sid_string); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(account_sid_dn, server_info); + + account_sid_blob = data_blob_string_const(account_sid_dn); + + nt_status = authsam_expand_nested_groups(auth_context->sam_ctx, &account_sid_blob, true, filter, + tmp_ctx, &groupSIDs, &num_groupSIDs); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(tmp_ctx); + return nt_status; + } + + /* Expands the primary group - this function takes in + * memberOf-like values, so we fake one up with the + * <SID=S-...> format of DN and then let it expand + * them, as long as they meet the filter - so only + * builtin groups + * + * We already have the primary group in the token, so set + * 'only childs' flag to true + */ + primary_group_string = dom_sid_string(tmp_ctx, server_info->primary_group_sid); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(primary_group_string, server_info); + + primary_group_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", primary_group_string); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(primary_group_dn, server_info); + + primary_group_blob = data_blob_string_const(primary_group_dn); + + nt_status = authsam_expand_nested_groups(auth_context->sam_ctx, &primary_group_blob, true, filter, + tmp_ctx, &groupSIDs, &num_groupSIDs); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(tmp_ctx); + return nt_status; + } + + for (i = 0; i < server_info->n_domain_groups; i++) { + const char *group_string; + const char *group_dn; + DATA_BLOB group_blob; + group_string = dom_sid_string(tmp_ctx, server_info->domain_groups[i]); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(group_string, server_info); + + group_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", group_string); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(group_dn, server_info); + + group_blob = data_blob_string_const(group_dn); + + /* This function takes in memberOf values and expands + * them, as long as they meet the filter - so only + * builtin groups */ + nt_status = authsam_expand_nested_groups(auth_context->sam_ctx, &group_blob, true, filter, + tmp_ctx, &groupSIDs, &num_groupSIDs); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(tmp_ctx); + return nt_status; + } + } + nt_status = security_token_create(session_info, auth_context->event_ctx, auth_context->lp_ctx, server_info->account_sid, server_info->primary_group_sid, - server_info->n_domain_groups, - server_info->domain_groups, + num_groupSIDs, + groupSIDs, server_info->authenticated, + is_enterprise_dc, &session_info->security_token); - NT_STATUS_NOT_OK_RETURN(nt_status); + 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; return NT_STATUS_OK; } |