winbind: Keep "force_reauth" in invalidate_cm_connection
[kai/samba-autobuild/.git] / source3 / winbindd / winbindd_cm.c
index 4229647dc4d135c9edf3146cce8fd0899ccea2b1..bf5a2b4d7b1c06b85c2af8728145451be66952e8 100644 (file)
@@ -999,6 +999,31 @@ static NTSTATUS cm_prepare_connection(struct winbindd_domain *domain,
 
        enum smb_signing_setting smb_sign_client_connections = lp_client_ipc_signing();
 
+       if (IS_AD_DC) {
+               if (domain->secure_channel_type == SEC_CHAN_NULL) {
+                       /*
+                        * Make sure we don't even try to
+                        * connect to a foreign domain
+                        * without a direct outbound trust.
+                        */
+                       return NT_STATUS_NO_TRUST_LSA_SECRET;
+               }
+
+               /*
+                * As AD DC we only use netlogon and lsa
+                * using schannel over an anonymous transport
+                * (ncacn_ip_tcp or ncacn_np).
+                *
+                * Currently we always establish the SMB connection,
+                * even if we don't use it, because we later use ncacn_ip_tcp.
+                *
+                * As we won't use the SMB connection there's no
+                * need to try kerberos. And NT4 domains expect
+                * an anonymous IPC$ connection anyway.
+                */
+               smb_sign_client_connections = SMB_SIGNING_OFF;
+       }
+
        if (smb_sign_client_connections == SMB_SIGNING_DEFAULT) {
                /*
                 * If we are connecting to our own AD domain, require
@@ -1011,8 +1036,7 @@ static NTSTATUS cm_prepare_connection(struct winbindd_domain *domain,
                 * AD domain in our forest
                 * then require smb signing to disrupt MITM attacks
                 */
-               } else if ((lp_security() == SEC_ADS ||
-                           lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC)
+               } else if ((lp_security() == SEC_ADS)
                           && domain->active_directory
                           && (domain->domain_trust_attribs
                               & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
@@ -1071,6 +1095,22 @@ static NTSTATUS cm_prepare_connection(struct winbindd_domain *domain,
                try_ipc_auth = true;
        }
 
+       if (IS_AD_DC) {
+               /*
+                * As AD DC we only use netlogon and lsa
+                * using schannel over an anonymous transport
+                * (ncacn_ip_tcp or ncacn_np).
+                *
+                * Currently we always establish the SMB connection,
+                * even if we don't use it, because we later use ncacn_ip_tcp.
+                *
+                * As we won't use the SMB connection there's no
+                * need to try kerberos. And NT4 domains expect
+                * an anonymous IPC$ connection anyway.
+                */
+               try_ipc_auth = false;
+       }
+
        if (try_ipc_auth) {
                result = get_trust_credentials(domain, talloc_tos(), false, &creds);
                if (!NT_STATUS_IS_OK(result)) {
@@ -2041,7 +2081,6 @@ void invalidate_cm_connection(struct winbindd_domain *domain)
        }
 
        conn->auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
-       conn->netlogon_force_reauth = false;
        TALLOC_FREE(conn->netlogon_creds_ctx);
 
        if (conn->cli) {
@@ -2190,6 +2229,15 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
        TALLOC_CTX *mem_ctx = NULL;
        struct dcerpc_binding_handle *b;
 
+       if (IS_DC) {
+               /*
+                * On a DC we loaded all trusts
+                * from configuration and never learn
+                * new domains.
+                */
+               return true;
+       }
+
        DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s\n", domain->name ));
 
        /* Our primary domain doesn't need to worry about trust flags.
@@ -2584,6 +2632,15 @@ done:
 
 static void set_dc_type_and_flags( struct winbindd_domain *domain )
 {
+       if (IS_DC) {
+               /*
+                * On a DC we loaded all trusts
+                * from configuration and never learn
+                * new domains.
+                */
+               return;
+       }
+
        /* we always have to contact our primary domain */
 
        if ( domain->primary || domain->internal) {
@@ -2650,6 +2707,20 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
                }
        }
 
+       if (IS_AD_DC) {
+               /*
+                * In theory we should not use SAMR within
+                * winbindd at all, but that's a larger task to
+                * remove this and avoid breaking existing
+                * setups.
+                *
+                * At least as AD DC we have the restriction
+                * to avoid SAMR against trusted domains,
+                * as there're no existing setups.
+                */
+               return NT_STATUS_REQUEST_NOT_ACCEPTED;
+       }
+
 retry:
        status = init_dc_connection_rpc(domain, need_rw_dc);
        if (!NT_STATUS_IS_OK(status)) {
@@ -2970,6 +3041,13 @@ retry:
 
        TALLOC_FREE(conn->lsa_pipe);
 
+       if (IS_AD_DC) {
+               /*
+                * Make sure we only use schannel as AD DC.
+                */
+               goto schannel;
+       }
+
        result = get_trust_credentials(domain, talloc_tos(), false, &creds);
        if (!NT_STATUS_IS_OK(result)) {
                DEBUG(10, ("cm_connect_lsa: No user available for "
@@ -3083,6 +3161,13 @@ retry:
                goto done;
        }
 
+       if (IS_AD_DC) {
+               /*
+                * Make sure we only use schannel as AD DC.
+                */
+               goto done;
+       }
+
        DEBUG(10,("cm_connect_lsa: rpccli_lsa_open_policy failed, trying "
                  "anonymous\n"));
 
@@ -3090,6 +3175,13 @@ retry:
 
  anonymous:
 
+       if (IS_AD_DC) {
+               /*
+                * Make sure we only use schannel as AD DC.
+                */
+               goto done;
+       }
+
        if (lp_winbind_sealed_pipes() || lp_require_strong_key()) {
                result = NT_STATUS_DOWNGRADE_DETECTED;
                DEBUG(1, ("Unwilling to make LSA connection to domain %s "
@@ -3191,6 +3283,17 @@ static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
 
        *cli = NULL;
 
+       if (IS_AD_DC) {
+               if (domain->secure_channel_type == SEC_CHAN_NULL) {
+                       /*
+                        * Make sure we don't even try to
+                        * connect to a foreign domain
+                        * without a direct outbound trust.
+                        */
+                       return NT_STATUS_NO_TRUST_LSA_SECRET;
+               }
+       }
+
        result = init_dc_connection_rpc(domain, domain->rodc);
        if (!NT_STATUS_IS_OK(result)) {
                return result;
@@ -3264,6 +3367,7 @@ static NTSTATUS cm_connect_netlogon_transport(struct winbindd_domain *domain,
                conn->cli, transport,
                conn->netlogon_creds_ctx, conn->netlogon_force_reauth, creds,
                &conn->netlogon_pipe);
+       conn->netlogon_force_reauth = false;
        if (!NT_STATUS_IS_OK(result)) {
                DBG_DEBUG("rpccli_connect_netlogon failed: %s\n",
                          nt_errstr(result));
@@ -3405,3 +3509,19 @@ void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
        }
        TALLOC_FREE(freeit);
 }
+
+void winbind_msg_disconnect_dc(struct messaging_context *msg_ctx,
+                              void *private_data,
+                              uint32_t msg_type,
+                              struct server_id server_id,
+                              DATA_BLOB *data)
+{
+       struct winbindd_domain *domain;
+
+       for (domain = domain_list(); domain; domain = domain->next) {
+               if (domain->internal) {
+                       continue;
+               }
+               invalidate_cm_connection(domain);
+       }
+}