1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-20 14:03:59 +03:00

CVE-2020-25717: Add FreeIPA domain controller role

As we want to reduce use of 'classic domain controller' role but FreeIPA
relies on it internally, add a separate role to mark FreeIPA domain
controller role.

It means that role won't result in ROLE_STANDALONE.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556

Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>

Signed-off-by: Alexander Bokovoy <ab@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
Alexander Bokovoy 2020-11-11 18:50:45 +02:00 committed by Joseph Sutton
parent 3efb9d684d
commit e4172baf12
21 changed files with 72 additions and 25 deletions

View File

@ -78,6 +78,13 @@
url="http://wiki.samba.org/index.php/Samba4/HOWTO">Samba4
HOWTO</ulink></para>
<para><anchor id="IPA-DC"/><emphasis>SERVER ROLE = IPA DOMAIN CONTROLLER</emphasis></para>
<para>This mode of operation runs Samba in a hybrid mode for IPA
domain controller, providing forest trust to Active Directory.
This role requires special configuration performed by IPA installers
and should not be used manually by any administrator.
</para>
</description>
<related>security</related>

View File

@ -42,6 +42,7 @@ static const struct srv_role_tab {
{ ROLE_DOMAIN_BDC, "ROLE_DOMAIN_BDC" },
{ ROLE_DOMAIN_PDC, "ROLE_DOMAIN_PDC" },
{ ROLE_ACTIVE_DIRECTORY_DC, "ROLE_ACTIVE_DIRECTORY_DC" },
{ ROLE_IPA_DC, "ROLE_IPA_DC"},
{ 0, NULL }
};
@ -140,6 +141,7 @@ bool lp_is_security_and_server_role_valid(int server_role, int security)
case ROLE_DOMAIN_PDC:
case ROLE_DOMAIN_BDC:
case ROLE_ACTIVE_DIRECTORY_DC:
case ROLE_IPA_DC:
if (security == SEC_USER) {
valid = true;
}

View File

@ -109,6 +109,7 @@ static const struct enum_list enum_server_role[] = {
{ROLE_ACTIVE_DIRECTORY_DC, "active directory domain controller"},
{ROLE_ACTIVE_DIRECTORY_DC, "domain controller"},
{ROLE_ACTIVE_DIRECTORY_DC, "dc"},
{ROLE_IPA_DC, "IPA primary domain controller"},
{-1, NULL}
};

View File

@ -255,6 +255,7 @@ const char *lpcfg_sam_name(struct loadparm_context *lp_ctx)
case ROLE_DOMAIN_BDC:
case ROLE_DOMAIN_PDC:
case ROLE_ACTIVE_DIRECTORY_DC:
case ROLE_IPA_DC:
return lpcfg_workgroup(lp_ctx);
default:
return lpcfg_netbios_name(lp_ctx);

View File

