Fix bug 7636 - winbind internal error, backtrace.
[samba.git] / source3 / winbindd / winbindd_cm.c
index d3d2e16c82a3d9864ba6c1bf2afc8b1e55f83035..0a5c147fd57fed3df2b6c717ebb6fac9eff00466 100644 (file)
@@ -174,9 +174,6 @@ static bool fork_child_dc_connect(struct winbindd_domain *domain)
        pid_t parent_pid = sys_getpid();
        char *lfile = NULL;
 
-       /* Stop zombies */
-       CatchChild();
-
        if (domain->dc_probe_pid != (pid_t)-1) {
                /*
                 * We might already have a DC probe
@@ -797,11 +794,31 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
 
        peeraddr_len = sizeof(peeraddr);
 
-       if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
-           (peeraddr_len != sizeof(struct sockaddr_in)) ||
-           (peeraddr_in->sin_family != PF_INET))
-       {
-               DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
+       if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0)) {
+               DEBUG(0,("cm_prepare_connection: getpeername failed with: %s\n",
+                       strerror(errno)));
+               result = NT_STATUS_UNSUCCESSFUL;
+               goto done;
+       }
+
+       if ((peeraddr_len != sizeof(struct sockaddr_in))
+#ifdef HAVE_IPV6
+           && (peeraddr_len != sizeof(struct sockaddr_in6))
+#endif
+           ) {
+               DEBUG(0,("cm_prepare_connection: got unexpected peeraddr len %d\n",
+                       peeraddr_len));
+               result = NT_STATUS_UNSUCCESSFUL;
+               goto done;
+       }
+
+       if ((peeraddr_in->sin_family != PF_INET)
+#ifdef HAVE_IPV6
+           && (peeraddr_in->sin_family != PF_INET6)
+#endif
+           ) {
+               DEBUG(0,("cm_prepare_connection: got unexpected family %d\n",
+                       peeraddr_in->sin_family));
                result = NT_STATUS_UNSUCCESSFUL;
                goto done;
        }
@@ -1119,7 +1136,8 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx,
                                        create_local_private_krb5_conf_for_domain(domain->alt_name,
                                                                        domain->name,
                                                                        sitename,
-                                                                       pss);
+                                                                       pss,
+                                                                       name);
 
                                        SAFE_FREE(sitename);
                                } else {
@@ -1127,7 +1145,8 @@ static bool dcip_to_name(TALLOC_CTX *mem_ctx,
                                        create_local_private_krb5_conf_for_domain(domain->alt_name,
                                                                        domain->name,
                                                                        NULL,
-                                                                       pss);
+                                                                       pss,
+                                                                       name);
                                }
                                winbindd_set_locator_kdc_envs(domain);
 
@@ -1622,6 +1641,12 @@ static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
                return NT_STATUS_OK;
        }
 
+       if (!winbindd_can_contact_domain(domain)) {
+               invalidate_cm_connection(&domain->conn);
+               domain->initialized = True;
+               return NT_STATUS_OK;
+       }
+
        if (connection_ok(domain)) {
                if (!domain->initialized) {
                        set_dc_type_and_flags(domain);
@@ -1650,6 +1675,23 @@ NTSTATUS init_dc_connection(struct winbindd_domain *domain)
        return init_dc_connection_network(domain);
 }
 
+static NTSTATUS init_dc_connection_rpc(struct winbindd_domain *domain)
+{
+       NTSTATUS status;
+
+       status = init_dc_connection(domain);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       if (!domain->internal && domain->conn.cli == NULL) {
+               /* happens for trusted domains without inbound trust */
+               return NT_STATUS_TRUSTED_DOMAIN_FAILURE;
+       }
+
+       return NT_STATUS_OK;
+}
+
 /******************************************************************************
  Set the trust flags (direction and forest location) for a domain
 ******************************************************************************/
@@ -1745,9 +1787,6 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
 
                        domain->initialized = True;
 
-                       if ( !winbindd_can_contact_domain( domain) )
-                               domain->internal = True;
-
                        break;
                }               
        }
@@ -1999,7 +2038,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
        char *machine_account = NULL;
        char *domain_name = NULL;
 
-       result = init_dc_connection(domain);
+       result = init_dc_connection_rpc(domain);
        if (!NT_STATUS_IS_OK(result)) {
                return result;
        }
@@ -2010,6 +2049,7 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
                goto done;
        }
 
+       TALLOC_FREE(conn->samr_pipe);
 
        /*
         * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO authenticated
@@ -2177,11 +2217,12 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
                            struct rpc_pipe_client **cli)
 {
        struct winbindd_cm_conn *conn;
+       struct dcinfo *dcinfo;
        NTSTATUS status;
 
        DEBUG(10,("cm_connect_lsa_tcp\n"));
 
-       status = init_dc_connection(domain);
+       status = init_dc_connection_rpc(domain);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -2197,14 +2238,20 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
 
        TALLOC_FREE(conn->lsa_pipe_tcp);
 
-       status = cli_rpc_pipe_open_schannel(conn->cli,
-                                           &ndr_table_lsarpc.syntax_id,
-                                           NCACN_IP_TCP,
-                                           PIPE_AUTH_LEVEL_PRIVACY,
-                                           domain->name,
-                                           &conn->lsa_pipe_tcp);
+       if (!cm_get_schannel_dcinfo(domain, &dcinfo)) {
+               status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+               goto done;
+       }
+
+       status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
+                                                    &ndr_table_lsarpc.syntax_id,
+                                                    NCACN_IP_TCP,
+                                                    PIPE_AUTH_LEVEL_PRIVACY,
+                                                    domain->name,
+                                                    dcinfo,
+                                                    &conn->lsa_pipe_tcp);
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(10,("cli_rpc_pipe_open_schannel failed: %s\n",
+               DEBUG(10,("cli_rpc_pipe_open_schannel_with_key failed: %s\n",
                        nt_errstr(status)));
                goto done;
        }
@@ -2227,7 +2274,7 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        struct dcinfo *p_dcinfo;
 
-       result = init_dc_connection(domain);
+       result = init_dc_connection_rpc(domain);
        if (!NT_STATUS_IS_OK(result))
                return result;
 
@@ -2237,6 +2284,8 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
                goto done;
        }
 
+       TALLOC_FREE(conn->lsa_pipe);
+
        if ((conn->cli->user_name[0] == '\0') ||
            (conn->cli->domain[0] == '\0') || 
            (conn->cli->password == NULL || conn->cli->password[0] == '\0')) {
@@ -2357,7 +2406,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
 
        *cli = NULL;
 
-       result = init_dc_connection(domain);
+       result = init_dc_connection_rpc(domain);
        if (!NT_STATUS_IS_OK(result)) {
                return result;
        }
@@ -2369,6 +2418,8 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
                return NT_STATUS_OK;
        }
 
+       TALLOC_FREE(conn->netlogon_pipe);
+
        result = cli_rpc_pipe_open_noauth(conn->cli,
                                          &ndr_table_netlogon.syntax_id,
                                          &netlogon_pipe);
@@ -2447,8 +2498,8 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
                DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
                          "was %s\n", nt_errstr(result)));
 
-               /* make sure we return something besides OK */
-               return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
+               invalidate_cm_connection(conn);
+               return result;
        }
 
        /*