Implement pdb_ads_delete_dom_group
[ira/wip.git] / source3 / passdb / pdb_ads.c
index 26bf176aaf6a2f24de99bee48507000ad35a36e6..45aab1c3df5ef30a7aae4e3c65d47f47ad14ada1 100644 (file)
@@ -24,6 +24,8 @@ static NTSTATUS pdb_ads_getsampwsid(struct pdb_methods *m,
                                    const DOM_SID *sid);
 static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
                               DOM_SID *sid);
+static bool pdb_ads_dnblob2sid(struct tldap_context *ld, DATA_BLOB *dnblob,
+                              struct dom_sid *psid);
 
 
 struct pdb_ads_state {
@@ -266,7 +268,7 @@ static bool pdb_ads_init_ads_from_sam(struct pdb_ads_state *state,
 
        ret &= tldap_make_mod_fmt(
                existing, mem_ctx, pnum_mods, pmods, "displayName",
-               pdb_get_fullname(sam));
+               "%s", pdb_get_fullname(sam));
 
        ret &= tldap_make_mod_blob(
                existing, mem_ctx, pnum_mods, pmods, "unicodePwd",
@@ -512,7 +514,7 @@ static NTSTATUS pdb_ads_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
        }
        if (talloc_array_length(group) != 1) {
                DEBUG(10, ("Expected 1 user, got %d\n",
-                          talloc_array_length(group)));
+                          (int)talloc_array_length(group)));
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
 
