1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00
samba-mirror/source4/auth/system_session.c
Joseph Sutton 1c3a8fa20c auth: Correct primary group handling
Heretofore we have treated the primary group SID specially, storing it
in a fixed position as the second element of the user_info_dc->sids
array, and filtering out other copies in the PAC_LOGON_INFO base
structure. This filtering has made it difficult to distinguish between
the case where the primary group is a universal or global group, located
in the base RIDs, and the case where it is a domain-local group, missing
from the base RIDs; especially since the attributes of a domain-local
primary group are lost by being stored in the PAC. Domain-local primary
groups are normally disallowed by Windows, but are allowed by Samba, and
so it is reasonable to support them with at least some measure of
consistency.

The second element of user_info_dc->sids is still reserved for the
primary group's SID, but we no longer filter out any other copies in the
array. The first two elements are no more than the SIDs of the user and
the primary group respectively; and the remaining SIDs are as if taken
without modification from arrays of SIDs in the PAC. user_info_dc->sids
should therefore become a more faithful representation of the SIDs in
the PAC. After adding resource SIDs to it with
dsdb_expand_resource_groups(), we should have a result that more closely
and in more cases matches that of Windows.

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2023-02-08 00:03:40 +00:00

450 lines
14 KiB
C

/*
Unix SMB/CIFS implementation.
Authentication utility functions
Copyright (C) Andrew Tridgell 1992-1998
Copyright (C) Andrew Bartlett 2001-2010
Copyright (C) Jeremy Allison 2000-2001
Copyright (C) Rafal Szczesniak 2002
Copyright (C) Stefan Metzmacher 2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "libcli/security/security.h"
#include "auth/credentials/credentials.h"
#include "param/param.h"
#include "auth/auth.h" /* for auth_user_info_dc */
#include "auth/session.h"
#include "auth/system_session_proto.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_AUTH
/*
prevent the static system session being freed
*/
static int system_session_destructor(struct auth_session_info *info)
{
return -1;
}
/* Create a security token for a session SYSTEM (the most
* trusted/privileged account), including the local machine account as
* the off-host credentials
*/
_PUBLIC_ struct auth_session_info *system_session(struct loadparm_context *lp_ctx)
{
static struct auth_session_info *static_session;
NTSTATUS nt_status;
if (static_session) {
return static_session;
}
/*
* Use NULL here, not the autofree context for this
* static pointer. The destructor prevents freeing this
* memory anyway.
*/
nt_status = auth_system_session_info(NULL,
lp_ctx,
&static_session);
if (!NT_STATUS_IS_OK(nt_status)) {
TALLOC_FREE(static_session);
return NULL;
}
talloc_set_destructor(static_session, system_session_destructor);
return static_session;
}
NTSTATUS auth_system_session_info(TALLOC_CTX *parent_ctx,
struct loadparm_context *lp_ctx,
struct auth_session_info **_session_info)
{
NTSTATUS nt_status;
struct auth_user_info_dc *user_info_dc = NULL;
struct auth_session_info *session_info = NULL;
TALLOC_CTX *mem_ctx = NULL;
bool ok;
mem_ctx = talloc_new(parent_ctx);
if (mem_ctx == NULL) {
return NT_STATUS_NO_MEMORY;
}
nt_status = auth_system_user_info_dc(mem_ctx, lpcfg_netbios_name(lp_ctx),
&user_info_dc);
if (!NT_STATUS_IS_OK(nt_status)) {
talloc_free(mem_ctx);
return nt_status;
}
/* references the user_info_dc into the session_info */
nt_status = auth_generate_session_info(parent_ctx, NULL, NULL, user_info_dc, AUTH_SESSION_INFO_SIMPLE_PRIVILEGES, &session_info);
talloc_free(mem_ctx);
NT_STATUS_NOT_OK_RETURN(nt_status);
session_info->credentials = cli_credentials_init(session_info);
if (!session_info->credentials) {
return NT_STATUS_NO_MEMORY;
}
ok = cli_credentials_set_conf(session_info->credentials, lp_ctx);
if (!ok) {
return NT_STATUS_INTERNAL_ERROR;
}
cli_credentials_set_machine_account_pending(session_info->credentials, lp_ctx);
*_session_info = session_info;
return NT_STATUS_OK;
}
NTSTATUS auth_system_user_info_dc(TALLOC_CTX *mem_ctx, const char *netbios_name,
struct auth_user_info_dc **_user_info_dc)
{
struct auth_user_info_dc *user_info_dc;
struct auth_user_info *info;
user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc);
NT_STATUS_HAVE_NO_MEMORY(user_info_dc);
/* This returns a pointer to a struct dom_sid, which is the
* same as a 1 element list of struct dom_sid */
user_info_dc->num_sids = 1;
user_info_dc->sids = talloc(user_info_dc, struct auth_SidAttr);
NT_STATUS_HAVE_NO_MEMORY(user_info_dc->sids);
user_info_dc->sids->sid = global_sid_System;
user_info_dc->sids->attrs = SE_GROUP_DEFAULT_FLAGS;
/* annoying, but the Anonymous really does have a session key,
and it is all zeros! */
user_info_dc->user_session_key = data_blob_talloc(user_info_dc, NULL, 16);
NT_STATUS_HAVE_NO_MEMORY(user_info_dc->user_session_key.data);
user_info_dc->lm_session_key = data_blob_talloc(user_info_dc, NULL, 16);
NT_STATUS_HAVE_NO_MEMORY(user_info_dc->lm_session_key.data);
data_blob_clear(&user_info_dc->user_session_key);
data_blob_clear(&user_info_dc->lm_session_key);
user_info_dc->info = info = talloc_zero(user_info_dc, struct auth_user_info);
NT_STATUS_HAVE_NO_MEMORY(user_info_dc->info);
info->account_name = talloc_strdup(info, "SYSTEM");
NT_STATUS_HAVE_NO_MEMORY(info->account_name);
info->domain_name = talloc_strdup(info, "NT AUTHORITY");
NT_STATUS_HAVE_NO_MEMORY(info->domain_name);
info->full_name = talloc_strdup(info, "System");
NT_STATUS_HAVE_NO_MEMORY(info->full_name);
info->logon_script = talloc_strdup(info, "");
NT_STATUS_HAVE_NO_MEMORY(info->logon_script);
info->profile_path = talloc_strdup(info, "");
NT_STATUS_HAVE_NO_MEMORY(info->profile_path);
info->home_directory = talloc_strdup(info, "");
NT_STATUS_HAVE_NO_MEMORY(info->home_directory);
info->home_drive = talloc_strdup(info, "");
NT_STATUS_HAVE_NO_MEMORY(info->home_drive);
info->logon_server = talloc_strdup(info, netbios_name);
NT_STATUS_HAVE_NO_MEMORY(info->logon_server);
info->last_logon = 0;
info->last_logoff = 0;
info->acct_expiry = 0;
info->last_password_change = 0;
info->allow_password_change = 0;
info->force_password_change = 0;
info->logon_count = 0;
info->bad_password_count = 0;
info->acct_flags = ACB_NORMAL;
info->user_flags = 0;
*_user_info_dc = user_info_dc;
return NT_STATUS_OK;
}
static NTSTATUS auth_domain_admin_user_info_dc(TALLOC_CTX *mem_ctx,
const char *netbios_name,
const char *domain_name,
struct dom_sid *domain_sid,
struct auth_user_info_dc **_user_info_dc)
{
struct auth_user_info_dc *user_info_dc;
struct auth_user_info *info;
user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc);
NT_STATUS_HAVE_NO_MEMORY(user_info_dc);
user_info_dc->num_sids = 8;
user_info_dc->sids = talloc_array(user_info_dc, struct auth_SidAttr, user_info_dc->num_sids);
user_info_dc->sids[PRIMARY_USER_SID_INDEX].sid = *domain_sid;
sid_append_rid(&user_info_dc->sids[PRIMARY_USER_SID_INDEX].sid, DOMAIN_RID_ADMINISTRATOR);
user_info_dc->sids[PRIMARY_USER_SID_INDEX].attrs = SE_GROUP_DEFAULT_FLAGS;
user_info_dc->sids[PRIMARY_GROUP_SID_INDEX].sid = *domain_sid;
sid_append_rid(&user_info_dc->sids[PRIMARY_GROUP_SID_INDEX].sid, DOMAIN_RID_USERS);
user_info_dc->sids[PRIMARY_GROUP_SID_INDEX].attrs = SE_GROUP_DEFAULT_FLAGS;
/* Add the primary group again. */
user_info_dc->sids[2] = user_info_dc->sids[PRIMARY_GROUP_SID_INDEX];
user_info_dc->sids[3].sid = global_sid_Builtin_Administrators;
user_info_dc->sids[3].attrs = SE_GROUP_DEFAULT_FLAGS;
user_info_dc->sids[4].sid = *domain_sid;
sid_append_rid(&user_info_dc->sids[4].sid, DOMAIN_RID_ADMINS);
user_info_dc->sids[4].attrs = SE_GROUP_DEFAULT_FLAGS;
user_info_dc->sids[5].sid = *domain_sid;
sid_append_rid(&user_info_dc->sids[5].sid, DOMAIN_RID_ENTERPRISE_ADMINS);
user_info_dc->sids[5].attrs = SE_GROUP_DEFAULT_FLAGS;
user_info_dc->sids[6].sid = *domain_sid;
sid_append_rid(&user_info_dc->sids[6].sid, DOMAIN_RID_POLICY_ADMINS);
user_info_dc->sids[6].attrs = SE_GROUP_DEFAULT_FLAGS;
user_info_dc->sids[7].sid = *domain_sid;
sid_append_rid(&user_info_dc->sids[7].sid, DOMAIN_RID_SCHEMA_ADMINS);
user_info_dc->sids[7].attrs = SE_GROUP_DEFAULT_FLAGS;
/* What should the session key be?*/
user_info_dc->user_session_key = data_blob_talloc(user_info_dc, NULL, 16);
NT_STATUS_HAVE_NO_MEMORY(user_info_dc->user_session_key.data);
user_info_dc->lm_session_key = data_blob_talloc(user_info_dc, NULL, 16);
NT_STATUS_HAVE_NO_MEMORY(user_info_dc->lm_session_key.data);
data_blob_clear(&user_info_dc->user_session_key);
data_blob_clear(&user_info_dc->lm_session_key);
user_info_dc->info = info = talloc_zero(user_info_dc, struct auth_user_info);
NT_STATUS_HAVE_NO_MEMORY(user_info_dc->info);
info->account_name = talloc_strdup(info, "Administrator");
NT_STATUS_HAVE_NO_MEMORY(info->account_name);
info->domain_name = talloc_strdup(info, domain_name);
NT_STATUS_HAVE_NO_MEMORY(info->domain_name);
info->full_name = talloc_strdup(info, "Administrator");
NT_STATUS_HAVE_NO_MEMORY(info->full_name);
info->logon_script = talloc_strdup(info, "");
NT_STATUS_HAVE_NO_MEMORY(info->logon_script);
info->profile_path = talloc_strdup(info, "");
NT_STATUS_HAVE_NO_MEMORY(info->profile_path);
info->home_directory = talloc_strdup(info, "");
NT_STATUS_HAVE_NO_MEMORY(info->home_directory);
info->home_drive = talloc_strdup(info, "");
NT_STATUS_HAVE_NO_MEMORY(info->home_drive);
info->logon_server = talloc_strdup(info, netbios_name);
NT_STATUS_HAVE_NO_MEMORY(info->logon_server);
info->last_logon = 0;
info->last_logoff = 0;
info->acct_expiry = 0;
info->last_password_change = 0;
info->allow_password_change = 0;
info->force_password_change = 0;
info->logon_count = 0;
info->bad_password_count = 0;
info->acct_flags = ACB_NORMAL;
info->user_flags = 0;
*_user_info_dc = user_info_dc;
return NT_STATUS_OK;
}
static NTSTATUS auth_domain_admin_session_info(TALLOC_CTX *parent_ctx,
struct loadparm_context *lp_ctx,
struct dom_sid *domain_sid,
struct auth_session_info **session_info)
{
NTSTATUS nt_status;
struct auth_user_info_dc *user_info_dc = NULL;
TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
nt_status = auth_domain_admin_user_info_dc(mem_ctx, lpcfg_netbios_name(lp_ctx),
lpcfg_workgroup(lp_ctx), domain_sid,
&user_info_dc);
if (!NT_STATUS_IS_OK(nt_status)) {
talloc_free(mem_ctx);
return nt_status;
}
nt_status = auth_generate_session_info(mem_ctx, NULL, NULL, user_info_dc,
AUTH_SESSION_INFO_SIMPLE_PRIVILEGES|AUTH_SESSION_INFO_AUTHENTICATED|AUTH_SESSION_INFO_DEFAULT_GROUPS,
session_info);
/* There is already a reference between the sesion_info and user_info_dc */
if (NT_STATUS_IS_OK(nt_status)) {
talloc_steal(parent_ctx, *session_info);
}
talloc_free(mem_ctx);
return nt_status;
}
_PUBLIC_ struct auth_session_info *admin_session(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, struct dom_sid *domain_sid)
{
NTSTATUS nt_status;
struct auth_session_info *session_info = NULL;
nt_status = auth_domain_admin_session_info(mem_ctx,
lp_ctx,
domain_sid,
&session_info);
if (!NT_STATUS_IS_OK(nt_status)) {
return NULL;
}
return session_info;
}
_PUBLIC_ NTSTATUS auth_anonymous_session_info(TALLOC_CTX *parent_ctx,
struct loadparm_context *lp_ctx,
struct auth_session_info **_session_info)
{
NTSTATUS nt_status;
struct auth_user_info_dc *user_info_dc = NULL;
struct auth_session_info *session_info = NULL;
TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
bool ok;
nt_status = auth_anonymous_user_info_dc(mem_ctx,
lpcfg_netbios_name(lp_ctx),
&user_info_dc);
if (!NT_STATUS_IS_OK(nt_status)) {
talloc_free(mem_ctx);
return nt_status;
}
/* references the user_info_dc into the session_info */
nt_status = auth_generate_session_info(parent_ctx, NULL, NULL, user_info_dc, AUTH_SESSION_INFO_SIMPLE_PRIVILEGES, &session_info);
talloc_free(mem_ctx);
NT_STATUS_NOT_OK_RETURN(nt_status);
session_info->credentials = cli_credentials_init(session_info);
if (!session_info->credentials) {
return NT_STATUS_NO_MEMORY;
}
ok = cli_credentials_set_conf(session_info->credentials, lp_ctx);
if (!ok) {
return NT_STATUS_INTERNAL_ERROR;
}
cli_credentials_set_anonymous(session_info->credentials);
*_session_info = session_info;
return NT_STATUS_OK;
}
_PUBLIC_ NTSTATUS auth_anonymous_user_info_dc(TALLOC_CTX *mem_ctx,
const char *netbios_name,
struct auth_user_info_dc **_user_info_dc)
{
struct auth_user_info_dc *user_info_dc;
struct auth_user_info *info;
user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc);
NT_STATUS_HAVE_NO_MEMORY(user_info_dc);
/* This returns a pointer to a struct dom_sid, which is the
* same as a 1 element list of struct dom_sid */
user_info_dc->num_sids = 1;
user_info_dc->sids = talloc(user_info_dc, struct auth_SidAttr);
NT_STATUS_HAVE_NO_MEMORY(user_info_dc->sids);
user_info_dc->sids->sid = global_sid_Anonymous;
user_info_dc->sids->attrs = SE_GROUP_DEFAULT_FLAGS;
/* annoying, but the Anonymous really does have a session key... */
user_info_dc->user_session_key = data_blob_talloc(user_info_dc, NULL, 16);
NT_STATUS_HAVE_NO_MEMORY(user_info_dc->user_session_key.data);
user_info_dc->lm_session_key = data_blob_talloc(user_info_dc, NULL, 16);
NT_STATUS_HAVE_NO_MEMORY(user_info_dc->lm_session_key.data);
/* and it is all zeros! */
data_blob_clear(&user_info_dc->user_session_key);
data_blob_clear(&user_info_dc->lm_session_key);
user_info_dc->info = info = talloc_zero(user_info_dc, struct auth_user_info);
NT_STATUS_HAVE_NO_MEMORY(user_info_dc->info);
info->account_name = talloc_strdup(info, "ANONYMOUS LOGON");
NT_STATUS_HAVE_NO_MEMORY(info->account_name);
info->domain_name = talloc_strdup(info, "NT AUTHORITY");
NT_STATUS_HAVE_NO_MEMORY(info->domain_name);
info->full_name = talloc_strdup(info, "Anonymous Logon");
NT_STATUS_HAVE_NO_MEMORY(info->full_name);
info->logon_script = talloc_strdup(info, "");
NT_STATUS_HAVE_NO_MEMORY(info->logon_script);
info->profile_path = talloc_strdup(info, "");
NT_STATUS_HAVE_NO_MEMORY(info->profile_path);
info->home_directory = talloc_strdup(info, "");
NT_STATUS_HAVE_NO_MEMORY(info->home_directory);
info->home_drive = talloc_strdup(info, "");
NT_STATUS_HAVE_NO_MEMORY(info->home_drive);
info->logon_server = talloc_strdup(info, netbios_name);
NT_STATUS_HAVE_NO_MEMORY(info->logon_server);
info->last_logon = 0;
info->last_logoff = 0;
info->acct_expiry = 0;
info->last_password_change = 0;
info->allow_password_change = 0;
info->force_password_change = 0;
info->logon_count = 0;
info->bad_password_count = 0;
info->acct_flags = ACB_NORMAL;
/* The user is not authenticated. */
info->user_flags = NETLOGON_GUEST;
*_user_info_dc = user_info_dc;
return NT_STATUS_OK;
}