Pass a talloc_ctx to pdb_enum_aliasmem
[ira/wip.git] / source3 / groupdb / mapping_ldb.c
index 21da363a530174f1a37a08352560bb2087fe8a7b..89966e1986e779c506e83a842f3577e682f42ac6 100644 (file)
  *  GNU General Public License for more details.
  *  
  *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "includes.h"
 #include "groupdb/mapping.h"
-#include "lib/ldb/include/includes.h"
+#include "lib/ldb/include/ldb.h"
 #include "lib/ldb/include/ldb_errors.h"
 
 static struct ldb_context *ldb;
 
-static BOOL mapping_upgrade(const char *tdb_path);
+static bool mapping_upgrade(const char *tdb_path);
 
 /*
   connect to the group mapping ldb
 */
-static BOOL init_group_mapping(void)
+static bool init_group_mapping(void)
 {
-       BOOL existed;
+       bool existed;
        const char *init_ldif[] = 
                { "dn: @ATTRIBUTES\n" \
                  "ntName: CASE_INSENSITIVE\n" \
@@ -56,12 +55,15 @@ static BOOL init_group_mapping(void)
        /* this is needed as Samba3 doesn't have this globally yet */
        ldb_global_init();
 
-       db_path = lock_path("group_mapping.ldb");
+       db_path = state_path("group_mapping.ldb");
 
-       ldb = ldb_init(NULL);
+       ldb = ldb_init(NULL, NULL);
        if (ldb == NULL) goto failed;
 
-       existed = file_exist(db_path, NULL);
+       /* Ensure this db is created read/write for root only. */
+       ldb_set_create_perms(ldb, 0600);
+
+       existed = file_exist(db_path);
 
        if (lp_parm_bool(-1, "groupmap", "nosync", False)) {
                flags |= LDB_FLG_NOSYNC;
@@ -75,7 +77,13 @@ static BOOL init_group_mapping(void)
        if (ret != LDB_SUCCESS) {
                goto failed;
        }
-       
+
+       /* force the permissions on the ldb to 0600 - this will fix
+          existing databases as well as new ones */
+       if (chmod(db_path, 0600) != 0) {
+               goto failed;
+       }
+
        if (!existed) {
                /* initialise the ldb with an index */
                struct ldb_ldif *ldif;
@@ -90,9 +98,9 @@ static BOOL init_group_mapping(void)
        }
 
        /* possibly upgrade */
-       tdb_path = lock_path("group_mapping.tdb");
-       if (file_exist(tdb_path, NULL) && !mapping_upgrade(tdb_path)) {
-               unlink(lock_path("group_mapping.ldb"));
+       tdb_path = state_path("group_mapping.tdb");
+       if (file_exist(tdb_path) && !mapping_upgrade(tdb_path)) {
+               unlink(state_path("group_mapping.ldb"));
                goto failed;
        }
 
@@ -120,19 +128,19 @@ static struct ldb_dn *mapping_dn(TALLOC_CTX *mem_ctx, const DOM_SID *sid)
        if (!sid_split_rid(&domsid, &rid)) {
                return NULL;
        }
-       if (!sid_to_string(string_sid, &domsid)) {
+       if (!sid_to_fstring(string_sid, &domsid)) {
                return NULL;
        }
        /* we split by domain and rid so we can do a subtree search
           when we only want one domain */
-       return ldb_dn_string_compose(mem_ctx, NULL, "rid=%u,domain=%s", 
-                                    rid, string_sid);
+       return ldb_dn_new_fmt(mem_ctx, ldb, "rid=%u,domain=%s", 
+                             rid, string_sid);
 }
 
 /*
   add a group mapping entry
  */
-static BOOL add_mapping_entry(GROUP_MAP *map, int flag)
+static bool add_mapping_entry(GROUP_MAP *map, int flag)
 {
        struct ldb_message *msg;        
        int ret, i;
@@ -150,7 +158,7 @@ static BOOL add_mapping_entry(GROUP_MAP *map, int flag)
 
        if (ldb_msg_add_string(msg, "objectClass", "groupMap") != LDB_SUCCESS ||
            ldb_msg_add_string(msg, "sid", 
-                              sid_to_string(string_sid, &map->sid)) != LDB_SUCCESS ||
+                              sid_to_fstring(string_sid, &map->sid)) != LDB_SUCCESS ||
            ldb_msg_add_fmt(msg, "gidNumber", "%u", (unsigned)map->gid) != LDB_SUCCESS ||
            ldb_msg_add_fmt(msg, "sidNameUse", "%u", (unsigned)map->sid_name_use) != LDB_SUCCESS ||
            ldb_msg_add_string(msg, "comment", map->comment) != LDB_SUCCESS ||
@@ -181,7 +189,7 @@ failed:
 /*
   unpack a ldb message into a GROUP_MAP structure
 */
-static BOOL msg_to_group_map(struct ldb_message *msg, GROUP_MAP *map)
+static bool msg_to_group_map(struct ldb_message *msg, GROUP_MAP *map)
 {
        const char *sidstr;
 
@@ -204,88 +212,88 @@ static BOOL msg_to_group_map(struct ldb_message *msg, GROUP_MAP *map)
 /*
  return a group map entry for a given sid
 */
-static BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map)
+static bool get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map)
 {
        int ret;
        struct ldb_dn *dn;
        struct ldb_result *res=NULL;
-       
-       dn = mapping_dn(ldb, &sid);
-       if (dn == NULL) goto failed;
+       bool result = false;
 
-       ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, NULL, NULL, &res);
-       talloc_steal(dn, res);
+       dn = mapping_dn(talloc_tos(), &sid);
+       if (dn == NULL) {
+               goto failed;
+       }
+
+       ret = ldb_search(ldb, dn, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
        if (ret != LDB_SUCCESS || res->count != 1) {
                goto failed;
        }
 
-       if (!msg_to_group_map(res->msgs[0], map)) goto failed;
+       if (!msg_to_group_map(res->msgs[0], map)) {
+               goto failed;
+       }
 
+       result = true;
+ failed:
        talloc_free(dn);
-       return True;
-
-failed:
-       talloc_free(dn);
-       return False;
+       return result;
 }
 
 /*
  return a group map entry for a given gid
 */
-static BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map)
+static bool get_group_map_from_gid(gid_t gid, GROUP_MAP *map)
 {
        int ret;
-       char *expr;
        struct ldb_result *res=NULL;
+       bool result = false;
 
-       expr = talloc_asprintf(ldb, "(&(gidNumber=%u)(objectClass=groupMap))", 
-                              (unsigned)gid);
-       if (expr == NULL) goto failed;
-
-       ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, expr, NULL, &res);
-       talloc_steal(expr, res);
-       if (ret != LDB_SUCCESS || res->count != 1) goto failed;
-       
-       if (!msg_to_group_map(res->msgs[0], map)) goto failed;
+       ret = ldb_search(ldb, talloc_tos(), &res, NULL, LDB_SCOPE_SUBTREE,
+                        NULL, "(&(gidNumber=%u)(objectClass=groupMap))",
+                        (unsigned)gid);
+       if (ret != LDB_SUCCESS || res->count != 1) {
+               goto failed;
+       }
 
-       talloc_free(expr);
-       return True;
+       if (!msg_to_group_map(res->msgs[0], map)) {
+               goto failed;
+       }
 
+       result = true;
 failed:
-       talloc_free(expr);
-       return False;
+       TALLOC_FREE(res);
+       return result;
 }
 
 /*
   Return the sid and the type of the unix group.
 */
-static BOOL get_group_map_from_ntname(const char *name, GROUP_MAP *map)
+static bool get_group_map_from_ntname(const char *name, GROUP_MAP *map)
 {
        int ret;
-       char *expr;
        struct ldb_result *res=NULL;
+       bool result = false;
 
-       expr = talloc_asprintf(ldb, "(&(ntName=%s)(objectClass=groupMap))", name);
-       if (expr == NULL) goto failed;
-
-       ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, expr, NULL, &res);
-       talloc_steal(expr, res);
-       if (ret != LDB_SUCCESS || res->count != 1) goto failed;
-       
-       if (!msg_to_group_map(res->msgs[0], map)) goto failed;
+       ret = ldb_search(ldb, talloc_tos(), &res, NULL, LDB_SCOPE_SUBTREE,
+                        NULL, "(&(ntName=%s)(objectClass=groupMap))", name);
+       if (ret != LDB_SUCCESS || res->count != 1) {
+               goto failed;
+       }
 
-       talloc_free(expr);
-       return True;
+       if (!msg_to_group_map(res->msgs[0], map)) {
+               goto failed;
+       }
 
-failed:
-       talloc_free(expr);
-       return False;
+       result = true;
+ failed:
+       TALLOC_FREE(res);
+       return result;
 }
 
 /*
  Remove a group mapping entry.
 */
-static BOOL group_map_remove(const DOM_SID *sid)
+static bool group_map_remove(const DOM_SID *sid)
 {
        struct ldb_dn *dn;
        int ret;
@@ -304,36 +312,35 @@ static BOOL group_map_remove(const DOM_SID *sid)
 /*
   Enumerate the group mappings for a domain
 */
-static BOOL enum_group_mapping(const DOM_SID *domsid, enum lsa_SidType sid_name_use, 
+static bool enum_group_mapping(const DOM_SID *domsid, enum lsa_SidType sid_name_use, 
                               GROUP_MAP **pp_rmap,
-                              size_t *p_num_entries, BOOL unix_only)
+                              size_t *p_num_entries, bool unix_only)
 {
        int i, ret;
-       char *expr;
        fstring name;
-       struct ldb_result *res;
+       struct ldb_result *res = NULL;
        struct ldb_dn *basedn=NULL;
        TALLOC_CTX *tmp_ctx;
 
        tmp_ctx = talloc_new(ldb);
        if (tmp_ctx == NULL) goto failed;
 
-       if (sid_name_use == SID_NAME_UNKNOWN) {
-               expr = talloc_asprintf(tmp_ctx, "(&(objectClass=groupMap))");
-       } else {
-               expr = talloc_asprintf(tmp_ctx, "(&(sidNameUse=%u)(objectClass=groupMap))",
-                                      sid_name_use);
-       }
-       if (expr == NULL) goto failed;
-
        /* we do a subtree search on the domain */
        if (domsid != NULL) {
-               sid_to_string(name, domsid);
-               basedn = ldb_dn_string_compose(tmp_ctx, NULL, "domain=%s", name);
+               sid_to_fstring(name, domsid);
+               basedn = ldb_dn_new_fmt(tmp_ctx, ldb, "domain=%s", name);
                if (basedn == NULL) goto failed;
        }
 
-       ret = ldb_search(ldb, basedn, LDB_SCOPE_SUBTREE, expr, NULL, &res);
+       if (sid_name_use == SID_NAME_UNKNOWN) {
+               ret = ldb_search(ldb, tmp_ctx, &res, basedn, LDB_SCOPE_SUBTREE,
+                                NULL, "(&(objectClass=groupMap))");
+       } else {
+               ret = ldb_search(ldb, tmp_ctx, &res, basedn, LDB_SCOPE_SUBTREE,
+                                NULL, "(&(sidNameUse=%u)(objectClass=groupMap))",
+                                sid_name_use);
+       }
+
        if (ret != LDB_SUCCESS) goto failed;
 
        (*pp_rmap) = NULL;
@@ -371,23 +378,20 @@ static NTSTATUS one_alias_membership(const DOM_SID *member,
                NULL
        };
        DOM_SID alias;
-       char *expr;
        int ret, i;
        struct ldb_result *res=NULL;
        fstring string_sid;
-       NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+       NTSTATUS status;
 
-       if (!sid_to_string(string_sid, member)) {
+       if (!sid_to_fstring(string_sid, member)) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       expr = talloc_asprintf(ldb, "(&(member=%s)(objectClass=groupMap))", 
-                              string_sid);
-       if (expr == NULL) goto failed;
-
-       ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, expr, attrs, &res);
-       talloc_steal(expr, res);
+       ret = ldb_search(ldb, talloc_tos(), &res, NULL, LDB_SCOPE_SUBTREE,
+                        attrs, "(&(member=%s)(objectClass=groupMap))",
+                        string_sid);
        if (ret != LDB_SUCCESS) {
+               status = NT_STATUS_INTERNAL_DB_CORRUPTION;
                goto failed;
        }
 
@@ -399,17 +403,15 @@ static NTSTATUS one_alias_membership(const DOM_SID *member,
                        goto failed;
                }
                string_to_sid(&alias, (char *)el->values[0].data);
-               if (!add_sid_to_array_unique(NULL, &alias, sids, num)) {
-                       status = NT_STATUS_NO_MEMORY;
+               status = add_sid_to_array_unique(NULL, &alias, sids, num);
+               if (!NT_STATUS_IS_OK(status)) {
                        goto failed;
                }
        }
 
-       talloc_free(expr);
-       return NT_STATUS_OK;
-
-failed:
-       talloc_free(expr);
+       status = NT_STATUS_OK;
+ failed:
+       TALLOC_FREE(res);
        return status;
 }
 
@@ -428,7 +430,7 @@ static NTSTATUS modify_aliasmem(const DOM_SID *alias, const DOM_SID *member,
        GROUP_MAP map;
 
        if (!get_group_map_from_sid(*alias, &map)) {
-               sid_to_string(string_sid, alias);
+               sid_to_fstring(string_sid, alias);
                return NT_STATUS_NO_SUCH_ALIAS;
        }
 
@@ -453,7 +455,7 @@ static NTSTATUS modify_aliasmem(const DOM_SID *alias, const DOM_SID *member,
        el.name = talloc_strdup(tmp_ctx, "member");
        el.num_values = 1;
        el.values = &val;
-       sid_to_string(string_sid, member);
+       sid_to_fstring(string_sid, member);
        val.data = (uint8_t *)string_sid;
        val.length = strlen(string_sid);
 
@@ -486,13 +488,15 @@ static NTSTATUS del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
 /*
   enumerate sids that have the given alias set in member
 */
-static NTSTATUS enum_aliasmem(const DOM_SID *alias, DOM_SID **sids, size_t *num)
+static NTSTATUS enum_aliasmem(const DOM_SID *alias, TALLOC_CTX *mem_ctx,
+                             DOM_SID **sids, size_t *num)
 {
        const char *attrs[] = {
                "member",
                NULL
        };
        int ret, i;
+       NTSTATUS status = NT_STATUS_OK;
        struct ldb_result *res=NULL;
        struct ldb_dn *dn;
        struct ldb_message_element *el;
@@ -505,9 +509,9 @@ static NTSTATUS enum_aliasmem(const DOM_SID *alias, DOM_SID **sids, size_t *num)
                return NT_STATUS_NO_MEMORY;
        }
 
-       ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, NULL, attrs, &res);
-       talloc_steal(dn, res);
+       ret = ldb_search(ldb, ldb, &res, dn, LDB_SCOPE_BASE, attrs, NULL);
        if (ret == LDB_SUCCESS && res->count == 0) {
+               talloc_free(res);
                talloc_free(dn);
                return NT_STATUS_OK;
        }
@@ -516,23 +520,25 @@ static NTSTATUS enum_aliasmem(const DOM_SID *alias, DOM_SID **sids, size_t *num)
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
 
+       talloc_steal(dn, res);
        el = ldb_msg_find_element(res->msgs[0], "member");
        if (el == NULL) {
                talloc_free(dn);
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+               return NT_STATUS_OK;
        }
        
        for (i=0;i<el->num_values;i++) {
                DOM_SID sid;
                string_to_sid(&sid, (const char *)el->values[i].data);
-               if (!add_sid_to_array_unique(NULL, &sid, sids, num)) {
-                       talloc_free(dn);
-                       return NT_STATUS_NO_MEMORY;
+               status = add_sid_to_array_unique(mem_ctx, &sid, sids, num);
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto done;
                }
        }
-       talloc_free(dn);
 
-       return NT_STATUS_OK;
+done:
+       talloc_free(dn);
+       return status;
 }
 
 /*
@@ -563,6 +569,13 @@ static int upgrade_map_record(TDB_CONTEXT *tdb_ctx, TDB_DATA key,
                return -1;
        }
 
+       if ((int)map.gid == -1) {
+               /*
+                * Ignore old invalid mappings
+                */
+               return 0;
+       }
+
        if (!add_mapping_entry(&map, 0)) {
                DEBUG(0,("Failed to add mapping entry during upgrade\n"));
                *(int *)state = -1;
@@ -579,8 +592,9 @@ static int upgrade_alias_record(TDB_CONTEXT *tdb_ctx, TDB_DATA key,
                                TDB_DATA data, void *state)
 {
        const char *p = (const char *)data.dptr;
-       fstring string_sid;
+       char *string_sid;
        DOM_SID member;
+       TALLOC_CTX *frame;
 
        if (strncmp((char *)key.dptr, MEMBEROF_PREFIX, 
                    MIN(key.dsize, strlen(MEMBEROF_PREFIX))) != 0) {
@@ -593,7 +607,8 @@ static int upgrade_alias_record(TDB_CONTEXT *tdb_ctx, TDB_DATA key,
                *(int *)state = -1;
        }
 
-       while (next_token(&p, string_sid, " ", sizeof(string_sid))) {
+       frame = talloc_stackframe();
+       while (next_token_talloc(frame,&p, &string_sid, " ")) {
                DOM_SID alias;
                NTSTATUS status;
                string_to_sid(&alias, string_sid);
@@ -605,22 +620,21 @@ static int upgrade_alias_record(TDB_CONTEXT *tdb_ctx, TDB_DATA key,
                        DEBUG(0,("Failed to add alias member during upgrade - %s\n",
                                 nt_errstr(status)));
                        *(int *)state = -1;
+                       TALLOC_FREE(frame);
                        return -1;
                }
        }
-
+       TALLOC_FREE(frame);
        return 0;
 }
 
 /*
   upgrade from a old style tdb
 */
-static BOOL mapping_upgrade(const char *tdb_path)
+static bool mapping_upgrade(const char *tdb_path)
 {
        static TDB_CONTEXT *tdb;
        int ret, status=0;
-       pstring old_path;
-       pstring new_path;
 
        tdb = tdb_open_log(tdb_path, 0, TDB_DEFAULT, O_RDWR, 0600);
        if (tdb == NULL) goto failed;
@@ -638,12 +652,17 @@ static BOOL mapping_upgrade(const char *tdb_path)
                tdb = NULL;
        }
 
-       pstrcpy(old_path, tdb_path);
-       pstrcpy(new_path, lock_path("group_mapping.tdb.upgraded"));
+       {
+               const char *old_path = tdb_path;
+               char *new_path = state_path("group_mapping.tdb.upgraded");
 
-       if (rename(old_path, new_path) != 0) {
-               DEBUG(0,("Failed to rename old group mapping database\n"));
-               goto failed;
+               if (!new_path) {
+                       goto failed;
+               }
+               if (rename(old_path, new_path) != 0) {
+                       DEBUG(0,("Failed to rename old group mapping database\n"));
+                       goto failed;
+               }
        }
        return True;