r25068: Older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for every opcode on the
[samba.git] / source3 / nsswitch / winbindd_cm.c
index b8b11b8466aa9638d4d165409124c1c0afbe8246..1a9d2bbeff36f6269b45918acdfc98ae0926e78f 100644 (file)
@@ -11,7 +11,7 @@
    
    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 2 of the License, or
+   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,
@@ -20,8 +20,7 @@
    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, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 /*
@@ -258,9 +257,7 @@ static void check_domain_online_handler(struct event_context *ctx,
                  "%s (online = %s)\n", domain->name, 
                  domain->online ? "True" : "False" ));
 
-       if (domain->check_online_event) {
-               TALLOC_FREE(domain->check_online_event);
-       }
+       TALLOC_FREE(domain->check_online_event);
 
        /* Are we still in "startup" mode ? */
 
@@ -312,9 +309,7 @@ void set_domain_offline(struct winbindd_domain *domain)
        DEBUG(10,("set_domain_offline: called for domain %s\n",
                domain->name ));
 
-       if (domain->check_online_event) {
-               TALLOC_FREE(domain->check_online_event);
-       }
+       TALLOC_FREE(domain->check_online_event);
 
        if (domain->internal) {
                DEBUG(3,("set_domain_offline: domain %s is internal - logic error.\n",
@@ -353,7 +348,7 @@ void set_domain_offline(struct winbindd_domain *domain)
 
        /* The above *has* to succeed for winbindd to work. */
        if (!domain->check_online_event) {
-               smb_panic("set_domain_offline: failed to add online handler.\n");
+               smb_panic("set_domain_offline: failed to add online handler");
        }
 
        DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
@@ -400,6 +395,8 @@ static void set_domain_online(struct winbindd_domain *domain)
                return;
        }
 
+       winbindd_set_locator_kdc_envs(domain);
+
        /* If we are waiting to get a krb5 ticket, trigger immediately. */
        GetTimeOfDay(&now);
        set_event_dispatch_time(winbind_event_context(),
@@ -426,9 +423,7 @@ static void set_domain_online(struct winbindd_domain *domain)
 
        /* Ensure we have no online timeout checks. */
        domain->check_online_timeout = 0;
-       if (domain->check_online_event) {
-               TALLOC_FREE(domain->check_online_event);
-       }
+       TALLOC_FREE(domain->check_online_event);
 
        /* Ensure we ignore any pending child messages. */
        messaging_deregister(winbind_messaging_context(),
@@ -496,7 +491,7 @@ void set_domain_online_request(struct winbindd_domain *domain)
 
                /* The above *has* to succeed for winbindd to work. */
                if (!domain->check_online_event) {
-                       smb_panic("set_domain_online_request: failed to add online handler.\n");
+                       smb_panic("set_domain_online_request: failed to add online handler");
                }
        }
 
@@ -527,6 +522,7 @@ void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
                add_failed_connection_entry(domain->alt_name, server, result);
                saf_delete(domain->alt_name);
        }
+       winbindd_unset_locator_kdc_env(domain);
 }
 
 /* Choose between anonymous or authenticated connections.  We need to use
@@ -748,6 +744,8 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
                                  "[%s]\n", controller, global_myname(),
                                  machine_krb5_principal));
 
+                       winbindd_set_locator_kdc_envs(domain);
+
                        ads_status = cli_session_setup_spnego(*cli,
                                                              machine_krb5_principal, 
                                                              machine_password, 
@@ -844,6 +842,8 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
                saf_store( domain->alt_name, (*cli)->desthost );
        }
 
+       winbindd_set_locator_kdc_envs(domain);
+
        if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
 
                result = cli_nt_error(*cli);
@@ -1084,19 +1084,29 @@ static BOOL dcip_to_name(const struct winbindd_domain *domain, struct in_addr ip
 
                        DEBUG(10,("dcip_to_name: flags = 0x%x\n", (unsigned int)ads->config.flags));
 
-                       if (domain->primary && (ads->config.flags & ADS_KDC) && ads_closest_dc(ads)) {
-                               char *sitename = sitename_fetch(ads->config.realm);
-
-                               /* We're going to use this KDC for this realm/domain.
-                                  If we are using sites, then force the krb5 libs
-                                  to use this KDC. */
-
-                               create_local_private_krb5_conf_for_domain(domain->alt_name,
-                                                               domain->name,
-                                                               sitename,
-                                                               ip);
+                       if (domain->primary && (ads->config.flags & ADS_KDC)) {
+                               if (ads_closest_dc(ads)) {
+                                       char *sitename = sitename_fetch(ads->config.realm);
+
+                                       /* We're going to use this KDC for this realm/domain.
+                                          If we are using sites, then force the krb5 libs
+                                          to use this KDC. */
+
+                                       create_local_private_krb5_conf_for_domain(domain->alt_name,
+                                                                       domain->name,
+                                                                       sitename,
+                                                                       ip);
+
+                                       SAFE_FREE(sitename);
+                               } else {
+                                       /* use an off site KDC */
+                                       create_local_private_krb5_conf_for_domain(domain->alt_name,
+                                                                       domain->name,
+                                                                       NULL,
+                                                                       ip);
+                               }
+                               winbindd_set_locator_kdc_envs(domain);
 
-                               SAFE_FREE(sitename);
                                /* Ensure we contact this DC also. */
                                saf_store( domain->name, name);
                                saf_store( domain->alt_name, name);
@@ -1401,6 +1411,9 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
        }
 
        if (NT_STATUS_IS_OK(result)) {
+
+               winbindd_set_locator_kdc_envs(domain);
+
                if (domain->online == False) {
                        /* We're changing state from offline to online. */
                        set_global_winbindd_state_online();
@@ -1702,6 +1715,16 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
                DEBUG(5, ("set_dc_type_and_flags_connect: rpccli_ds_getprimarydominfo "
                          "on domain %s failed: (%s)\n",
                          domain->name, nt_errstr(result)));
+
+               /* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
+                * every opcode on the LSARPC_DS pipe, continue with
+                * no_lsarpc_ds mode here as well to get domain->initialized
+                * set - gd */
+
+               if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
+                       goto no_lsarpc_ds;
+               }
+
                return;
        }
        
@@ -2201,6 +2224,12 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
  no_schannel:
        if ((lp_client_schannel() == False) ||
                        ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
+
+               /*
+                * NetSamLogonEx only works for schannel
+                */
+               domain->can_do_samlogon_ex = False;
+
                /* We're done - just keep the existing connection to NETLOGON
                 * open */
                conn->netlogon_pipe = netlogon_pipe;
@@ -2232,6 +2261,11 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
                return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
        }
 
+       /*
+        * Try NetSamLogonEx for AD domains
+        */
+       domain->can_do_samlogon_ex = domain->active_directory;
+       
        *cli = conn->netlogon_pipe;
        return NT_STATUS_OK;
 }