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:
parent
3efb9d684d
commit
e4172baf12
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
||||
/*
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user