Fix bug #8953 - winbind can hang as nbt_getdc() has no timeout.
[ddiss/samba.git] / source3 / winbindd / winbindd_cm.c
index 302df1e22d41e066343da33338912185a69db32d..9b04abab610b68cf69444a7c7ef6f86bc359f27b 100644 (file)
 #include "rpc_client/cli_lsarpc.h"
 #include "../librpc/gen_ndr/ndr_dssetup_c.h"
 #include "libads/sitename_cache.h"
-#include "librpc/gen_ndr/messaging.h"
+#include "libsmb/libsmb.h"
 #include "libsmb/clidgram.h"
 #include "ads.h"
 #include "secrets.h"
 #include "../libcli/security/security.h"
+#include "passdb.h"
+#include "messages.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
@@ -187,6 +189,7 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain)
        TALLOC_CTX *mem_ctx = NULL;
        pid_t parent_pid = sys_getpid();
        char *lfile = NULL;
+       NTSTATUS status;
 
        if (domain->dc_probe_pid != (pid_t)-1) {
                /*
@@ -231,7 +234,10 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain)
                }
        }
 
-       if (!winbindd_reinit_after_fork(lfile)) {
+       status = winbindd_reinit_after_fork(NULL, lfile);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
+                         nt_errstr(status)));
                messaging_send_buf(winbind_messaging_context(),
                                   pid_to_procid(parent_pid),
                                   MSG_WINBIND_FAILED_TO_GO_ONLINE,
@@ -814,7 +820,12 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
 
        (*cli)->timeout = 10000;        /* 10 seconds */
        (*cli)->fd = sockfd;
-       fstrcpy((*cli)->desthost, controller);
+       (*cli)->desthost = talloc_strdup((*cli), controller);
+       if ((*cli)->desthost == NULL) {
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+
        (*cli)->use_kerberos = True;
 
        peeraddr_len = sizeof(peeraddr);
@@ -1177,7 +1188,7 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx,
        }
 #endif
 
-       status = nbt_getdc(winbind_messaging_context(), pss, domain->name,
+       status = nbt_getdc(winbind_messaging_context(), 10, pss, domain->name,
                           &domain->sid, nt_version, mem_ctx, &nt_version,
                           &dc_name, NULL);
        if (NT_STATUS_IS_OK(status)) {
@@ -1373,7 +1384,7 @@ static bool find_new_dc(TALLOC_CTX *mem_ctx,
                return False;
 
        status = smbsock_any_connect(addrs, dcnames, NULL, NULL, NULL,
-                                    num_addrs, 0, fd, &fd_index, NULL);
+                                    num_addrs, 0, 10, fd, &fd_index, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                for (i=0; i<num_dcs; i++) {
                        char ab[INET6_ADDRSTRLEN];
@@ -1569,7 +1580,7 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
 
                        status = smbsock_connect(&domain->dcaddr, 0,
                                                 NULL, -1, NULL, -1,
-                                                &fd, NULL);
+                                                &fd, NULL, 10);
                        if (!NT_STATUS_IS_OK(status)) {
                                fd = -1;
                        }
@@ -1697,6 +1708,7 @@ void invalidate_cm_connection(struct winbindd_cm_conn *conn)
 void close_conns_after_fork(void)
 {
        struct winbindd_domain *domain;
+       struct winbindd_cli_state *cli_state;
 
        for (domain = domain_list(); domain; domain = domain->next) {
                struct cli_state *cli = domain->conn.cli;
@@ -1713,6 +1725,15 @@ void close_conns_after_fork(void)
 
                invalidate_cm_connection(&domain->conn);
        }
+
+       for (cli_state = winbindd_client_list();
+            cli_state != NULL;
+            cli_state = cli_state->next) {
+               if (cli_state->sock >= 0) {
+                       close(cli_state->sock);
+                       cli_state->sock = -1;
+               }
+       }
 }
 
 static bool connection_ok(struct winbindd_domain *domain)
@@ -1905,6 +1926,8 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
                                 "running active directory.\n", domain->name, 
                                 domain->active_directory ? "" : "NOT "));
 
+                       domain->can_do_ncacn_ip_tcp = domain->active_directory;
+                       domain->can_do_validation6 = domain->active_directory;
 
                        domain->initialized = True;
 
@@ -1983,7 +2006,7 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
                 * no_dssetup mode here as well to get domain->initialized
                 * set - gd */
 
-               if (NT_STATUS_V(status) == DCERPC_FAULT_OP_RNG_ERROR) {
+               if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
                        goto no_dssetup;
                }