@@ -679,7 +681,53 @@ static NTSTATUS pdb_ads_create_dom_group(struct pdb_methods *m,
 static NTSTATUS pdb_ads_delete_dom_group(struct pdb_methods *m,
                                         TALLOC_CTX *mem_ctx, uint32 rid)
 {
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct pdb_ads_state *state = talloc_get_type_abort(
+               m->private_data, struct pdb_ads_state);
+       struct dom_sid sid;
+       char *sidstr;
+       struct tldap_message **msg;
+       char *dn;
+       int rc;
+
+       sid_compose(&sid, &state->domainsid, rid);
+
+       sidstr = sid_binstring(talloc_tos(), &sid);
+       NT_STATUS_HAVE_NO_MEMORY(sidstr);
+
+       rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
+                             NULL, 0, 0, talloc_tos(), &msg,
+                             ("(&(objectSid=%s)(objectClass=group))"),
+                             sidstr);
+       TALLOC_FREE(sidstr);
+       if (rc != TLDAP_SUCCESS) {
+               DEBUG(10, ("ldap_search failed %s\n",
+                          tldap_errstr(debug_ctx(), state->ld, rc)));
+               return NT_STATUS_LDAP(rc);
+       }
+
+       switch talloc_array_length(msg) {
+       case 0:
+               return NT_STATUS_NO_SUCH_GROUP;
+       case 1:
+               break;
+       default:
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+
+       if (!tldap_entry_dn(msg[0], &dn)) {
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+
+       rc = tldap_delete(state->ld, dn, NULL, NULL);
+       if (rc != TLDAP_SUCCESS) {
+               DEBUG(10, ("ldap_delete failed: %s\n",
+                          tldap_errstr(debug_ctx(), state->ld, rc)));
+               TALLOC_FREE(dn);
+               return NT_STATUS_LDAP(rc);
+       }
+
+       TALLOC_FREE(msg);
+       return NT_STATUS_OK;
 }
 
 static NTSTATUS pdb_ads_add_group_mapping_entry(struct pdb_methods *m,
@@ -713,10 +761,62 @@ static NTSTATUS pdb_ads_enum_group_mapping(struct pdb_methods *m,
 static NTSTATUS pdb_ads_enum_group_members(struct pdb_methods *m,
                                           TALLOC_CTX *mem_ctx,
                                           const DOM_SID *group,
-                                          uint32 **pp_member_rids,
-                                          size_t *p_num_members)
+                                          uint32 **pmembers,
+                                          size_t *pnum_members)
 {
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct pdb_ads_state *state = talloc_get_type_abort(
+               m->private_data, struct pdb_ads_state);
+       const char *attrs[1] = { "member" };
+       char *sidstr;
+       struct tldap_message **msg;
+       int i, rc, num_members;
+       DATA_BLOB *blobs;
+       uint32_t *members;
+
+       sidstr = sid_binstring(talloc_tos(), group);
+       NT_STATUS_HAVE_NO_MEMORY(sidstr);
+
+       rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
+                             attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &msg,
+                             "(objectsid=%s)", sidstr);
+       TALLOC_FREE(sidstr);
+       if (rc != TLDAP_SUCCESS) {
+               DEBUG(10, ("ldap_search failed %s\n",
+                          tldap_errstr(debug_ctx(), state->ld, rc)));
+               return NT_STATUS_LDAP(rc);
+       }
+       switch talloc_array_length(msg) {
+       case 0:
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+               break;
+       case 1:
+               break;
+       default:
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+               break;
+       }
+
+       if (!tldap_entry_values(msg[0], "member", &num_members, &blobs)) {
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+
+       members = talloc_array(mem_ctx, uint32_t, num_members);
+       if (members == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i=0; i<num_members; i++) {
+               struct dom_sid sid;
+               if (!pdb_ads_dnblob2sid(state->ld, &blobs[i], &sid)
+                   || !sid_peek_rid(&sid, &members[i])) {
+                       TALLOC_FREE(members);
+                       return NT_STATUS_INTERNAL_DB_CORRUPTION;
+               }
+       }
+
+       *pmembers = members;
+       *pnum_members = num_members;
+       return NT_STATUS_OK;
 }
 
 static NTSTATUS pdb_ads_enum_group_memberships(struct pdb_methods *m,
@@ -878,7 +978,50 @@ static NTSTATUS pdb_ads_create_alias(struct pdb_methods *m,
 static NTSTATUS pdb_ads_delete_alias(struct pdb_methods *m,
                                     const DOM_SID *sid)
 {
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct pdb_ads_state *state = talloc_get_type_abort(
+               m->private_data, struct pdb_ads_state);
+       struct tldap_message **alias;
+       char *sidstr, *dn;
+       int rc;
+
+       sidstr = sid_binstring(talloc_tos(), sid);
+       if (sidstr == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
+                             NULL, 0, 0, talloc_tos(), &alias,
+                             "(&(objectSid=%s)(objectclass=group)"
+                             "(|(grouptype=%d)(grouptype=%d)))",
+                             sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
+                             GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
+       TALLOC_FREE(sidstr);
+       if (rc != TLDAP_SUCCESS) {
+               DEBUG(10, ("ldap_search failed: %s\n",
+                          tldap_errstr(debug_ctx(), state->ld, rc)));
+               TALLOC_FREE(dn);
+               return NT_STATUS_LDAP(rc);
+       }
+       if (talloc_array_length(alias) != 1) {
+               DEBUG(10, ("Expected 1 alias, got %d\n",
+                          (int)talloc_array_length(alias)));
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+       if (!tldap_entry_dn(alias[0], &dn)) {
+               DEBUG(10, ("Could not get DN for alias %s\n",
+                          sid_string_dbg(sid)));
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+
+       rc = tldap_delete(state->ld, dn, NULL, NULL);
+       if (rc != TLDAP_SUCCESS) {
+               DEBUG(10, ("ldap_delete failed: %s\n",
+                          tldap_errstr(debug_ctx(), state->ld, rc)));
+               TALLOC_FREE(dn);
+               return NT_STATUS_LDAP(rc);
+       }
+
+       return NT_STATUS_OK;
 }
 
 static NTSTATUS pdb_ads_get_aliasinfo(struct pdb_methods *m,
@@ -895,25 +1038,205 @@ static NTSTATUS pdb_ads_set_aliasinfo(struct pdb_methods *m,
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
+static NTSTATUS pdb_ads_sid2dn(struct pdb_ads_state *state,
+                              const struct dom_sid *sid,
+                              TALLOC_CTX *mem_ctx, char **pdn)
+{
+       struct tldap_message **msg;
+       char *sidstr, *dn;
+       int rc;
+
+       sidstr = sid_binstring(talloc_tos(), sid);
+       NT_STATUS_HAVE_NO_MEMORY(sidstr);
+
+       rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
+                             NULL, 0, 0, talloc_tos(), &msg,
+                             "(objectsid=%s)", sidstr);
+       TALLOC_FREE(sidstr);
+       if (rc != TLDAP_SUCCESS) {
+               DEBUG(10, ("ldap_search failed %s\n",
+                          tldap_errstr(debug_ctx(), state->ld, rc)));
+               return NT_STATUS_LDAP(rc);
+       }
+
+       switch talloc_array_length(msg) {
+       case 0:
+               return NT_STATUS_NOT_FOUND;
+       case 1:
+               break;
+       default:
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+
+       if (!tldap_entry_dn(msg[0], &dn)) {
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+
+       dn = talloc_strdup(mem_ctx, dn);
+       if (dn == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       TALLOC_FREE(msg);
+
+       *pdn = dn;
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_ads_mod_aliasmem(struct pdb_methods *m,
+                                    const DOM_SID *alias,
+                                    const DOM_SID *member,
+                                    int mod_op)
+{
+       struct pdb_ads_state *state = talloc_get_type_abort(
+               m->private_data, struct pdb_ads_state);
+       TALLOC_CTX *frame = talloc_stackframe();
+       struct tldap_mod *mods;
+       int rc;
+       char *aliasdn, *memberdn;
+       NTSTATUS status;
+
+       status = pdb_ads_sid2dn(state, alias, talloc_tos(), &aliasdn);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
+                          sid_string_dbg(alias), nt_errstr(status)));
+               TALLOC_FREE(frame);
+               return NT_STATUS_NO_SUCH_ALIAS;
+       }
+       status = pdb_ads_sid2dn(state, member, talloc_tos(), &memberdn);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
+                          sid_string_dbg(member), nt_errstr(status)));
+               TALLOC_FREE(frame);
+               return status;
+       }
+
+       mods = NULL;
+
+       if (!tldap_add_mod_str(talloc_tos(), &mods, mod_op,
+                              "member", memberdn)) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       rc = tldap_modify(state->ld, aliasdn, 1, mods, NULL, NULL);
+       TALLOC_FREE(frame);
+       if (rc != TLDAP_SUCCESS) {
+               DEBUG(10, ("ldap_modify failed: %s\n",
+                          tldap_errstr(debug_ctx(), state->ld, rc)));
+               if (rc == TLDAP_TYPE_OR_VALUE_EXISTS) {
+                       return NT_STATUS_MEMBER_IN_ALIAS;
+               }
+               if (rc == TLDAP_NO_SUCH_ATTRIBUTE) {
+                       return NT_STATUS_MEMBER_NOT_IN_ALIAS;
+               }
+               return NT_STATUS_LDAP(rc);
+       }
+
+       return NT_STATUS_OK;
+}
+
 static NTSTATUS pdb_ads_add_aliasmem(struct pdb_methods *m,
                                     const DOM_SID *alias,
                                     const DOM_SID *member)
 {
-       return NT_STATUS_NOT_IMPLEMENTED;
+       return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_ADD);
 }
 
 static NTSTATUS pdb_ads_del_aliasmem(struct pdb_methods *m,
                                     const DOM_SID *alias,
                                     const DOM_SID *member)
 {
-       return NT_STATUS_NOT_IMPLEMENTED;
+       return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_DELETE);
+}
+
+static bool pdb_ads_dnblob2sid(struct tldap_context *ld, DATA_BLOB *dnblob,
+                              struct dom_sid *psid)
+{
+       const char *attrs[1] = { "objectSid" };
+       struct tldap_message **msg;
+       char *dn;
+       size_t len;
+       int rc;
+       bool ret;
+
+       if (!convert_string_talloc(talloc_tos(), CH_UTF8, CH_UNIX,
+                                  dnblob->data, dnblob->length, &dn, &len,
+                                  false)) {
+               return false;
+       }
+       rc = tldap_search_fmt(ld, dn, TLDAP_SCOPE_BASE,
+                             attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
+                             &msg, "(objectclass=*)");
+       TALLOC_FREE(dn);
+       if (talloc_array_length(msg) != 1) {
+               DEBUG(10, ("Got %d objects, expected one\n",
+                          (int)talloc_array_length(msg)));
+               TALLOC_FREE(msg);
+               return false;
+       }
+
+       ret = tldap_pull_binsid(msg[0], "objectSid", psid);
+       TALLOC_FREE(msg);
+       return ret;
 }
 
 static NTSTATUS pdb_ads_enum_aliasmem(struct pdb_methods *m,
-                                     const DOM_SID *alias, DOM_SID **members,
-                                     size_t *p_num_members)
+                                     const DOM_SID *alias,
+                                     TALLOC_CTX *mem_ctx,
+                                     DOM_SID **pmembers,
+                                     size_t *pnum_members)
 {
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct pdb_ads_state *state = talloc_get_type_abort(
+               m->private_data, struct pdb_ads_state);
+       const char *attrs[1] = { "member" };
+       char *sidstr;
+       struct tldap_message **msg;
+       int i, rc, num_members;
+       DATA_BLOB *blobs;
+       struct dom_sid *members;
+
+       sidstr = sid_binstring(talloc_tos(), alias);
+       NT_STATUS_HAVE_NO_MEMORY(sidstr);
+
+       rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
+                             attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &msg,
+                             "(objectsid=%s)", sidstr);
+       TALLOC_FREE(sidstr);
+       if (rc != TLDAP_SUCCESS) {
+               DEBUG(10, ("ldap_search failed %s\n",
+                          tldap_errstr(debug_ctx(), state->ld, rc)));
+               return NT_STATUS_LDAP(rc);
+       }
+       switch talloc_array_length(msg) {
+       case 0:
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+               break;
+       case 1:
+               break;
+       default:
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+               break;
+       }
+
+       if (!tldap_entry_values(msg[0], "member", &num_members, &blobs)) {
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+
+       members = talloc_array(mem_ctx, struct dom_sid, num_members);
+       if (members == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i=0; i<num_members; i++) {
+               if (!pdb_ads_dnblob2sid(state->ld, &blobs[i], &members[i])) {
+                       TALLOC_FREE(members);
+                       return NT_STATUS_INTERNAL_DB_CORRUPTION;
+               }
+       }
+
+       *pmembers = members;
+       *pnum_members = num_members;
+       return NT_STATUS_OK;
 }
 
 static NTSTATUS pdb_ads_enum_alias_memberships(struct pdb_methods *m,