s3:winbind Ensure we always init idmap_passdb before we use it
[metze/samba/wip.git] / source3 / winbindd / idmap.c
index 54b5f468e4ac304beeb1fdb47762a4468314eae4..532a90ed3d8df147296e49ed7d8ad20e65b8ffa9 100644 (file)
@@ -40,27 +40,6 @@ struct idmap_backend {
 };
 static struct idmap_backend *backends = NULL;
 
-/**
- * Pointer to the alloc backend methods. Modules register themselves here via
- * smb_register_idmap_alloc.
- */
-struct idmap_alloc_backend {
-       const char *name;
-       struct idmap_alloc_methods *methods;
-       struct idmap_alloc_backend *prev, *next;
-};
-static struct idmap_alloc_backend *alloc_backends = NULL;
-
-/**
- * The idmap alloc context that is configured via "idmap alloc
- * backend". Defaults to "idmap backend" in case the module (tdb, ldap) also
- * provides alloc methods.
- */
-struct idmap_alloc_context {
-       struct idmap_alloc_methods *methods;
-};
-static struct idmap_alloc_context *idmap_alloc_ctx = NULL;
-
 /**
  * Default idmap domain configured via "idmap backend".
  */
@@ -94,19 +73,6 @@ static struct idmap_methods *get_methods(const char *name)
        return NULL;
 }
 
