s3-idmap: convert most idmap_cache callers to unixid API
[kai/samba.git] / source3 / passdb / pdb_ads.c
index 48def7e44a63cd6ac7674cadc8aea7754a3639d1..f88ad75de7c876f827ce121cfa42ea3ba8e4c0e3 100644 (file)
 */
 
 #include "includes.h"
+#include "passdb.h"
 #include "tldap.h"
 #include "tldap_util.h"
 #include "../libds/common/flags.h"
 #include "secrets.h"
 #include "../librpc/gen_ndr/samr.h"
+#include "../librpc/gen_ndr/idmap.h"
 #include "../libcli/ldap/ldap_ndr.h"
 #include "../libcli/security/security.h"
+#include "../libds/common/flag_mapping.h"
 
 struct pdb_ads_state {
        struct sockaddr_un socket_address;
@@ -387,7 +390,7 @@ static bool pdb_ads_init_ads_from_sam(struct pdb_ads_state *state,
                ret &= convert_string_talloc(talloc_tos(),
                                             CH_UNIX, CH_UTF16LE,
                                             pw_quote, strlen(pw_quote),
-                                            &pw_utf16, &pw_utf16_len, false);
+                                            &pw_utf16, &pw_utf16_len);
                if (!ret) {
                        goto fail;
                }
@@ -796,16 +799,14 @@ static NTSTATUS pdb_ads_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
        if (str == NULL) {
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
-       fstrcpy(map->nt_name, str);
-       TALLOC_FREE(str);
+       map->nt_name = talloc_move(map, &str);
 
        str = tldap_talloc_single_attribute(group[0], "description",
                                            talloc_tos());
        if (str != NULL) {
-               fstrcpy(map->comment, str);
-               TALLOC_FREE(str);
+               map->comment = talloc_move(map, &str);
        } else {
-               map->comment[0] = '\0';
+               map->comment = talloc_strdup(map, "");
        }
 
        if (pmsg != NULL) {
@@ -1015,7 +1016,7 @@ static NTSTATUS pdb_ads_update_group_mapping_entry(struct pdb_methods *m,
        char *filter;
        struct tldap_message *existing;
        char *dn;
-       GROUP_MAP existing_map;
+       GROUP_MAP *existing_map;
        int rc, num_mods = 0;
        bool ret;
        NTSTATUS status;
@@ -1031,8 +1032,15 @@ static NTSTATUS pdb_ads_update_group_mapping_entry(struct pdb_methods *m,
        if (filter == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
-       status = pdb_ads_getgrfilter(m, &existing_map, filter,
+
+       existing_map = talloc_zero(talloc_tos(), GROUP_MAP);
+       if (!existing_map) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       status = pdb_ads_getgrfilter(m, existing_map, filter,
                                     talloc_tos(), &existing);
+       TALLOC_FREE(existing_map);
        TALLOC_FREE(filter);
 
        if (!tldap_entry_dn(existing, &dn)) {
@@ -1077,7 +1085,7 @@ static NTSTATUS pdb_ads_delete_group_mapping_entry(struct pdb_methods *m,
 static NTSTATUS pdb_ads_enum_group_mapping(struct pdb_methods *m,
                                           const struct dom_sid *sid,
                                           enum lsa_SidType sid_name_use,
-                                          GROUP_MAP **pp_rmap,
+                                          GROUP_MAP ***pp_rmap,
                                           size_t *p_num_entries,
                                           bool unix_only)
 {
@@ -1152,7 +1160,7 @@ static NTSTATUS pdb_ads_enum_group_memberships(struct pdb_methods *m,
                                               struct samu *user,
                                               struct dom_sid **pp_sids,
                                               gid_t **pp_gids,
-                                              size_t *p_num_groups)
+                                              uint32_t *p_num_groups)
 {
        struct pdb_ads_state *state = talloc_get_type_abort(
                m->private_data, struct pdb_ads_state);
@@ -1651,8 +1659,7 @@ static bool pdb_ads_dnblob2sid(struct pdb_ads_state *state, DATA_BLOB *dnblob,
        bool ret;
 
        if (!convert_string_talloc(talloc_tos(), CH_UTF8, CH_UNIX,
-                                  dnblob->data, dnblob->length, &dn, &len,
-                                  false)) {
+                                  dnblob->data, dnblob->length, &dn, &len)) {
                return false;
        }
        rc = pdb_ads_search_fmt(state, dn, TLDAP_SCOPE_BASE,
@@ -2198,50 +2205,69 @@ static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
 }
 
 static bool pdb_ads_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
-                             union unid_t *id, enum lsa_SidType *type)
+                             struct unixid *id)
 {
        struct pdb_ads_state *state = talloc_get_type_abort(
                m->private_data, struct pdb_ads_state);
+       const char *attrs[4] = { "objectClass", "samAccountType",
+                                "uidNumber", "gidNumber" };
        struct tldap_message **msg;
-       char *sidstr;
-       uint32_t rid;
+       char *sidstr, *base;
+       uint32_t atype;
        int rc;
+       bool ret = false;
 
-       /*
-        * This is a big, big hack: Just hard-code the rid as uid/gid.
-        */
+       id->id = -1;
+       id->type = ID_TYPE_NOT_SPECIFIED;
 
-       sid_peek_rid(sid, &rid);
-
-       sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
+       sidstr = sid_binstring_hex(sid);
        if (sidstr == NULL) {
                return false;
        }
+       base = talloc_asprintf(talloc_tos(), "<SID=%s>", sidstr);
+       SAFE_FREE(sidstr);
 
        rc = pdb_ads_search_fmt(
-               state, state->domaindn, TLDAP_SCOPE_SUB,
-               NULL, 0, 0, talloc_tos(), &msg,
-               "(&(objectsid=%s)(objectclass=user))", sidstr);
-       if ((rc == TLDAP_SUCCESS) && (talloc_array_length(msg) > 0)) {
-               id->uid = rid;
-               *type = SID_NAME_USER;
-               TALLOC_FREE(sidstr);
-               return true;
-       }
+               state, base, TLDAP_SCOPE_BASE,
+               attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &msg,
+               "(objectclass=*)");
+       TALLOC_FREE(base);
 
-       rc = pdb_ads_search_fmt(
-               state, state->domaindn, TLDAP_SCOPE_SUB,
-               NULL, 0, 0, talloc_tos(), &msg,
-               "(&(objectsid=%s)(objectclass=group))", sidstr);
-       if ((rc == TLDAP_SUCCESS) && (talloc_array_length(msg) > 0)) {
-               id->gid = rid;
-               *type = SID_NAME_DOM_GRP;
-               TALLOC_FREE(sidstr);
-               return true;
+       if (rc != TLDAP_SUCCESS) {
+               DEBUG(10, ("pdb_ads_search_fmt failed: %s\n",
+                          tldap_errstr(talloc_tos(), state->ld, rc)));
+               return false;
        }
-
-       TALLOC_FREE(sidstr);
-       return false;
+       if (talloc_array_length(msg) != 1) {
+               DEBUG(10, ("Got %d objects, expected 1\n",
+                          (int)talloc_array_length(msg)));
+               goto fail;
+       }
+       if (!tldap_pull_uint32(msg[0], "samAccountType", &atype)) {
+               DEBUG(10, ("samAccountType not found\n"));
+               goto fail;
+       }
+       if (atype == ATYPE_ACCOUNT) {
+               uid_t uid;
+               id->type = ID_TYPE_UID;
+               if (!tldap_pull_uint32(msg[0], "uidNumber", &uid)) {
+                       DEBUG(10, ("Did not find uidNumber\n"));
+                       goto fail;
+               }
+               id->id = uid;
+       } else {
+               gid_t gid;
+               id->type = ID_TYPE_GID;
+               if (!tldap_pull_uint32(msg[0], "gidNumber", gid)) {
+                       DEBUG(10, ("Did not find gidNumber\n"));
+                       goto fail;
+               }
+               id->id = gid;
+       }
+       ret = true;
+fail:
+       TALLOC_FREE(msg);
+       return ret;
 }
 
 static uint32_t pdb_ads_capabilities(struct pdb_methods *m)
@@ -2492,7 +2518,7 @@ static NTSTATUS pdb_ads_connect(struct pdb_ads_state *state,
 
        state->configdn = tldap_talloc_single_attribute(
                rootdse, "configurationNamingContext", state);
-       if (state->domaindn == NULL) {
+       if (state->configdn == NULL) {
                DEBUG(10, ("Could not get configurationNamingContext\n"));
                status = NT_STATUS_INTERNAL_DB_CORRUPTION;
                goto done;
@@ -2573,6 +2599,42 @@ done:
        return status;
 }
 
+static NTSTATUS pdb_ads_init_secrets(struct pdb_methods *m)
+{
+#if _SAMBA_BUILD_ == 4
+       struct pdb_domain_info *dom_info;
+       bool ret;
+
+       dom_info = pdb_ads_get_domain_info(m, m);
+       if (!dom_info) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       secrets_clear_domain_protection(dom_info->name);
+       ret = secrets_store_domain_sid(dom_info->name,
+                                      &dom_info->sid);
+       if (!ret) {
+               goto done;
+       }
+       ret = secrets_store_domain_guid(dom_info->name,
+                                       &dom_info->guid);
+       if (!ret) {
+               goto done;
+       }
+       ret = secrets_mark_domain_protected(dom_info->name);
+       if (!ret) {
+               goto done;
+       }
+
+done:
+       TALLOC_FREE(dom_info);
+       if (!ret) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+#endif
+       return NT_STATUS_OK;
+}
+
 static NTSTATUS pdb_init_ads(struct pdb_methods **pdb_method,
                             const char *location)
 {
@@ -2608,6 +2670,12 @@ static NTSTATUS pdb_init_ads(struct pdb_methods **pdb_method,
                goto fail;
        }
 
+       status = pdb_ads_init_secrets(m);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10, ("pdb_ads_init_secrets failed!\n"));
+               goto fail;
+       }
+
        *pdb_method = m;
        return NT_STATUS_OK;
 nomem: