diff options
Diffstat (limited to 'source3/sam/gums.c')
-rw-r--r-- | source3/sam/gums.c | 171 |
1 files changed, 122 insertions, 49 deletions
diff --git a/source3/sam/gums.c b/source3/sam/gums.c index a118740637..ab374b9342 100644 --- a/source3/sam/gums.c +++ b/source3/sam/gums.c @@ -20,8 +20,8 @@ #include "includes.h" -/*#undef DBGC_CLASS -#define DBGC_CLASS DBGC_GUMS*/ +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_SAM #define GMV_MAJOR 0 #define GMV_MINOR 1 @@ -56,8 +56,7 @@ #define PRIV_ALL 255 -GUMS_FUNCTIONS *gums_storage; -static void *dl_handle; +static GUMS_FUNCTIONS *gums_backend = NULL; static PRIVS gums_privs[] = { {PRIV_NONE, "no_privs", "No privilege"}, /* this one MUST be first */ @@ -90,72 +89,146 @@ static PRIVS gums_privs[] = { {PRIV_ALL, "SaAllPrivs", "All Privileges"} }; -NTSTATUS gums_init(const char *module_name) +static struct gums_init_function_entry *backends = NULL; + +static void lazy_initialize_gums(void) { - int (*module_version)(int); - NTSTATUS (*module_init)(); -/* gums_module_init module_init;*/ - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + static BOOL initialized = False; + + if (initialized) + return; - DEBUG(5, ("Opening gums module %s\n", module_name)); - dl_handle = sys_dlopen(module_name, RTLD_NOW); - if (!dl_handle) { - DEBUG(0, ("ERROR: Failed to load gums module %s, error: %s\n", module_name, sys_dlerror())); - return NT_STATUS_UNSUCCESSFUL; - } + static_init_gums; + initialized = True; +} - module_version = sys_dlsym(dl_handle, "gumm_version"); - if (!module_version) { - DEBUG(0, ("ERROR: Failed to find gums module version!\n")); - goto error; - } +static struct gums_init_function_entry *gums_find_backend_entry(const char *name); + +NTSTATUS gums_register_module(int version, const char *name, gums_init_function init_fn) +{ + struct gums_init_function_entry *entry = backends; + + if (version != GUMS_INTERFACE_VERSION) { + DEBUG(0,("Can't register gums backend!\n" + "You tried to register a gums module with" + "GUMS_INTERFACE_VERSION %d, while this version" + "of samba uses version %d\n", version, + GUMS_INTERFACE_VERSION)); - if (module_version(GMV_MAJOR) != GUMS_VERSION_MAJOR) { - DEBUG(0, ("ERROR: Module's major version does not match gums version!\n")); - goto error; + return NT_STATUS_OBJECT_TYPE_MISMATCH; } - if (module_version(GMV_MINOR) != GUMS_VERSION_MINOR) { - DEBUG(1, ("WARNING: Module's minor version does not match gums version!\n")); + if (!name || !init_fn) { + return NT_STATUS_INVALID_PARAMETER; } - module_init = sys_dlsym(dl_handle, "gumm_init"); - if (!module_init) { - DEBUG(0, ("ERROR: Failed to find gums module's init function!\n")); - goto error; + DEBUG(5,("Attempting to register gums backend %s\n", name)); + + /* Check for duplicates */ + if (gums_find_backend_entry(name)) { + DEBUG(0,("There already is a gums backend registered" + "with the name %s!\n", name)); + return NT_STATUS_OBJECT_NAME_COLLISION; } - DEBUG(5, ("Initializing module %s\n", module_name)); + entry = smb_xmalloc(sizeof(struct gums_init_function_entry)); + entry->name = smb_xstrdup(name); + entry->init_fn = init_fn; - ret = module_init(&gums_storage); - goto done; + DLIST_ADD(backends, entry); + DEBUG(5,("Successfully added gums backend '%s'\n", name)); + return NT_STATUS_OK; +} -error: - ret = NT_STATUS_UNSUCCESSFUL; - sys_dlclose(dl_handle); +static struct gums_init_function_entry *gums_find_backend_entry(const char *name) +{ + struct gums_init_function_entry *entry = backends; -done: - return ret; + while (entry) { + if (strcmp(entry->name, name) == 0) + return entry; + entry = entry->next; + } + + return NULL; } -NTSTATUS gums_unload(void) +NTSTATUS gums_setup_backend(const char *backend) { - NTSTATUS ret; - NTSTATUS (*module_finalize)(); - if (!dl_handle) - return NT_STATUS_UNSUCCESSFUL; + TALLOC_CTX *mem_ctx; + char *module_name = smb_xstrdup(backend); + char *p, *module_data = NULL; + struct gums_init_function_entry *entry; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + lazy_initialize_gums(); + + p = strchr(module_name, ':'); + if (p) { + *p = 0; + module_data = p+1; + trim_string(module_data, " ", " "); + } + + trim_string(module_name, " ", " "); - module_finalize = sys_dlsym(dl_handle, "gumm_finalize"); - if (!module_finalize) { - DEBUG(0, ("ERROR: Failed to find gums module's init function!\n")); - return NT_STATUS_UNSUCCESSFUL; + DEBUG(5,("Attempting to find a gums backend to match %s (%s)\n", backend, module_name)); + + entry = gums_find_backend_entry(module_name); + + /* Try to find a module that contains this module */ + if (!entry) { + DEBUG(2,("No builtin backend found, trying to load plugin\n")); + if(NT_STATUS_IS_OK(smb_probe_module("gums", module_name)) && !(entry = gums_find_backend_entry(module_name))) { + DEBUG(0,("Plugin is available, but doesn't register gums backend %s\n", module_name)); + SAFE_FREE(module_name); + return NT_STATUS_UNSUCCESSFUL; + } } - DEBUG(5, ("Finalizing module")); + /* No such backend found */ + if(!entry) { + DEBUG(0,("No builtin nor plugin backend for %s found\n", module_name)); + SAFE_FREE(module_name); + return NT_STATUS_INVALID_PARAMETER; + } - ret = module_finalize(); - sys_dlclose(dl_handle); + DEBUG(5,("Found gums backend %s\n", module_name)); + /* free current functions structure if any */ + if (gums_backend) { + gums_backend->free_private_data(gums_backend->private_data); + talloc_destroy(gums_backend->mem_ctx); + gums_backend = NULL; + } + + /* allocate a new GUMS_FUNCTIONS structure and memory context */ + mem_ctx = talloc_init("gums_backend (%s)", module_name); + if (!mem_ctx) + return NT_STATUS_NO_MEMORY; + gums_backend = talloc(mem_ctx, sizeof(GUMS_FUNCTIONS)); + if (!gums_backend) + return NT_STATUS_NO_MEMORY; + gums_backend->mem_ctx = mem_ctx; + + /* init the requested backend module */ + if (NT_STATUS_IS_OK(ret = entry->init_fn(gums_backend, module_data))) { + DEBUG(5,("gums backend %s has a valid init\n", backend)); + } else { + DEBUG(0,("gums backend %s did not correctly init (error was %s)\n", backend, nt_errstr(ret))); + } + SAFE_FREE(module_name); return ret; } + +NTSTATUS get_gums_fns(GUMS_FUNCTIONS **fns) +{ + if (gums_backend != NULL) { + *fns = gums_backend; + return NT_STATUS_OK; + } + + DEBUG(2, ("get_gums_fns: unable to get gums functions! backend uninitialized?\n")); + return NT_STATUS_UNSUCCESSFUL; +} |