s3: Fix a typo
[abartlet/samba.git/.git] / source3 / winbindd / winbindd_cm.c
index c2df24456886bc84bb0c8b5649c425c16a69c603..94142e03238cf542bae3fbbd67efa2bcaa789efc 100644 (file)
 #include "winbindd.h"
 #include "../libcli/auth/libcli_auth.h"
 #include "../librpc/gen_ndr/cli_netlogon.h"
+#include "rpc_client/cli_netlogon.h"
 #include "../librpc/gen_ndr/cli_samr.h"
 #include "../librpc/gen_ndr/cli_lsa.h"
+#include "rpc_client/cli_lsarpc.h"
 #include "../librpc/gen_ndr/cli_dssetup.h"
 #include "libads/sitename_cache.h"
+#include "librpc/gen_ndr/messaging.h"
+#include "libsmb/clidgram.h"
+#include "ads.h"
+#include "secrets.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
@@ -180,9 +186,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
@@ -810,11 +813,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;
        }
@@ -1134,7 +1157,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 {
@@ -1142,7 +1166,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);
 
@@ -1433,7 +1458,7 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
        }
 
        /* we have to check the server affinity cache here since 
-          later we selecte a DC based on response time and not preference */
+          later we select a DC based on response time and not preference */
 
        /* Check the negative connection cache
           before talking to it. It going down may have
@@ -1551,6 +1576,10 @@ void invalidate_cm_connection(struct winbindd_cm_conn *conn)
        }
 
        if (conn->samr_pipe != NULL) {
+               if (is_valid_policy_hnd(&conn->sam_connect_handle)) {
+                       rpccli_samr_Close(conn->samr_pipe, talloc_tos(),
+                                         &conn->sam_connect_handle);
+               }
                TALLOC_FREE(conn->samr_pipe);
                /* Ok, it must be dead. Drop timeout to 0.5 sec. */
                if (conn->cli) {
@@ -1559,6 +1588,10 @@ void invalidate_cm_connection(struct winbindd_cm_conn *conn)
        }
 
        if (conn->lsa_pipe != NULL) {
+               if (is_valid_policy_hnd(&conn->lsa_policy)) {
+                       rpccli_lsa_Close(conn->lsa_pipe, talloc_tos(),
+                                        &conn->lsa_policy);
+               }
                TALLOC_FREE(conn->lsa_pipe);
                /* Ok, it must be dead. Drop timeout to 0.5 sec. */
                if (conn->cli) {
@@ -1567,6 +1600,10 @@ void invalidate_cm_connection(struct winbindd_cm_conn *conn)
        }
 
        if (conn->lsa_pipe_tcp != NULL) {
+               if (is_valid_policy_hnd(&conn->lsa_policy)) {
+                       rpccli_lsa_Close(conn->lsa_pipe, talloc_tos(),
+                                        &conn->lsa_policy);
+               }
                TALLOC_FREE(conn->lsa_pipe_tcp);
                /* Ok, it must be dead. Drop timeout to 0.5 sec. */
                if (conn->cli) {
@@ -1668,6 +1705,10 @@ static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain)
 
 NTSTATUS init_dc_connection(struct winbindd_domain *domain)
 {
+       if (domain->internal) {
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+       }
+
        if (domain->initialized && !domain->online) {
                /* We check for online status elsewhere. */
                return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
@@ -2003,30 +2044,30 @@ static void set_dc_type_and_flags( struct winbindd_domain *domain )
 /**********************************************************************
 ***********************************************************************/
 
-static bool cm_get_schannel_creds(struct winbindd_domain *domain,
+static NTSTATUS cm_get_schannel_creds(struct winbindd_domain *domain,
                                   struct netlogon_creds_CredentialState **ppdc)
 {
-       NTSTATUS result;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        struct rpc_pipe_client *netlogon_pipe;
 
        if (lp_client_schannel() == False) {
-               return False;
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;;
        }
 
        result = cm_connect_netlogon(domain, &netlogon_pipe);
        if (!NT_STATUS_IS_OK(result)) {
-               return False;
+               return result;
        }
 
        /* Return a pointer to the struct netlogon_creds_CredentialState from the
           netlogon pipe. */
 
        if (!domain->conn.netlogon_pipe->dc) {
-               return false;
+               return NT_STATUS_INTERNAL_ERROR; /* This shouldn't happen. */
        }
 
        *ppdc = domain->conn.netlogon_pipe->dc;
-       return True;
+       return NT_STATUS_OK;
 }
 
 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
@@ -2039,6 +2080,10 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
        char *machine_account = NULL;
        char *domain_name = NULL;
 
+       if (sid_check_is_domain(&domain->sid)) {
+               return open_internal_samr_conn(mem_ctx, domain, cli, sam_handle);
+       }
+
        result = init_dc_connection_rpc(domain);
        if (!NT_STATUS_IS_OK(result)) {
                return result;
@@ -2123,10 +2168,13 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 
        /* Fall back to schannel if it's a W2K pre-SP1 box. */
 
-       if (!cm_get_schannel_creds(domain, &p_creds)) {
+       result = cm_get_schannel_creds(domain, &p_creds);
+       if (!NT_STATUS_IS_OK(result)) {
                /* If this call fails - conn->cli can now be NULL ! */
                DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
-                          "for domain %s, trying anon\n", domain->name));
+                          "for domain %s (error %s), trying anon\n",
+                       domain->name,
+                       nt_errstr(result) ));
                goto anonymous;
        }
        result = cli_rpc_pipe_open_schannel_with_key
@@ -2218,6 +2266,7 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
                            struct rpc_pipe_client **cli)
 {
        struct winbindd_cm_conn *conn;
+       struct netlogon_creds_CredentialState *creds;
        NTSTATUS status;
 
        DEBUG(10,("cm_connect_lsa_tcp\n"));
@@ -2238,14 +2287,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,
-                                           DCERPC_AUTH_LEVEL_PRIVACY,
-                                           domain->name,
-                                           &conn->lsa_pipe_tcp);
+       status = cm_get_schannel_creds(domain, &creds);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
+
+       status = cli_rpc_pipe_open_schannel_with_key(conn->cli,
+                                                    &ndr_table_lsarpc.syntax_id,
+                                                    NCACN_IP_TCP,
+                                                    DCERPC_AUTH_LEVEL_PRIVACY,
+                                                    domain->name,
+                                                    &creds,
+                                                    &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;
        }
@@ -2325,10 +2380,13 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
 
        /* Fall back to schannel if it's a W2K pre-SP1 box. */
 
-       if (!cm_get_schannel_creds(domain, &p_creds)) {
+       result = cm_get_schannel_creds(domain, &p_creds);
+       if (!NT_STATUS_IS_OK(result)) {
                /* If this call fails - conn->cli can now be NULL ! */
                DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
-                          "for domain %s, trying anon\n", domain->name));
+                          "for domain %s (error %s), trying anon\n",
+                       domain->name,
+                       nt_errstr(result) ));
                goto anonymous;
        }
        result = cli_rpc_pipe_open_schannel_with_key