From 91dfe750f64cc0d8a970864959767379e0d128db Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 11 Jan 2009 12:15:48 -0500 Subject: Turn ldap_provider.c into proxy.c and make it possible to load just any libnss library through config directives on the domain object --- server/Makefile.in | 2 +- server/examples/config.ldif | 3 + server/providers/data_provider_be.c | 3 +- server/providers/dp_backend.h | 1 + server/providers/ldap_provider.c | 253 -------------------------------- server/providers/proxy.c | 281 ++++++++++++++++++++++++++++++++++++ server/server.mk | 8 +- 7 files changed, 292 insertions(+), 259 deletions(-) delete mode 100644 server/providers/ldap_provider.c create mode 100644 server/providers/proxy.c diff --git a/server/Makefile.in b/server/Makefile.in index 966286b37..b86d88110 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -60,7 +60,7 @@ OBJS = $(SERVER_OBJ) @LIBREPLACEOBJ@ $(EXTRA_OBJ) headers = .h BINS = sbin/sssd sbin/sssd_nss sbin/sssd_dp sbin/sssd_be -SOLIBS = lib/libsss_ldap.$(SHLIBEXT) +SOLIBS = lib/libsss_proxy.$(SHLIBEXT) DIRS = sbin lib diff --git a/server/examples/config.ldif b/server/examples/config.ldif index e2eee8184..2ca830c4c 100644 --- a/server/examples/config.ldif +++ b/server/examples/config.ldif @@ -52,3 +52,6 @@ description: TEST Ldap domain provider: TEST basedn: cn=test,cn=remote command: ./sbin/sssd_be -d 2 --provider ldap --domain TEST +libName: ldap +libPath: /usr/lib64/libnss_ldap.so.2 + diff --git a/server/providers/data_provider_be.c b/server/providers/data_provider_be.c index 568fb2eca..8f0d8318a 100644 --- a/server/providers/data_provider_be.c +++ b/server/providers/data_provider_be.c @@ -402,7 +402,8 @@ int be_process_init(TALLOC_CTX *mem_ctx, ctx->name = talloc_strdup(ctx, be_name); ctx->domain = talloc_strdup(ctx, be_domain); ctx->identity = talloc_asprintf(ctx, "%%BE_%s", be_domain); - if (!ctx->name || !ctx->domain || !ctx->identity) { + ctx->conf_path = talloc_asprintf(ctx, "config/domains/%s", be_domain); + if (!ctx->name || !ctx->domain || !ctx->identity || !ctx->conf_path) { DEBUG(0, ("Out of memory!?\n")); return ENOMEM; } diff --git a/server/providers/dp_backend.h b/server/providers/dp_backend.h index 81df6b7d1..c7cb61c40 100644 --- a/server/providers/dp_backend.h +++ b/server/providers/dp_backend.h @@ -35,6 +35,7 @@ struct be_ctx { const char *name; const char *domain; const char *identity; + const char *conf_path; struct be_mod_ops *ops; void *pvt_data; }; diff --git a/server/providers/ldap_provider.c b/server/providers/ldap_provider.c deleted file mode 100644 index dd8ac18dc..000000000 --- a/server/providers/ldap_provider.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - SSSD - - Test LDAP Module - - Copyright (C) Simo Sorce 2008 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - 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, see . -*/ - -#include -#include -#include -#include -#include "util/util.h" -#include "providers/dp_backend.h" - -struct ldap_nss_ops { - enum nss_status (*getpwnam_r)(const char *name, struct passwd *result, - char *buffer, size_t buflen, int *errnop); - enum nss_status (*getpwuid_r)(uid_t uid, struct passwd *result, - char *buffer, size_t buflen, int *errnop); - enum nss_status (*setpwent)(void); - enum nss_status (*getpwent_r)(struct passwd *result, - char *buffer, size_t buflen, int *errnop); - enum nss_status (*endpwent)(void); - - enum nss_status (*getgrnam_r)(const char *name, struct group *result, - char *buffer, size_t buflen, int *errnop); - enum nss_status (*getgrgid_r)(gid_t gid, struct group *result, - char *buffer, size_t buflen, int *errnop); - enum nss_status (*setgrent)(void); - enum nss_status (*getgrent_r)(struct group *result, - char *buffer, size_t buflen, int *errnop); - enum nss_status (*endgrent)(void); - enum nss_status (*initgroups_dyn)(const char *user, gid_t group, - long int *start, long int *size, - gid_t **groups, long int limit, - int *errnop); -}; - -struct ldap_ctx { - struct ldap_nss_ops ops; -}; - -static int get_pw_name(struct be_ctx *be_ctx, struct ldap_ctx *ldap_ctx, char *name) -{ - struct ldap_nss_ops *ops = &ldap_ctx->ops; - enum nss_status status; - struct passwd result; - char *buffer; - int ret; - - buffer = talloc_size(NULL, 4096); - if (!buffer) return ENOMEM; - - status = ops->getpwnam_r(name, &result, buffer, 4096, &ret); - - switch (status) { - case NSS_STATUS_NOTFOUND: - ret = dp_be_remove_account_posix(be_ctx, name); - break; - case NSS_STATUS_SUCCESS: - ret = dp_be_store_account_posix(be_ctx, name, result.pw_passwd, - result.pw_uid, result.pw_gid, - result.pw_gecos, result.pw_dir, - result.pw_shell); - break; - default: - DEBUG(2, ("ldap->getpwnam_r failed for '%s' (%d)[%s]\n", - name, ret, strerror(ret))); - talloc_free(buffer); - return ret; - } - - if (ret != EOK) { - DEBUG(1, ("Failed to update LDB Cache for '%s' (%d) !?\n", - name, ret)); - } - - talloc_free(buffer); - return ret; -} - -static int ldap_check_online(struct be_ctx *be_ctx, int *reply) -{ - *reply = MOD_ONLINE; - return EOK; -} - -static int ldap_get_account_info(struct be_ctx *be_ctx, - int entry_type, int attr_type, - int filter_type, char *filter_value) -{ - struct ldap_ctx *ctx; - - ctx = talloc_get_type(be_ctx->pvt_data, struct ldap_ctx); - - switch (entry_type) { - case BE_REQ_USER: /* user */ - switch (filter_type) { - case BE_FILTER_NAME: - switch (attr_type) { - case BE_ATTR_CORE: - if (strchr(filter_value, '*')) { - /* TODO */ - } else { - return get_pw_name(be_ctx, ctx, filter_value); - } - break; - default: - return EINVAL; - } - break; - case BE_FILTER_IDNUM: - break; - default: - return EINVAL; - } - break; - - case BE_REQ_GROUP: /* group */ - /* TODO */ - return EOK; - - default: /*fail*/ - return EINVAL; - } - - return EOK; -} - -struct be_mod_ops ldap_mod_ops = { - .check_online = ldap_check_online, - .get_account_info = ldap_get_account_info -}; - -int sssm_ldap_init(struct be_ctx *bectx, struct be_mod_ops **ops, void **pvt_data) -{ - struct ldap_ctx *ctx; - void *handle; - int ret; - - ctx = talloc(bectx, struct ldap_ctx); - if (!ctx) { - return ENOMEM; - } - - handle = dlopen("/usr/lib64/libnss_ldap.so.2", RTLD_NOW); - if (!handle) { - DEBUG(0, ("Unable to load libnss_ldap module with path, error: %s\n", dlerror())); - ret = ELIBACC; - goto done; - } - - ctx->ops.getpwnam_r = dlsym(handle, "_nss_ldap_getpwnam_r"); - if (!ctx->ops.getpwnam_r) { - DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); - ret = ELIBBAD; - goto done; - } - - ctx->ops.getpwuid_r = dlsym(handle, "_nss_ldap_getpwuid_r"); - if (!ctx->ops.getpwuid_r) { - DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); - ret = ELIBBAD; - goto done; - } - - ctx->ops.setpwent = dlsym(handle, "_nss_ldap_setpwent"); - if (!ctx->ops.setpwent) { - DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); - ret = ELIBBAD; - goto done; - } - - ctx->ops.getpwent_r = dlsym(handle, "_nss_ldap_getpwent_r"); - if (!ctx->ops.getpwent_r) { - DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); - ret = ELIBBAD; - goto done; - } - - ctx->ops.endpwent = dlsym(handle, "_nss_ldap_endpwent"); - if (!ctx->ops.endpwent) { - DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); - ret = ELIBBAD; - goto done; - } - - ctx->ops.getgrnam_r = dlsym(handle, "_nss_ldap_getgrnam_r"); - if (!ctx->ops.getgrnam_r) { - DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); - ret = ELIBBAD; - goto done; - } - - ctx->ops.getgrgid_r = dlsym(handle, "_nss_ldap_getgrgid_r"); - if (!ctx->ops.getgrgid_r) { - DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); - ret = ELIBBAD; - goto done; - } - - ctx->ops.setgrent = dlsym(handle, "_nss_ldap_setgrent"); - if (!ctx->ops.setgrent) { - DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); - ret = ELIBBAD; - goto done; - } - - ctx->ops.getgrent_r = dlsym(handle, "_nss_ldap_getgrent_r"); - if (!ctx->ops.getgrent_r) { - DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); - ret = ELIBBAD; - goto done; - } - - ctx->ops.endgrent = dlsym(handle, "_nss_ldap_endgrent"); - if (!ctx->ops.endgrent) { - DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); - ret = ELIBBAD; - goto done; - } - - ctx->ops.initgroups_dyn = dlsym(handle, "_nss_ldap_initgroups_dyn"); - if (!ctx->ops.initgroups_dyn) { - DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); - ret = ELIBBAD; - goto done; - } - - *ops = &ldap_mod_ops; - *pvt_data = ctx; - ret = EOK; - -done: - if (ret != EOK) { - talloc_free(ctx); - } - return ret; -} diff --git a/server/providers/proxy.c b/server/providers/proxy.c new file mode 100644 index 000000000..b5674490e --- /dev/null +++ b/server/providers/proxy.c @@ -0,0 +1,281 @@ +/* + SSSD + + Proxy Module + + Copyright (C) Simo Sorce 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . +*/ + +#include +#include +#include +#include +#include "util/util.h" +#include "providers/dp_backend.h" + +struct proxy_nss_ops { + enum nss_status (*getpwnam_r)(const char *name, struct passwd *result, + char *buffer, size_t buflen, int *errnop); + enum nss_status (*getpwuid_r)(uid_t uid, struct passwd *result, + char *buffer, size_t buflen, int *errnop); + enum nss_status (*setpwent)(void); + enum nss_status (*getpwent_r)(struct passwd *result, + char *buffer, size_t buflen, int *errnop); + enum nss_status (*endpwent)(void); + + enum nss_status (*getgrnam_r)(const char *name, struct group *result, + char *buffer, size_t buflen, int *errnop); + enum nss_status (*getgrgid_r)(gid_t gid, struct group *result, + char *buffer, size_t buflen, int *errnop); + enum nss_status (*setgrent)(void); + enum nss_status (*getgrent_r)(struct group *result, + char *buffer, size_t buflen, int *errnop); + enum nss_status (*endgrent)(void); + enum nss_status (*initgroups_dyn)(const char *user, gid_t group, + long int *start, long int *size, + gid_t **groups, long int limit, + int *errnop); +}; + +struct proxy_ctx { + struct proxy_nss_ops ops; +}; + +static int get_pw_name(struct be_ctx *be_ctx, struct proxy_ctx *proxy_ctx, char *name) +{ + struct proxy_nss_ops *ops = &proxy_ctx->ops; + enum nss_status status; + struct passwd result; + char *buffer; + int ret; + + buffer = talloc_size(NULL, 4096); + if (!buffer) return ENOMEM; + + status = ops->getpwnam_r(name, &result, buffer, 4096, &ret); + + switch (status) { + case NSS_STATUS_NOTFOUND: + ret = dp_be_remove_account_posix(be_ctx, name); + break; + case NSS_STATUS_SUCCESS: + ret = dp_be_store_account_posix(be_ctx, name, result.pw_passwd, + result.pw_uid, result.pw_gid, + result.pw_gecos, result.pw_dir, + result.pw_shell); + break; + default: + DEBUG(2, ("proxy -> getpwnam_r failed for '%s' (%d)[%s]\n", + name, ret, strerror(ret))); + talloc_free(buffer); + return ret; + } + + if (ret != EOK) { + DEBUG(1, ("Failed to update LDB Cache for '%s' (%d) !?\n", + name, ret)); + } + + talloc_free(buffer); + return ret; +} + +static int proxy_check_online(struct be_ctx *be_ctx, int *reply) +{ + *reply = MOD_ONLINE; + return EOK; +} + +static int proxy_get_account_info(struct be_ctx *be_ctx, + int entry_type, int attr_type, + int filter_type, char *filter_value) +{ + struct proxy_ctx *ctx; + + ctx = talloc_get_type(be_ctx->pvt_data, struct proxy_ctx); + + switch (entry_type) { + case BE_REQ_USER: /* user */ + switch (filter_type) { + case BE_FILTER_NAME: + switch (attr_type) { + case BE_ATTR_CORE: + if (strchr(filter_value, '*')) { + /* TODO */ + } else { + return get_pw_name(be_ctx, ctx, filter_value); + } + break; + default: + return EINVAL; + } + break; + case BE_FILTER_IDNUM: + break; + default: + return EINVAL; + } + break; + + case BE_REQ_GROUP: /* group */ + /* TODO */ + return EOK; + + default: /*fail*/ + return EINVAL; + } + + return EOK; +} + +struct be_mod_ops proxy_mod_ops = { + .check_online = proxy_check_online, + .get_account_info = proxy_get_account_info +}; + +static void *proxy_dlsym(void *handle, const char *functemp, char *libname) +{ + char *funcname; + void *funcptr; + + funcname = talloc_asprintf(NULL, functemp, libname); + if (funcname == NULL) return NULL; + + funcptr = dlsym(handle, funcname); + talloc_free(funcname); + + return funcptr; +} + +int sssm_proxy_init(struct be_ctx *bectx, struct be_mod_ops **ops, void **pvt_data) +{ + struct proxy_ctx *ctx; + char *libname; + char *libpath; + void *handle; + int ret; + + ctx = talloc(bectx, struct proxy_ctx); + if (!ctx) { + return ENOMEM; + } + + ret = confdb_get_string(bectx->cdb, ctx, bectx->conf_path, + "libName", NULL, &libname); + ret = confdb_get_string(bectx->cdb, ctx, bectx->conf_path, + "libPath", NULL, &libpath); + if (ret != EOK) goto done; + if (libpath == NULL || libname == NULL) { + ret = ENOENT; + goto done; + } + + handle = dlopen(libpath, RTLD_NOW); + if (!handle) { + DEBUG(0, ("Unable to load %s module with path, error: %s\n", + libpath, dlerror())); + ret = ELIBACC; + goto done; + } + + ctx->ops.getpwnam_r = proxy_dlsym(handle, "_nss_%s_getpwnam_r", libname); + if (!ctx->ops.getpwnam_r) { + DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); + ret = ELIBBAD; + goto done; + } + + ctx->ops.getpwuid_r = proxy_dlsym(handle, "_nss_%s_getpwuid_r", libname); + if (!ctx->ops.getpwuid_r) { + DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); + ret = ELIBBAD; + goto done; + } + + ctx->ops.setpwent = proxy_dlsym(handle, "_nss_%s_setpwent", libname); + if (!ctx->ops.setpwent) { + DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); + ret = ELIBBAD; + goto done; + } + + ctx->ops.getpwent_r = proxy_dlsym(handle, "_nss_%s_getpwent_r", libname); + if (!ctx->ops.getpwent_r) { + DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); + ret = ELIBBAD; + goto done; + } + + ctx->ops.endpwent = proxy_dlsym(handle, "_nss_%s_endpwent", libname); + if (!ctx->ops.endpwent) { + DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); + ret = ELIBBAD; + goto done; + } + + ctx->ops.getgrnam_r = proxy_dlsym(handle, "_nss_%s_getgrnam_r", libname); + if (!ctx->ops.getgrnam_r) { + DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); + ret = ELIBBAD; + goto done; + } + + ctx->ops.getgrgid_r = proxy_dlsym(handle, "_nss_%s_getgrgid_r", libname); + if (!ctx->ops.getgrgid_r) { + DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); + ret = ELIBBAD; + goto done; + } + + ctx->ops.setgrent = proxy_dlsym(handle, "_nss_%s_setgrent", libname); + if (!ctx->ops.setgrent) { + DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); + ret = ELIBBAD; + goto done; + } + + ctx->ops.getgrent_r = proxy_dlsym(handle, "_nss_%s_getgrent_r", libname); + if (!ctx->ops.getgrent_r) { + DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); + ret = ELIBBAD; + goto done; + } + + ctx->ops.endgrent = proxy_dlsym(handle, "_nss_%s_endgrent", libname); + if (!ctx->ops.endgrent) { + DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); + ret = ELIBBAD; + goto done; + } + + ctx->ops.initgroups_dyn = proxy_dlsym(handle, "_nss_%s_initgroups_dyn", + libname); + if (!ctx->ops.initgroups_dyn) { + DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror())); + ret = ELIBBAD; + goto done; + } + + *ops = &proxy_mod_ops; + *pvt_data = ctx; + ret = EOK; + +done: + if (ret != EOK) { + talloc_free(ctx); + } + return ret; +} diff --git a/server/server.mk b/server/server.mk index 9435db0c6..30ee91267 100644 --- a/server/server.mk +++ b/server/server.mk @@ -21,8 +21,8 @@ DP_BE_OBJ = \ providers/data_provider_be.o \ providers/dp_backend_store.o -LDAP_BE_OBJ = \ - providers/ldap_provider.o +PROXY_BE_OBJ = \ + providers/proxy.o NSSSRV_OBJ = \ nss/nsssrv.o \ @@ -47,5 +47,5 @@ sbin/sssd_dp: $(DP_OBJ) $(UTIL_OBJ) sbin/sssd_be: $(DP_BE_OBJ) $(UTIL_OBJ) $(CC) -Wl,-E -o sbin/sssd_be $(DP_BE_OBJ) $(UTIL_OBJ) $(LDFLAGS) $(LIBS) -lib/libsss_ldap.$(SHLIBEXT): $(LDAP_BE_OBJ) - $(SHLD) $(SHLD_FLAGS) -o $@ $(LDAP_BE_OBJ) $(LDFLAGS) $(LIBS) +lib/libsss_proxy.$(SHLIBEXT): $(PROXY_BE_OBJ) + $(SHLD) $(SHLD_FLAGS) -o $@ $(PROXY_BE_OBJ) $(LDFLAGS) $(LIBS) -- cgit