ctdb-scripts: Clarify logic for success of interface monitoring
[obnox/samba/samba-obnox.git] / source3 / winbindd / winbindd_msrpc.c
index 8986598daa021732a0bb454d256ba6f6dd84ba9f..41217475862121069366b207c7f7733b805ebb8b 100644 (file)
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 
+static NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
+                                     struct winbindd_domain *domain,
+                                     uint32_t num_names,
+                                     const char **names,
+                                     const char ***domains,
+                                     struct dom_sid **sids,
+                                     enum lsa_SidType **types);
 
 /* Query display info for a domain.  This returns enough information plus a
    bit extra to give an overview of domain users for the User Manager
@@ -69,7 +76,7 @@ static NTSTATUS msrpc_query_user_list(struct winbindd_domain *domain,
                goto done;
        }
 
-       status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol);
+       status = cm_connect_sam(domain, tmp_ctx, false, &samr_pipe, &dom_pol);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -128,7 +135,7 @@ static NTSTATUS msrpc_enum_dom_groups(struct winbindd_domain *domain,
                goto done;
        }
 
-       status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol);
+       status = cm_connect_sam(domain, tmp_ctx, false, &samr_pipe, &dom_pol);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -187,7 +194,7 @@ static NTSTATUS msrpc_enum_local_groups(struct winbindd_domain *domain,
                goto done;
        }
 
-       status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol);
+       status = cm_connect_sam(domain, tmp_ctx, false, &samr_pipe, &dom_pol);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -227,6 +234,7 @@ static NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
        struct dom_sid *sids = NULL;
        enum lsa_SidType *types = NULL;
        char *full_name = NULL;
+       const char *names[1];
        NTSTATUS name_map_status = NT_STATUS_UNSUCCESSFUL;
        char *mapped_name = NULL;
 
@@ -247,7 +255,7 @@ static NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
        name_map_status = normalize_name_unmap(mem_ctx, full_name,
                                               &mapped_name);
 
-       /* Reset the full_name pointer if we mapped anytthing */
+       /* Reset the full_name pointer if we mapped anything */
 
        if (NT_STATUS_IS_OK(name_map_status) ||
            NT_STATUS_EQUAL(name_map_status, NT_STATUS_FILE_RENAMED))
@@ -258,8 +266,10 @@ static NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
        DEBUG(3,("name_to_sid [rpc] %s for domain %s\n",
                 full_name?full_name:"", domain_name ));
 
+       names[0] = full_name;
+
        result = winbindd_lookup_names(mem_ctx, domain, 1,
-                                      (const char **)&full_name, NULL,
+                                      names, NULL,
                                       &sids, &types);
        if (!NT_STATUS_IS_OK(result))
                return result;
@@ -327,7 +337,7 @@ static NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
 static NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
                                    TALLOC_CTX *mem_ctx,
                                    const struct dom_sid *sid,
-                                   uint32 *rids,
+                                   uint32_t *rids,
                                    size_t num_rids,
                                    char **domain_name,
                                    char ***names,
@@ -342,7 +352,7 @@ static NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
        DEBUG(3, ("msrpc_rids_to_names: domain %s\n", domain->name ));
 
        if (num_rids) {
-               sids = TALLOC_ARRAY(mem_ctx, struct dom_sid, num_rids);
+               sids = talloc_array(mem_ctx, struct dom_sid, num_rids);
                if (sids == NULL) {
                        return NT_STATUS_NO_MEMORY;
                }
@@ -432,6 +442,14 @@ static NTSTATUS msrpc_query_user(struct winbindd_domain *domain,
                user_info->full_name = talloc_strdup(user_info,
                                                     user->base.full_name.string);
 
+               if (user_info->full_name == NULL) {
+                       /* this might fail so we don't check the return code */
+                       wcache_query_user_fullname(domain,
+                                                  mem_ctx,
+                                                  user_sid,
+                                                  &user_info->full_name);
+               }
+
                status = NT_STATUS_OK;
                goto done;
        }
@@ -445,7 +463,7 @@ static NTSTATUS msrpc_query_user(struct winbindd_domain *domain,
        }
 
        /* no cache; hit the wire */
-       status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol);
+       status = cm_connect_sam(domain, tmp_ctx, false, &samr_pipe, &dom_pol);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -505,7 +523,7 @@ static NTSTATUS msrpc_lookup_usergroups(struct winbindd_domain *domain,
        }
 
        /* no cache; hit the wire */
-       status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol);
+       status = cm_connect_sam(domain, tmp_ctx, false, &samr_pipe, &dom_pol);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -538,9 +556,9 @@ done:
 
 static NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
                                         TALLOC_CTX *mem_ctx,
-                                        uint32 num_sids, const struct dom_sid *sids,
-                                        uint32 *pnum_aliases,
-                                        uint32 **palias_rids)
+                                        uint32_t num_sids, const struct dom_sid *sids,
+                                        uint32_t *pnum_aliases,
+                                        uint32_t **palias_rids)
 {
        struct rpc_pipe_client *samr_pipe;
        struct policy_handle dom_pol;
@@ -568,7 +586,7 @@ static NTSTATUS msrpc_lookup_useraliases(struct winbindd_domain *domain,
                goto done;
        }
 
-       status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol);
+       status = cm_connect_sam(domain, tmp_ctx, false, &samr_pipe, &dom_pol);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -609,11 +627,11 @@ static NTSTATUS msrpc_lookup_groupmem(struct winbindd_domain *domain,
                                      uint32_t **name_types)
 {
        NTSTATUS status, result;
-        uint32 i, total_names = 0;
+       uint32_t i, total_names = 0;
         struct policy_handle dom_pol, group_pol;
-        uint32 des_access = SEC_FLAG_MAXIMUM_ALLOWED;
-       uint32 *rid_mem = NULL;
-       uint32 group_rid;
+       uint32_t des_access = SEC_FLAG_MAXIMUM_ALLOWED;
+       uint32_t *rid_mem = NULL;
+       uint32_t group_rid;
        unsigned int j, r;
        struct rpc_pipe_client *cli;
        unsigned int orig_timeout;
@@ -634,7 +652,7 @@ static NTSTATUS msrpc_lookup_groupmem(struct winbindd_domain *domain,
 
        *num_names = 0;
 
-       result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
+       result = cm_connect_sam(domain, mem_ctx, false, &cli, &dom_pol);
        if (!NT_STATUS_IS_OK(result))
                return result;
 
@@ -699,9 +717,9 @@ static NTSTATUS msrpc_lookup_groupmem(struct winbindd_domain *domain,
 
 #define MAX_LOOKUP_RIDS 900
 
-        *names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_names);
-        *name_types = TALLOC_ZERO_ARRAY(mem_ctx, uint32, *num_names);
-        *sid_mem = TALLOC_ZERO_ARRAY(mem_ctx, struct dom_sid, *num_names);
+        *names = talloc_zero_array(mem_ctx, char *, *num_names);
+        *name_types = talloc_zero_array(mem_ctx, uint32_t, *num_names);
+        *sid_mem = talloc_zero_array(mem_ctx, struct dom_sid, *num_names);
 
        for (j=0;j<(*num_names);j++)
                sid_compose(&(*sid_mem)[j], &domain->sid, rid_mem[j]);
@@ -737,14 +755,20 @@ static NTSTATUS msrpc_lookup_groupmem(struct winbindd_domain *domain,
                /* Copy result into array.  The talloc system will take
                   care of freeing the temporary arrays later on. */
 
-               if (tmp_names.count != tmp_types.count) {
-                       return NT_STATUS_UNSUCCESSFUL;
+               if (tmp_names.count != num_lookup_rids) {
+                       return NT_STATUS_INVALID_NETWORK_RESPONSE;
+               }
+               if (tmp_types.count != num_lookup_rids) {
+                       return NT_STATUS_INVALID_NETWORK_RESPONSE;
                }
 
                for (r=0; r<tmp_names.count; r++) {
                        if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
                                continue;
                        }
+                       if (total_names >= *num_names) {
+                               break;
+                       }
                        (*names)[total_names] = fill_domain_username_talloc(
                                mem_ctx, domain->name,
                                tmp_names.names[r].string, true);
@@ -760,9 +784,9 @@ static NTSTATUS msrpc_lookup_groupmem(struct winbindd_domain *domain,
 
 #ifdef HAVE_LDAP
 
-#include <ldap.h>
+#include "ads.h"
 
-static int get_ldap_seq(const char *server, int port, uint32 *seq)
+static int get_ldap_seq(const char *server, struct sockaddr_storage *ss, int port, uint32_t *seq)
 {
        int ret = -1;
        struct timeval to;
@@ -778,7 +802,7 @@ static int get_ldap_seq(const char *server, int port, uint32 *seq)
         * search timeout doesn't seem to apply to doing an open as well. JRA.
         */
 
-       ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout());
+       ldp = ldap_open_with_timeout(server, ss, port, lp_ldap_timeout());
        if (ldp == NULL)
                return -1;
 
@@ -787,7 +811,7 @@ static int get_ldap_seq(const char *server, int port, uint32 *seq)
        to.tv_usec = 0;
 
        if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)",
-                          CONST_DISCARD(char **, attrs), 0, &to, &res))
+                          discard_const_p(char *, attrs), 0, &to, &res))
                goto done;
 
        if (ldap_count_entries(ldp, res) != 1)
@@ -816,13 +840,13 @@ static int get_ldap_seq(const char *server, int port, uint32 *seq)
  LDAP queries.
 **********************************************************************/
 
-static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
+static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32_t *seq)
 {
        int ret = -1;
        char addr[INET6_ADDRSTRLEN];
 
        print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
-       if ((ret = get_ldap_seq(addr, LDAP_PORT, seq)) == 0) {
+       if ((ret = get_ldap_seq(addr, &domain->dcaddr, LDAP_PORT, seq)) == 0) {
                DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
                          "number for Domain (%s) from DC (%s)\n",
                        domain->name, addr));
@@ -838,7 +862,7 @@ static NTSTATUS msrpc_sequence_number(struct winbindd_domain *domain,
 {
        struct rpc_pipe_client *samr_pipe;
        struct policy_handle dom_pol;
-       uint32_t seq;
+       uint32_t seq = DOM_SEQUENCE_NONE;
        TALLOC_CTX *tmp_ctx;
        NTSTATUS status;
 
@@ -890,7 +914,7 @@ static NTSTATUS msrpc_sequence_number(struct winbindd_domain *domain,
        }
 #endif /* HAVE_LDAP */
 
-       status = cm_connect_sam(domain, tmp_ctx, &samr_pipe, &dom_pol);
+       status = cm_connect_sam(domain, tmp_ctx, false, &samr_pipe, &dom_pol);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -937,8 +961,9 @@ static NTSTATUS msrpc_trusted_domains(struct winbindd_domain *domain,
        }
 
        status = cm_connect_lsa(domain, tmp_ctx, &lsa_pipe, &lsa_policy);
-       if (!NT_STATUS_IS_OK(status))
-               return status;
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
 
        status = rpc_trusted_domains(tmp_ctx,
                                     lsa_pipe,
@@ -978,7 +1003,7 @@ static NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
                return NT_STATUS_NOT_SUPPORTED;
        }
 
-       status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
+       status = cm_connect_sam(domain, mem_ctx, false, &cli, &dom_pol);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -1028,7 +1053,7 @@ static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
                return NT_STATUS_NOT_SUPPORTED;
        }
 
-       status = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
+       status = cm_connect_sam(domain, mem_ctx, false, &cli, &dom_pol);
        if (!NT_STATUS_IS_OK(status)) {
                goto done;
        }
@@ -1057,15 +1082,6 @@ static NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
        return status;
 }
 
-typedef NTSTATUS (*lookup_sids_fn_t)(struct rpc_pipe_client *cli,
-                                    TALLOC_CTX *mem_ctx,
-                                    struct policy_handle *pol,
-                                    int num_sids,
-                                    const struct dom_sid *sids,
-                                    char ***pdomains,
-                                    char ***pnames,
-                                    enum lsa_SidType **ptypes);
-
 NTSTATUS winbindd_lookup_sids(TALLOC_CTX *mem_ctx,
                              struct winbindd_domain *domain,
                              uint32_t num_sids,
@@ -1075,54 +1091,62 @@ NTSTATUS winbindd_lookup_sids(TALLOC_CTX *mem_ctx,
                              enum lsa_SidType **types)
 {
        NTSTATUS status;
+       NTSTATUS result;
        struct rpc_pipe_client *cli = NULL;
+       struct dcerpc_binding_handle *b = NULL;
        struct policy_handle lsa_policy;
        unsigned int orig_timeout;
-       lookup_sids_fn_t lookup_sids_fn = rpccli_lsa_lookup_sids;
-
-       if (domain->can_do_ncacn_ip_tcp) {
-               status = cm_connect_lsa_tcp(domain, mem_ctx, &cli);
-               if (NT_STATUS_IS_OK(status)) {
-                       lookup_sids_fn = rpccli_lsa_lookup_sids3;
-                       goto lookup;
-               }
-               domain->can_do_ncacn_ip_tcp = false;
-       }
-       status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
+       bool use_lookupsids3 = false;
+       bool retried = false;
 
+ connect:
+       status = cm_connect_lsat(domain, mem_ctx, &cli, &lsa_policy);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
- lookup:
+       b = cli->binding_handle;
+
+       if (cli->transport->transport == NCACN_IP_TCP) {
+               use_lookupsids3 = true;
+       }
+
        /*
         * This call can take a long time
         * allow the server to time out.
         * 35 seconds should do it.
         */
-       orig_timeout = rpccli_set_timeout(cli, 35000);
-
-       status = lookup_sids_fn(cli,
-                               mem_ctx,
-                               &lsa_policy,
-                               num_sids,
-                               sids,
-                               domains,
-                               names,
-                               types);
+       orig_timeout = dcerpc_binding_handle_set_timeout(b, 35000);
+
+       status = dcerpc_lsa_lookup_sids_generic(b,
+                                               mem_ctx,
+                                               &lsa_policy,
+                                               num_sids,
+                                               sids,
+                                               domains,
+                                               names,
+                                               types,
+                                               use_lookupsids3,
+                                               &result);
 
        /* And restore our original timeout. */
-       rpccli_set_timeout(cli, orig_timeout);
+       dcerpc_binding_handle_set_timeout(b, orig_timeout);
 
-       if (NT_STATUS_V(status) == DCERPC_FAULT_ACCESS_DENIED ||
-           NT_STATUS_V(status) == DCERPC_FAULT_SEC_PKG_ERROR) {
+       if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
+           NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
+           NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
                /*
                 * This can happen if the schannel key is not
                 * valid anymore, we need to invalidate the
                 * all connections to the dc and reestablish
                 * a netlogon connection first.
                 */
-               invalidate_cm_connection(&domain->conn);
+               invalidate_cm_connection(domain);
+               domain->can_do_ncacn_ip_tcp = domain->active_directory;
+               if (!retried) {
+                       retried = true;
+                       goto connect;
+               }
                status = NT_STATUS_ACCESS_DENIED;
        }
 
@@ -1130,78 +1154,78 @@ NTSTATUS winbindd_lookup_sids(TALLOC_CTX *mem_ctx,
                return status;
        }
 
-       return status;
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
+       }
+
+       return NT_STATUS_OK;
 }
 
-typedef NTSTATUS (*lookup_names_fn_t)(struct rpc_pipe_client *cli,
-                                     TALLOC_CTX *mem_ctx,
-                                     struct policy_handle *pol,
-                                     int num_names,
+static NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
+                                     struct winbindd_domain *domain,
+                                     uint32_t num_names,
                                      const char **names,
-                                     const char ***dom_names,
-                                     int level,
+                                     const char ***domains,
                                      struct dom_sid **sids,
-                                     enum lsa_SidType **types);
-
-NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
-                              struct winbindd_domain *domain,
-                              uint32_t num_names,
-                              const char **names,
-                              const char ***domains,
-                              struct dom_sid **sids,
-                              enum lsa_SidType **types)
+                                     enum lsa_SidType **types)
 {
        NTSTATUS status;
+       NTSTATUS result;
        struct rpc_pipe_client *cli = NULL;
+       struct dcerpc_binding_handle *b = NULL;
        struct policy_handle lsa_policy;
        unsigned int orig_timeout = 0;
-       lookup_names_fn_t lookup_names_fn = rpccli_lsa_lookup_names;
-
-       if (domain->can_do_ncacn_ip_tcp) {
-               status = cm_connect_lsa_tcp(domain, mem_ctx, &cli);
-               if (NT_STATUS_IS_OK(status)) {
-                       lookup_names_fn = rpccli_lsa_lookup_names4;
-                       goto lookup;
-               }
-               domain->can_do_ncacn_ip_tcp = false;
-       }
-       status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
+       bool use_lookupnames4 = false;
+       bool retried = false;
 
+ connect:
+       status = cm_connect_lsat(domain, mem_ctx, &cli, &lsa_policy);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
- lookup:
+       b = cli->binding_handle;
+
+       if (cli->transport->transport == NCACN_IP_TCP) {
+               use_lookupnames4 = true;
+       }
 
        /*
         * This call can take a long time
         * allow the server to time out.
         * 35 seconds should do it.
         */
-       orig_timeout = rpccli_set_timeout(cli, 35000);
-
-       status = lookup_names_fn(cli,
-                                mem_ctx,
-                                &lsa_policy,
-                                num_names,
-                                (const char **) names,
-                                domains,
-                                1,
-                                sids,
-                                types);
+       orig_timeout = dcerpc_binding_handle_set_timeout(b, 35000);
+
+       status = dcerpc_lsa_lookup_names_generic(b,
+                                                mem_ctx,
+                                                &lsa_policy,
+                                                num_names,
+                                                (const char **) names,
+                                                domains,
+                                                1,
+                                                sids,
+                                                types,
+                                                use_lookupnames4,
+                                                &result);
 
        /* And restore our original timeout. */
-       rpccli_set_timeout(cli, orig_timeout);
+       dcerpc_binding_handle_set_timeout(b, orig_timeout);
 
-       if (NT_STATUS_V(status) == DCERPC_FAULT_ACCESS_DENIED ||
-           NT_STATUS_V(status) == DCERPC_FAULT_SEC_PKG_ERROR) {
+       if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
+           NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR) ||
+           NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
                /*
                 * This can happen if the schannel key is not
                 * valid anymore, we need to invalidate the
                 * all connections to the dc and reestablish
                 * a netlogon connection first.
                 */
-               invalidate_cm_connection(&domain->conn);
+               invalidate_cm_connection(domain);
+               if (!retried) {
+                       retried = true;
+                       goto connect;
+               }
                status = NT_STATUS_ACCESS_DENIED;
        }
 
@@ -1209,7 +1233,11 @@ NTSTATUS winbindd_lookup_names(TALLOC_CTX *mem_ctx,
                return status;
        }
 
-       return status;
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
+       }
+
+       return NT_STATUS_OK;
 }
 
 /* the rpc backend methods are exposed via this structure */