@ -93,7 +93,7 @@ NTSTATUS pull_netlogon_samlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
if (ndr->offset < ndr->data_size) {
TALLOC_FREE(ndr);
/*
* We need to handle a bug in FreeIPA (at least <= 4.1.2).
* We need to handle a bug in IPA (at least <= 4.1.2).
*
* They include the ip address information without setting
* NETLOGON_NT_VERSION_5EX_WITH_IP, while using

View File

@ -33,6 +33,7 @@ enum server_role {
/* not in samr.idl */
ROLE_ACTIVE_DIRECTORY_DC = 4,
ROLE_IPA_DC = 5,
/* To determine the role automatically, this is not a valid role */
ROLE_AUTO = 100

View File

@ -544,6 +544,7 @@ NTSTATUS make_auth3_context_for_ntlm(TALLOC_CTX *mem_ctx,
break;
case ROLE_DOMAIN_BDC:
case ROLE_DOMAIN_PDC:
case ROLE_IPA_DC:
role = "'DC'";
methods = "anonymous sam winbind sam_ignoredomain";
break;
@ -575,6 +576,7 @@ NTSTATUS make_auth3_context_for_netlogon(TALLOC_CTX *mem_ctx,
switch (lp_server_role()) {
case ROLE_DOMAIN_BDC:
case ROLE_DOMAIN_PDC:
case ROLE_IPA_DC:
methods = "sam_netlogon3 winbind";
break;
@ -596,6 +598,7 @@ NTSTATUS make_auth3_context_for_winbind(TALLOC_CTX *mem_ctx,
case ROLE_DOMAIN_MEMBER:
case ROLE_DOMAIN_BDC:
case ROLE_DOMAIN_PDC:
case ROLE_IPA_DC:
methods = "sam";
break;
case ROLE_ACTIVE_DIRECTORY_DC:

View File

@ -143,12 +143,13 @@ static NTSTATUS auth_samstrict_auth(const struct auth_context *auth_context,
break;
case ROLE_DOMAIN_PDC:
case ROLE_DOMAIN_BDC:
case ROLE_IPA_DC:
if (!is_local_name && !is_my_domain) {
/* If we are running on a DC that has PASSDB module with domain
* information, check if DNS forest name is matching the domain
* name. This is the case of FreeIPA domain controller when
* trusted AD DCs attempt to authenticate FreeIPA users using
* the forest root domain (which is the only domain in FreeIPA).
* name. This is the case of IPA domain controller when
* trusted AD DCs attempt to authenticate IPA users using
* the forest root domain (which is the only domain in IPA).
*/
struct pdb_domain_info *dom_info = NULL;
@ -234,6 +235,7 @@ static NTSTATUS auth_sam_netlogon3_auth(const struct auth_context *auth_context,
switch (lp_server_role()) {
case ROLE_DOMAIN_PDC:
case ROLE_DOMAIN_BDC:
case ROLE_IPA_DC:
break;
default:
DBG_ERR("Invalid server role\n");
@ -252,9 +254,9 @@ static NTSTATUS auth_sam_netlogon3_auth(const struct auth_context *auth_context,
if (!is_my_domain) {
/* If we are running on a DC that has PASSDB module with domain
* information, check if DNS forest name is matching the domain
* name. This is the case of FreeIPA domain controller when
* trusted AD DCs attempt to authenticate FreeIPA users using
* the forest root domain (which is the only domain in FreeIPA).
* name. This is the case of IPA domain controller when
* trusted AD DCs attempt to authenticate IPA users using
* the forest root domain (which is the only domain in IPA).
*/
struct pdb_domain_info *dom_info = NULL;
dom_info = pdb_get_domain_info(mem_ctx);

View File

@ -203,7 +203,7 @@ copy an IP address from one buffer to another
Check to see if we are a DC for this domain
*****************************************************************************/
#define IS_DC (lp_server_role()==ROLE_DOMAIN_PDC || lp_server_role()==ROLE_DOMAIN_BDC || lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC)
#define IS_DC (lp_server_role()==ROLE_DOMAIN_PDC || lp_server_role()==ROLE_DOMAIN_BDC || lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC || lp_server_role() == ROLE_IPA_DC)
#define IS_AD_DC (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC)
/*

View File

@ -378,6 +378,7 @@ WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
case ROLE_DOMAIN_MEMBER:
case ROLE_DOMAIN_PDC:
case ROLE_DOMAIN_BDC:
case ROLE_IPA_DC:
*r->out.name_type = NetSetupDomainName;
break;
case ROLE_STANDALONE:

View File

@ -4421,6 +4421,7 @@ int lp_default_server_announce(void)
default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
break;
case ROLE_DOMAIN_PDC:
case ROLE_IPA_DC:
default_server_announce |= SV_TYPE_DOMAIN_CTRL;
break;
case ROLE_DOMAIN_BDC:
@ -4446,7 +4447,8 @@ int lp_default_server_announce(void)
bool lp_domain_master(void)
{
if (Globals._domain_master == Auto)
return (lp_server_role() == ROLE_DOMAIN_PDC);
return (lp_server_role() == ROLE_DOMAIN_PDC ||
lp_server_role() == ROLE_IPA_DC);
return (bool)Globals._domain_master;
}

View File

@ -121,7 +121,7 @@ bool lookup_name(TALLOC_CTX *mem_ctx,
/* If we are running on a DC that has PASSDB module with domain
* information, check if DNS forest name is matching the domain
* name. This is the case of FreeIPA domain controller when
* name. This is the case of IPA domain controller when
* trusted AD DC looks up users found in a Global Catalog of
* the forest root domain. */
if (!check_global_sam && (IS_DC)) {

View File

@ -198,7 +198,8 @@ bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
dyn_guid = (struct GUID *)secrets_fetch(key, &size);
if (!dyn_guid) {
if (lp_server_role() == ROLE_DOMAIN_PDC) {
if (lp_server_role() == ROLE_DOMAIN_PDC ||
lp_server_role() == ROLE_IPA_DC) {
new_guid = GUID_random();
if (!secrets_store_domain_guid(domain, &new_guid))
return False;
@ -314,9 +315,7 @@ static const char *trust_keystr(const char *domain)
enum netr_SchannelType get_default_sec_channel(void)
{
if (lp_server_role() == ROLE_DOMAIN_BDC ||
lp_server_role() == ROLE_DOMAIN_PDC ||
lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
if (IS_DC) {
return SEC_CHAN_BDC;
} else {
return SEC_CHAN_WKSTA;

View File

@ -40,6 +40,7 @@ static int prod_options_fetch_values(const char *key, struct regval_ctr *regvals
switch (lp_server_role()) {
case ROLE_DOMAIN_PDC:
case ROLE_DOMAIN_BDC:
case ROLE_IPA_DC:
value_ascii = "LanmanNT";
break;
case ROLE_STANDALONE:

View File

@ -63,6 +63,7 @@ static WERROR fill_dsrole_dominfo_basic(TALLOC_CTX *ctx,
basic->domain = get_global_sam_name();
break;
case ROLE_DOMAIN_PDC:
case ROLE_IPA_DC:
basic->role = DS_ROLE_PRIMARY_DC;
basic->domain = get_global_sam_name();
break;

View File

@ -1930,7 +1930,7 @@ extern void build_options(bool screen);
exit_daemon("smbd can not open secrets.tdb", EACCES);
}
if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) {
if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC || lp_server_role() == ROLE_IPA_DC) {
struct loadparm_context *lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
if (!open_schannel_session_store(NULL, lp_ctx)) {
exit_daemon("ERROR: Samba cannot open schannel store for secured NETLOGON operations.", EACCES);

View File

@ -76,7 +76,7 @@ static char *get_trust_type_string(TALLOC_CTX *mem_ctx,
case SEC_CHAN_BDC: {
int role = lp_server_role();
if (role == ROLE_DOMAIN_PDC) {
if (role == ROLE_DOMAIN_PDC || role == ROLE_IPA_DC) {
s = talloc_strdup(mem_ctx, "PDC");
if (s == NULL) {
return NULL;

View File

@ -1322,15 +1322,37 @@ bool init_domain_list(void)
secure_channel_type = SEC_CHAN_LOCAL;
}
status = add_trusted_domain(get_global_sam_name(),
NULL,
get_global_sam_sid(),
LSA_TRUST_TYPE_DOWNLEVEL,
trust_flags,
0, /* trust_attribs */
secure_channel_type,
NULL,
&domain);
if ((pdb_domain_info != NULL) && (role == ROLE_IPA_DC)) {
/* This is IPA DC that presents itself as
* an Active Directory domain controller to trusted AD
* forests but in fact is a classic domain controller.
*/
trust_flags = NETR_TRUST_FLAG_PRIMARY;
trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
trust_flags |= NETR_TRUST_FLAG_NATIVE;
trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
trust_flags |= NETR_TRUST_FLAG_TREEROOT;
status = add_trusted_domain(pdb_domain_info->name,
pdb_domain_info->dns_domain,
&pdb_domain_info->sid,
LSA_TRUST_TYPE_UPLEVEL,
trust_flags,
LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
secure_channel_type,
NULL,
&domain);
TALLOC_FREE(pdb_domain_info);
} else {
status = add_trusted_domain(get_global_sam_name(),
NULL,
get_global_sam_sid(),
LSA_TRUST_TYPE_DOWNLEVEL,
trust_flags,
0, /* trust_attribs */
secure_channel_type,
NULL,
&domain);
}
if (!NT_STATUS_IS_OK(status)) {
DBG_ERR("Failed to add local SAM to "
"domain to winbindd's internal list\n");

View File

@ -737,6 +737,7 @@ const char **auth_methods_from_lp(TALLOC_CTX *mem_ctx, struct loadparm_context *
case ROLE_DOMAIN_BDC:
case ROLE_DOMAIN_PDC:
case ROLE_ACTIVE_DIRECTORY_DC:
case ROLE_IPA_DC:
auth_methods = str_list_make(mem_ctx, "anonymous sam winbind sam_ignoredomain", NULL);
break;
}

View File

@ -276,6 +276,7 @@ static NTSTATUS kdc_task_init(struct task_server *task)
return NT_STATUS_INVALID_DOMAIN_ROLE;
case ROLE_DOMAIN_PDC:
case ROLE_DOMAIN_BDC:
case ROLE_IPA_DC:
task_server_terminate(
task, "Cannot start KDC as a 'classic Samba' DC", false);
return NT_STATUS_INVALID_DOMAIN_ROLE;

View File

@ -575,6 +575,7 @@ static NTSTATUS dcesrv_samr_info_DomGeneralInformation(struct samr_domain_state
break;
case ROLE_DOMAIN_PDC:
case ROLE_DOMAIN_BDC:
case ROLE_IPA_DC:
case ROLE_AUTO:
return NT_STATUS_INTERNAL_ERROR;
case ROLE_DOMAIN_MEMBER:
@ -723,6 +724,7 @@ static NTSTATUS dcesrv_samr_info_DomInfo7(struct samr_domain_state *state,
break;
case ROLE_DOMAIN_PDC:
case ROLE_DOMAIN_BDC:
case ROLE_IPA_DC:
case ROLE_AUTO:
return NT_STATUS_INTERNAL_ERROR;
case ROLE_DOMAIN_MEMBER: