summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Bokovoy <ab@samba.org>2020-11-11 18:50:45 +0200
committerJule Anger <janger@samba.org>2021-11-09 19:45:33 +0000
commite2d5b4d709293b52112d078d6fcde95593d790c5 (patch)
tree5913a1da26d2a90cdb1a1ce8ffaeae2ef872b674
parent57abb7f8f8884f52f1d194c5c74e067aecd0d3dd (diff)
downloadsamba-e2d5b4d709293b52112d078d6fcde95593d790c5.tar.gz
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>
-rw-r--r--docs-xml/smbdotconf/security/serverrole.xml7
-rw-r--r--lib/param/loadparm_server_role.c2
-rw-r--r--lib/param/param_table.c1
-rw-r--r--lib/param/util.c1
-rw-r--r--libcli/netlogon/netlogon.c2
-rw-r--r--libds/common/roles.h1
-rw-r--r--source3/auth/auth.c3
-rw-r--r--source3/auth/auth_sam.c14
-rw-r--r--source3/include/smb_macros.h2
-rw-r--r--source3/lib/netapi/joindomain.c1
-rw-r--r--source3/param/loadparm.c4
-rw-r--r--source3/passdb/lookup_sid.c2
-rw-r--r--source3/passdb/machine_account_secrets.c7
-rw-r--r--source3/registry/reg_backend_prod_options.c1
-rw-r--r--source3/rpc_server/dssetup/srv_dssetup_nt.c1
-rw-r--r--source3/smbd/server.c2
-rw-r--r--source3/winbindd/winbindd_misc.c2
-rw-r--r--source3/winbindd/winbindd_util.c40
-rw-r--r--source4/auth/ntlm/auth.c1
-rw-r--r--source4/kdc/kdc-heimdal.c1
-rw-r--r--source4/rpc_server/samr/dcesrv_samr.c2
21 files changed, 72 insertions, 25 deletions
diff --git a/docs-xml/smbdotconf/security/serverrole.xml b/docs-xml/smbdotconf/security/serverrole.xml
index 9511c61c96d..b8b83a127b5 100644
--- a/docs-xml/smbdotconf/security/serverrole.xml
+++ b/docs-xml/smbdotconf/security/serverrole.xml
@@ -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>
diff --git a/lib/param/loadparm_server_role.c b/lib/param/loadparm_server_role.c
index 7a6bc770723..a78d1ab9cf3 100644
--- a/lib/param/loadparm_server_role.c
+++ b/lib/param/loadparm_server_role.c
@@ -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;
}
diff --git a/lib/param/param_table.c b/lib/param/param_table.c
index d9301152d94..9fac73ef113 100644
--- a/lib/param/param_table.c
+++ b/lib/param/param_table.c
@@ -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}
};
diff --git a/lib/param/util.c b/lib/param/util.c
index cd8e74b9d8f..9a0fc102de8 100644
--- a/lib/param/util.c
+++ b/lib/param/util.c
@@ -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);
diff --git a/libcli/netlogon/netlogon.c b/libcli/netlogon/netlogon.c
index 239503e85b6..59af460dc4e 100644
--- a/libcli/netlogon/netlogon.c
+++ b/libcli/netlogon/netlogon.c
@@ -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
diff --git a/libds/common/roles.h b/libds/common/roles.h
index 4772c8d7d3f..03ba1915b21 100644
--- a/libds/common/roles.h
+++ b/libds/common/roles.h
@@ -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
diff --git a/source3/auth/auth.c b/source3/auth/auth.c
index ce6bf6c5621..fec19c76dbb 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -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:
diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c
index e8e0d543f8c..a2ce1013975 100644
--- a/source3/auth/auth_sam.c
+++ b/source3/auth/auth_sam.c
@@ -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);
diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h
index 39a7c0d6911..ba2c76764d1 100644
--- a/source3/include/smb_macros.h
+++ b/source3/include/smb_macros.h
@@ -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)
/*
diff --git a/source3/lib/netapi/joindomain.c b/source3/lib/netapi/joindomain.c
index da40a887172..4fe5a3b8eef 100644
--- a/source3/lib/netapi/joindomain.c
+++ b/source3/lib/netapi/joindomain.c
@@ -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:
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index fd1f7b92610..62878c213d3 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -4422,6 +4422,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:
@@ -4447,7 +4448,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;
}
diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c
index 0e01467b3cb..a551bcfd24a 100644
--- a/source3/passdb/lookup_sid.c
+++ b/source3/passdb/lookup_sid.c
@@ -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)) {
diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c
index 1964eb5a448..f98f0c98674 100644
--- a/source3/passdb/machine_account_secrets.c
+++ b/source3/passdb/machine_account_secrets.c
@@ -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;
diff --git a/source3/registry/reg_backend_prod_options.c b/source3/registry/reg_backend_prod_options.c
index 655c587ac40..7bd3f324c37 100644
--- a/source3/registry/reg_backend_prod_options.c
+++ b/source3/registry/reg_backend_prod_options.c
@@ -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:
diff --git a/source3/rpc_server/dssetup/srv_dssetup_nt.c b/source3/rpc_server/dssetup/srv_dssetup_nt.c
index 64569382695..932452bc13b 100644
--- a/source3/rpc_server/dssetup/srv_dssetup_nt.c
+++ b/source3/rpc_server/dssetup/srv_dssetup_nt.c
@@ -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;
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index b9fb7e855b8..d7f5b4b73c0 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -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);
diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c
index 451ad6aee14..db7e1c87dee 100644
--- a/source3/winbindd/winbindd_misc.c
+++ b/source3/winbindd/winbindd_misc.c
@@ -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;
diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 6e3739f68c1..fe68adec534 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -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");
diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c
index 4c66f2c23cb..ea9ff70ce80 100644
--- a/source4/auth/ntlm/auth.c
+++ b/source4/auth/ntlm/auth.c
@@ -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;
}
diff --git a/source4/kdc/kdc-heimdal.c b/source4/kdc/kdc-heimdal.c
index c695004cafc..ce32d3cb1b3 100644
--- a/source4/kdc/kdc-heimdal.c
+++ b/source4/kdc/kdc-heimdal.c
@@ -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;
diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c
index cda887d45ee..29c509522be 100644
--- a/source4/rpc_server/samr/dcesrv_samr.c
+++ b/source4/rpc_server/samr/dcesrv_samr.c
@@ -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: