pdb_samba_dsdb: implement pdb_samba_dsdb_enum_trusteddoms()
[bbaumbach/samba-autobuild/.git] / source3 / passdb / pdb_samba_dsdb.c
index 6b99d8204a0e46686e1bed70b035d125b2d58b16..d70a867505d564edbdfdd60180fad1d63adeaac8 100644 (file)
@@ -39,6 +39,7 @@
 #include "source3/include/secrets.h"
 #include "source4/auth/auth_sam.h"
 #include "auth/credentials/credentials.h"
+#include "lib/util/base64.h"
 
 struct pdb_samba_dsdb_state {
        struct tevent_context *ev;
@@ -365,7 +366,7 @@ static int pdb_samba_dsdb_replace_by_sam(struct pdb_samba_dsdb_state *state,
        /* If we set a plaintext password, the system will
         * force the pwdLastSet to now() */
        if (need_update(sam, PDB_PASSLASTSET)) {
-               dsdb_flags = DSDB_PASSWORD_BYPASS_LAST_SET;
+               dsdb_flags |= DSDB_PASSWORD_BYPASS_LAST_SET;
 
                ret |= pdb_samba_dsdb_add_time(msg, "pwdLastSet",
                                           pdb_get_pass_last_set_time(sam));
@@ -442,10 +443,10 @@ static int pdb_samba_dsdb_replace_by_sam(struct pdb_samba_dsdb_state *state,
                                invalid_history = true;
                        } else {
                                unsigned int i;
-                               static const uint8_t zeros[16];
                                /* Parse the history into the correct format */
                                for (i = 0; i < current_hist_len; i++) {
-                                       if (memcmp(&history[i*PW_HISTORY_ENTRY_LEN], zeros, 16) != 0) {
+                                       if (!all_zero(&history[i*PW_HISTORY_ENTRY_LEN],
+                                                     16)) {
                                                /* If the history is in the old format, with a salted hash, then we can't migrate it to AD format */
                                                invalid_history = true;
                                                break;
@@ -472,7 +473,7 @@ static int pdb_samba_dsdb_replace_by_sam(struct pdb_samba_dsdb_state *state,
                }
                if (changed_lm_pw || changed_nt_pw || changed_history) {
                        /* These attributes can only be modified directly by using a special control */
-                       dsdb_flags = DSDB_BYPASS_PASSWORD_HASH;
+                       dsdb_flags |= DSDB_BYPASS_PASSWORD_HASH;
                }
        }
 
@@ -659,7 +660,13 @@ static NTSTATUS pdb_samba_dsdb_getsamupriv(struct pdb_samba_dsdb_state *state,
 static NTSTATUS pdb_samba_dsdb_getsampwfilter(struct pdb_methods *m,
                                          struct pdb_samba_dsdb_state *state,
                                          struct samu *sam_acct,
-                                         const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
+                                         const char *exp_fmt, ...)
+                                         PRINTF_ATTRIBUTE(4,5);
+
+static NTSTATUS pdb_samba_dsdb_getsampwfilter(struct pdb_methods *m,
+                                         struct pdb_samba_dsdb_state *state,
+                                         struct samu *sam_acct,
+                                         const char *exp_fmt, ...)
 {
        struct ldb_message *priv;
        NTSTATUS status;
@@ -884,8 +891,13 @@ static NTSTATUS pdb_samba_dsdb_update_login_attempts(struct pdb_methods *m,
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
+static NTSTATUS pdb_samba_dsdb_getgrfilter(struct pdb_methods *m,
+                                          GROUP_MAP *map,
+                                          const char *exp_fmt, ...)
+                                          PRINTF_ATTRIBUTE(3,4);
+
 static NTSTATUS pdb_samba_dsdb_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
-                                   const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
+                                   const char *exp_fmt, ...)
 {
        struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
                m->private_data, struct pdb_samba_dsdb_state);
@@ -1013,7 +1025,7 @@ static NTSTATUS pdb_samba_dsdb_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
                return NT_STATUS_NO_MEMORY;
        }
 
-       status = pdb_samba_dsdb_getgrfilter(m, map, filter);
+       status = pdb_samba_dsdb_getgrfilter(m, map, "%s", filter);
        TALLOC_FREE(filter);
        return status;
 }
@@ -1057,7 +1069,7 @@ static NTSTATUS pdb_samba_dsdb_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
                return NT_STATUS_NO_MEMORY;
        }
 
-       status = pdb_samba_dsdb_getgrfilter(m, map, filter);
+       status = pdb_samba_dsdb_getgrfilter(m, map, "%s", filter);
        TALLOC_FREE(filter);
        return status;
 }
@@ -1896,10 +1908,16 @@ static void pdb_samba_dsdb_search_end(struct pdb_search *search)
        talloc_free(state);
 }
 
+static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
+                                        struct pdb_search *search,
+                                        struct pdb_samba_dsdb_search_state **pstate,
+                                        const char *exp_fmt, ...)
+                                        PRINTF_ATTRIBUTE(4, 5);
+
 static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
                                     struct pdb_search *search,
                                     struct pdb_samba_dsdb_search_state **pstate,
-                                    const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
+                                    const char *exp_fmt, ...)
 {
        struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
                m->private_data, struct pdb_samba_dsdb_state);
@@ -2157,15 +2175,16 @@ static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
        const char *netbios_domain = NULL;
        const struct dom_sid *domain_sid = NULL;
 
-       status = sam_get_results_trust(state->ldb, tmp_ctx, domain,
-                                      NULL, attrs, &msg);
+       status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
+                                      attrs, tmp_ctx, &msg);
        if (!NT_STATUS_IS_OK(status)) {
                /*
                 * This can be called to work out of a domain is
                 * trusted, rather than just to get the password
                 */
-               DEBUG(2, ("Failed to get trusted domain password for %s.  "
-                         "It may not be a trusted domain.\n", domain));
+               DEBUG(2, ("Failed to get trusted domain password for %s - %s.  "
+                         "It may not be a trusted domain.\n", domain,
+                         nt_errstr(status)));
                TALLOC_FREE(tmp_ctx);
                return false;
        }
@@ -2317,17 +2336,18 @@ static NTSTATUS pdb_samba_dsdb_get_trusteddom_creds(struct pdb_methods *m,
        char *principal_name = NULL;
        const char *dns_domain = NULL;
 
-       status = sam_get_results_trust(state->ldb, tmp_ctx, domain,
-                                      NULL, attrs, &msg);
+       status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
+                                      attrs, tmp_ctx, &msg);
        if (!NT_STATUS_IS_OK(status)) {
                /*
                 * This can be called to work out of a domain is
                 * trusted, rather than just to get the password
                 */
-               DEBUG(2, ("Failed to get trusted domain password for %s.  "
-                         "It may not be a trusted domain.\n", domain));
+               DEBUG(2, ("Failed to get trusted domain password for %s - %s "
+                         "It may not be a trusted domain.\n", domain,
+                         nt_errstr(status)));
                TALLOC_FREE(tmp_ctx);
-               return status;
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
        }
 
        netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
@@ -2612,15 +2632,16 @@ static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m,
                return false;
        }
 
-       status = sam_get_results_trust(state->ldb, tmp_ctx, domain,
-                                      NULL, attrs, &msg);
+       status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
+                                      attrs, tmp_ctx, &msg);
        if (!NT_STATUS_IS_OK(status)) {
                /*
                 * This can be called to work out of a domain is
                 * trusted, rather than just to get the password
                 */
-               DEBUG(2, ("Failed to get trusted domain password for %s.  "
-                         "It may not be a trusted domain.\n", domain));
+               DEBUG(2, ("Failed to get trusted domain password for %s - %s.  "
+                         "It may not be a trusted domain.\n", domain,
+                         nt_errstr(status)));
                TALLOC_FREE(tmp_ctx);
                ldb_transaction_cancel(state->ldb);
                return false;
@@ -2857,11 +2878,89 @@ static bool pdb_samba_dsdb_del_trusteddom_pw(struct pdb_methods *m,
 
 static NTSTATUS pdb_samba_dsdb_enum_trusteddoms(struct pdb_methods *m,
                                         TALLOC_CTX *mem_ctx,
-                                        uint32_t *num_domains,
-                                        struct trustdom_info ***domains)
+                                        uint32_t *_num_domains,
+                                        struct trustdom_info ***_domains)
 {
-       *num_domains = 0;
-       *domains = NULL;
+       struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
+               m->private_data, struct pdb_samba_dsdb_state);
+       TALLOC_CTX *tmp_ctx = talloc_stackframe();
+       const char * const attrs[] = {
+               "securityIdentifier",
+               "flatName",
+               "trustDirection",
+               NULL
+       };
+       struct ldb_result *res = NULL;
+       unsigned int i;
+       struct trustdom_info **domains = NULL;
+       NTSTATUS status;
+       uint32_t di = 0;
+
+       *_num_domains = 0;
+       *_domains = NULL;
+
+       status = dsdb_trust_search_tdos(state->ldb, NULL,
+                                       attrs, tmp_ctx, &res);
+       if (!NT_STATUS_IS_OK(status)) {
+               DBG_ERR("dsdb_trust_search_tdos() - %s ", nt_errstr(status));
+               TALLOC_FREE(tmp_ctx);
+               return status;
+       }
+
+       if (res->count == 0) {
+               TALLOC_FREE(tmp_ctx);
+               return NT_STATUS_OK;
+       }
+
+       domains = talloc_zero_array(tmp_ctx, struct trustdom_info *,
+                                   res->count);
+       if (domains == NULL) {
+               TALLOC_FREE(tmp_ctx);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i = 0; i < res->count; i++) {
+               struct ldb_message *msg = res->msgs[i];
+               struct trustdom_info *d = NULL;
+               const char *name = NULL;
+               struct dom_sid *sid = NULL;
+               uint32_t direction;
+
+               d = talloc_zero(domains, struct trustdom_info);
+               if (d == NULL) {
+                       TALLOC_FREE(tmp_ctx);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               name = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
+               if (name == NULL) {
+                       TALLOC_FREE(tmp_ctx);
+                       return NT_STATUS_INTERNAL_DB_CORRUPTION;
+               }
+               sid = samdb_result_dom_sid(msg, msg, "securityIdentifier");
+               if (sid == NULL) {
+                       continue;
+               }
+
+               direction = ldb_msg_find_attr_as_uint(msg, "trustDirection", 0);
+               if (!(direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
+                       continue;
+               }
+
+               d->name = talloc_strdup(d, name);
+               if (d->name == NULL) {
+                       TALLOC_FREE(tmp_ctx);
+                       return NT_STATUS_NO_MEMORY;
+               }
+               d->sid = *sid;
+
+               domains[di++] = d;
+       }
+
+       talloc_realloc(domains, domains, struct trustdom_info *, di);
+       *_domains = talloc_move(mem_ctx, &domains);
+       *_num_domains = di;
+       TALLOC_FREE(tmp_ctx);
        return NT_STATUS_OK;
 }
 
@@ -3002,6 +3101,8 @@ static NTSTATUS pdb_init_samba_dsdb(struct pdb_methods **pdb_method,
        struct pdb_methods *m;
        struct pdb_samba_dsdb_state *state;
        NTSTATUS status;
+       char *errstring = NULL;
+       int ret;
 
        if ( !NT_STATUS_IS_OK(status = make_pdb_method( &m )) ) {
                return status;
@@ -3027,21 +3128,20 @@ static NTSTATUS pdb_init_samba_dsdb(struct pdb_methods **pdb_method,
                goto nomem;
        }
 
-       if (location) {
-               state->ldb = samdb_connect_url(state,
-                                  state->ev,
-                                  state->lp_ctx,
-                                  system_session(state->lp_ctx),
-                                  0, location);
-       } else {
-               state->ldb = samdb_connect(state,
-                                  state->ev,
-                                  state->lp_ctx,
-                                  system_session(state->lp_ctx), 0);
+       if (location == NULL) {
+               location = "sam.ldb";
        }
 
+       ret = samdb_connect_url(state,
+                               state->ev,
+                               state->lp_ctx,
+                               system_session(state->lp_ctx),
+                               0, location,
+                               &state->ldb, &errstring);
+
        if (!state->ldb) {
-               DEBUG(0, ("samdb_connect failed\n"));
+               DEBUG(0, ("samdb_connect failed: %s: %s\n",
+                         errstring, ldb_strerror(ret)));
                status = NT_STATUS_INTERNAL_ERROR;
                goto fail;
        }
@@ -3069,8 +3169,8 @@ fail:
        return status;
 }
 
-NTSTATUS pdb_samba_dsdb_init(void);
-NTSTATUS pdb_samba_dsdb_init(void)
+NTSTATUS pdb_samba_dsdb_init(TALLOC_CTX *);
+NTSTATUS pdb_samba_dsdb_init(TALLOC_CTX *ctx)
 {
        NTSTATUS status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba_dsdb",
                                              pdb_init_samba_dsdb);