-static struct idmap_alloc_methods *get_alloc_methods(const char *name)
-{
-       struct idmap_alloc_backend *b;
-
-       for (b = alloc_backends; b; b = b->next) {
-               if (strequal(b->name, name)) {
-                       return b->methods;
-               }
-       }
-
-       return NULL;
-}
-
 bool idmap_is_offline(void)
 {
        return ( lp_winbind_offline_logon() &&
@@ -170,55 +136,6 @@ NTSTATUS smb_register_idmap(int version, const char *name,
        return NT_STATUS_OK;
 }
 
-/**********************************************************************
- Allow a module to register itself as an alloc method.
-**********************************************************************/
-
-NTSTATUS smb_register_idmap_alloc(int version, const char *name,
-                                 struct idmap_alloc_methods *methods)
-{
-       struct idmap_alloc_methods *test;
-       struct idmap_alloc_backend *entry;
-
-       if ((version != SMB_IDMAP_INTERFACE_VERSION)) {
-               DEBUG(0, ("Failed to register idmap alloc module.\n"
-                         "The module was compiled against "
-                         "SMB_IDMAP_INTERFACE_VERSION %d,\n"
-                         "current SMB_IDMAP_INTERFACE_VERSION is %d.\n"
-                         "Please recompile against the current version "
-                         "of samba!\n",
-                         version, SMB_IDMAP_INTERFACE_VERSION));
-               return NT_STATUS_OBJECT_TYPE_MISMATCH;
-       }
-
-       if (!name || !name[0] || !methods) {
-               DEBUG(0,("Called with NULL pointer or empty name!\n"));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       test = get_alloc_methods(name);
-       if (test) {
-               DEBUG(0,("idmap_alloc module %s already registered!\n", name));
-               return NT_STATUS_OBJECT_NAME_COLLISION;
-       }
-
-       entry = talloc(NULL, struct idmap_alloc_backend);
-       if ( ! entry) {
-               DEBUG(0,("Out of memory!\n"));
-               return NT_STATUS_NO_MEMORY;
-       }
-       entry->name = talloc_strdup(entry, name);
-       if ( ! entry->name) {
-               DEBUG(0,("Out of memory!\n"));
-               return NT_STATUS_NO_MEMORY;
-       }
-       entry->methods = methods;
-
-       DLIST_ADD(alloc_backends, entry);
-       DEBUG(5, ("Successfully added idmap alloc backend '%s'\n", name));
-       return NT_STATUS_OK;
-}
-
 static int close_domain_destructor(struct idmap_domain *dom)
 {
        NTSTATUS ret;
@@ -275,12 +192,14 @@ static bool parse_idmap_module(TALLOC_CTX *mem_ctx, const char *param,
  * @param[in] domainname       which domain is this for
  * @param[in] modulename       which backend module
  * @param[in] params           parameter to pass to the init function
+ * @param[in] check_range      whether range checking should be done
  * @result The initialized structure
  */
 static struct idmap_domain *idmap_init_domain(TALLOC_CTX *mem_ctx,
                                              const char *domainname,
                                              const char *modulename,
-                                             const char *params)
+                                             const char *params,
+                                             bool check_range)
 {
        struct idmap_domain *result;
        NTSTATUS status;
@@ -297,6 +216,91 @@ static struct idmap_domain *idmap_init_domain(TALLOC_CTX *mem_ctx,
                goto fail;
        }
 
+       /*
+        * load ranges and read only information from the config
+        */
+       if (strequal(result->name, "*")) {
+               /*
+                * The default domain "*" is configured differently
+                * from named domains.
+                */
+               uid_t low_uid = 0;
+               uid_t high_uid = 0;
+               gid_t low_gid = 0;
+               gid_t high_gid = 0;
+
+               result->low_id = 0;
+               result->high_id = 0;
+
+               if (!lp_idmap_uid(&low_uid, &high_uid)) {
+                       DEBUG(1, ("'idmap uid' not set!\n"));
+                       if (check_range) {
+                               goto fail;
+                       }
+               }
+
+               result->low_id = low_uid;
+               result->high_id = high_uid;
+
+               if (!lp_idmap_gid(&low_gid, &high_gid)) {
+                       DEBUG(1, ("'idmap gid' not set!\n"));
+                       if (check_range) {
+                               goto fail;
+                       }
+               }
+
+               if ((low_gid != low_uid) || (high_gid != high_uid)) {
+                       DEBUG(1, ("Warning: 'idmap uid' and 'idmap gid'"
+                             " ranges do not agree -- building "
+                             "intersection\n"));
+                       result->low_id = MAX(result->low_id, low_gid);
+                       result->high_id = MIN(result->high_id, high_gid);
+               }
+
+               result->read_only = lp_idmap_read_only();
+       } else {
+               char *config_option = NULL;
+               const char *range;
+
+               config_option = talloc_asprintf(result, "idmap config %s",
+                                               result->name);
+               if (config_option == NULL) {
+                       DEBUG(0, ("Out of memory!\n"));
+                       goto fail;
+               }
+
+               range = lp_parm_const_string(-1, config_option, "range", NULL);
+               if (range == NULL) {
+                       DEBUG(1, ("idmap range not specified for domain %s\n",
+                                 result ->name));
+                       if (check_range) {
+                               goto fail;
+                       }
+               } else if (sscanf(range, "%u - %u", &result->low_id,
+                                 &result->high_id) != 2)
+               {
+                       DEBUG(1, ("invalid range '%s' specified for domain "
+                                 "'%s'\n", range, result->name));
+                       if (check_range) {
+                               goto fail;
+                       }
+               }
+
+               result->read_only = lp_parm_bool(-1, config_option, "read only",
+                                                false);
+
+               talloc_free(config_option);
+       }
+
+       if (result->low_id > result->high_id) {
+               DEBUG(1, ("Error: invalid idmap range detected: %lu - %lu\n",
+                         (unsigned long)result->low_id,
+                         (unsigned long)result->high_id));
+               if (check_range) {
+                       goto fail;
+               }
+       }
+
        result->methods = get_methods(modulename);
        if (result->methods == NULL) {
                DEBUG(3, ("idmap backend %s not found\n", modulename));
@@ -358,7 +362,7 @@ static struct idmap_domain *idmap_init_default_domain(TALLOC_CTX *mem_ctx)
 
        DEBUG(3, ("idmap_init: using '%s' as remote backend\n", modulename));
 
-       result = idmap_init_domain(mem_ctx, "*", modulename, params);
+       result = idmap_init_domain(mem_ctx, "*", modulename, params, true);
        if (result == NULL) {
                goto fail;
        }
@@ -404,7 +408,7 @@ static struct idmap_domain *idmap_init_named_domain(TALLOC_CTX *mem_ctx,
                goto fail;
        }
 
-       result = idmap_init_domain(mem_ctx, domname, backend, NULL);
+       result = idmap_init_domain(mem_ctx, domname, backend, NULL, true);
        if (result == NULL) {
                goto fail;
        }
@@ -428,12 +432,16 @@ fail:
 
 static struct idmap_domain *idmap_init_passdb_domain(TALLOC_CTX *mem_ctx)
 {
+       DEBUG(10, ("idmap_init_passdb_domain: calling static_init_idmap\n"));
+
+       static_init_idmap;
+
        if (passdb_idmap_domain != NULL) {
                return passdb_idmap_domain;
        }
 
        passdb_idmap_domain = idmap_init_domain(NULL, get_global_sam_name(),
-                                               "passdb", NULL);
+                                               "passdb", NULL, false);
        if (passdb_idmap_domain == NULL) {
                DEBUG(1, ("Could not init passdb idmap domain\n"));
        }
@@ -511,192 +519,47 @@ static struct idmap_domain *idmap_find_domain(const char *domname)
 
 void idmap_close(void)
 {
-        if (idmap_alloc_ctx) {
-                idmap_alloc_ctx->methods->close_fn();
-                idmap_alloc_ctx->methods = NULL;
-        }
-        alloc_backends = NULL;
        TALLOC_FREE(default_idmap_domain);
        TALLOC_FREE(passdb_idmap_domain);
        TALLOC_FREE(idmap_domains);
        num_domains = 0;
 }
 
-/**
- * Initialize the idmap alloc backend
- * @param[out] ctx             Where to put the alloc_ctx?
- * @result Did it work fine?
- *
- * This routine first looks at "idmap alloc backend" and if that is not
- * defined, it uses "idmap backend" for the module name.
- */
-static NTSTATUS idmap_alloc_init(struct idmap_alloc_context **ctx)
-{
-       const char *backend;
-       char *modulename, *params;
-       NTSTATUS ret = NT_STATUS_NO_MEMORY;;
-
-       static_init_idmap;
-
-       if (idmap_alloc_ctx != NULL) {
-               *ctx = idmap_alloc_ctx;
-               return NT_STATUS_OK;
-       }
-
-       idmap_alloc_ctx = talloc(NULL, struct idmap_alloc_context);
-       if (idmap_alloc_ctx == NULL) {
-               DEBUG(0, ("talloc failed\n"));
-               goto fail;
-       }
-
-       backend = lp_idmap_alloc_backend();
-       if ((backend == NULL) || (backend[0] == '\0')) {
-               backend = lp_idmap_backend();
-       }
-
-       if (backend == NULL) {
-               DEBUG(3, ("no idmap alloc backend defined\n"));
-               ret = NT_STATUS_INVALID_PARAMETER;
-               goto fail;
-       }
-
-       if (!parse_idmap_module(idmap_alloc_ctx, backend, &modulename,
-                               &params)) {
-               DEBUG(1, ("parse_idmap_module %s failed\n", backend));
-               goto fail;
-       }
+/**************************************************************************
+ idmap allocator interface functions
+**************************************************************************/
 
-       idmap_alloc_ctx->methods = get_alloc_methods(modulename);
+static NTSTATUS idmap_allocate_unixid(struct unixid *id)
+{
+       struct idmap_domain *dom;
+       NTSTATUS ret;
 
-       if (idmap_alloc_ctx->methods == NULL) {
-               ret = smb_probe_module("idmap", modulename);
-               if (NT_STATUS_IS_OK(ret)) {
-                       idmap_alloc_ctx->methods =
-                               get_alloc_methods(modulename);
-               }
-       }
+       dom = idmap_find_domain(NULL);
 
-       if (idmap_alloc_ctx->methods == NULL) {
-               DEBUG(1, ("could not find idmap alloc module %s\n", backend));
-               ret = NT_STATUS_INVALID_PARAMETER;
-               goto fail;
+       if (dom == NULL) {
+               return NT_STATUS_UNSUCCESSFUL;
        }
 
-       ret = idmap_alloc_ctx->methods->init(params);
-
-       if (!NT_STATUS_IS_OK(ret)) {
-               DEBUG(0, ("ERROR: Initialization failed for alloc "
-                         "backend, deferred!\n"));
-               goto fail;
+       if (dom->methods->allocate_id == NULL) {
+               return NT_STATUS_NOT_IMPLEMENTED;
        }
 
-       TALLOC_FREE(modulename);
-       TALLOC_FREE(params);
-
-       *ctx = idmap_alloc_ctx;
-       return NT_STATUS_OK;
+       ret = dom->methods->allocate_id(dom, id);
 
-fail:
-       TALLOC_FREE(idmap_alloc_ctx);
        return ret;
 }
 
-/**************************************************************************
- idmap allocator interface functions
-**************************************************************************/
 
 NTSTATUS idmap_allocate_uid(struct unixid *id)
 {
-       struct idmap_alloc_context *ctx;
-       NTSTATUS ret;
-
-       if (!NT_STATUS_IS_OK(ret = idmap_alloc_init(&ctx))) {
-               return ret;
-       }
-
        id->type = ID_TYPE_UID;
-       return ctx->methods->allocate_id(id);
+       return idmap_allocate_unixid(id);
 }
 
 NTSTATUS idmap_allocate_gid(struct unixid *id)
 {
-       struct idmap_alloc_context *ctx;
-       NTSTATUS ret;
-
-       if (!NT_STATUS_IS_OK(ret = idmap_alloc_init(&ctx))) {
-               return ret;
-       }
-
        id->type = ID_TYPE_GID;
-       return ctx->methods->allocate_id(id);
-}
-
-NTSTATUS idmap_new_mapping(const struct dom_sid *psid, enum id_type type,
-                          struct unixid *pxid)
-{
-       struct dom_sid sid;
-       struct idmap_domain *dom;
-       struct id_map map;
-       NTSTATUS status;
-
-       dom = idmap_find_domain(NULL);
-       if (dom == NULL) {
-               DEBUG(3, ("no default domain, no place to write\n"));
-               return NT_STATUS_ACCESS_DENIED;
-       }
-       if (dom->methods->set_mapping == NULL) {
-               DEBUG(3, ("default domain not writable\n"));
-               return NT_STATUS_MEDIA_WRITE_PROTECTED;
-       }
-
-       sid_copy(&sid, psid);
-       map.sid = &sid;
-       map.xid.type = type;
-
-       switch (type) {
-       case ID_TYPE_UID:
-               status = idmap_allocate_uid(&map.xid);
-               break;
-       case ID_TYPE_GID:
-               status = idmap_allocate_gid(&map.xid);
-               break;
-       default:
-               status = NT_STATUS_INVALID_PARAMETER;
-               break;
-       }
-
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(3, ("Could not allocate id: %s\n", nt_errstr(status)));
-               return status;
-       }
-
-       map.status = ID_MAPPED;
-
-       DEBUG(10, ("Setting mapping: %s <-> %s %lu\n",
-                  sid_string_dbg(map.sid),
-                  (map.xid.type == ID_TYPE_UID) ? "UID" : "GID",
-                  (unsigned long)map.xid.id));
-
-       status = dom->methods->set_mapping(dom, &map);
-
-       if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
-               struct id_map *ids[2];
-               DEBUG(5, ("Mapping for %s exists - retrying to map sid\n",
-                         sid_string_dbg(map.sid)));
-               ids[0] = &map;
-               ids[1] = NULL;
-               status = dom->methods->sids_to_unixids(dom, ids);
-       }
-
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(3, ("Could not store the new mapping: %s\n",
-                         nt_errstr(status)));
-               return status;
-       }
-
-       *pxid = map.xid;
-
-       return NT_STATUS_OK;
+       return idmap_allocate_unixid(id);
 }
 
 NTSTATUS idmap_backends_unixid_to_sid(const char *domname, struct id_map *id)
@@ -758,20 +621,3 @@ NTSTATUS idmap_backends_sid_to_unixid(const char *domain, struct id_map *id)
 
        return dom->methods->sids_to_unixids(dom, maps);
 }
-
-NTSTATUS idmap_remove_mapping(const struct id_map *map)
-{
-       struct idmap_domain *dom;
-
-       dom = idmap_find_domain(NULL);
-       if (dom == NULL) {
-               DEBUG(3, ("no default domain, no place to write\n"));
-               return NT_STATUS_ACCESS_DENIED;
-       }
-       if (dom->methods->remove_mapping == NULL) {
-               DEBUG(3, ("default domain not writable\n"));
-               return NT_STATUS_MEDIA_WRITE_PROTECTED;
-       }
-
-       return dom->methods->remove_mapping(dom, map);
-}