static errno_t proxy_id_load_symbols(struct proxy_nss_ops *ops, const char *libname, void *handle) { int i; struct {void **dest; const char *name; const char *custom_error; bool is_fatal; } symbols[] = { {(void**)&ops->getpwnam_r, "getpwnam_r", NULL, true}, {(void**)&ops->getpwuid_r, "getpwuid_r", NULL, true}, {(void**)&ops->setpwent, "setpwent", NULL, true}, {(void**)&ops->getpwent_r, "getpwent_r", NULL, true}, {(void**)&ops->endpwent, "endpwent", NULL, true}, {(void**)&ops->getgrnam_r, "getgrnam_r", NULL, true}, {(void**)&ops->getgrgid_r, "getgrgid_r", NULL, true}, {(void**)&ops->setgrent, "setgrent", NULL, true}, {(void**)&ops->getgrent_r, "getgrent_r", NULL, true}, {(void**)&ops->endgrent, "endgrent", NULL, true}, {(void**)&ops->initgroups_dyn, "initgroups_dyn", ERROR_INITGR, false}, {(void**)&ops->setnetgrent, "setnetgrent", ERROR_NETGR, false}, {(void**)&ops->getnetgrent_r, "getnetgrent_r", ERROR_NETGR, false}, {(void**)&ops->endnetgrent, "endnetgrent", ERROR_NETGR, false}, {(void**)&ops->getservbyname_r, "getservbyname_r", ERROR_SERV, false}, {(void**)&ops->getservbyport_r, "getservbyport_r", ERROR_SERV, false}, {(void**)&ops->setservent, "setservent", ERROR_SERV, false}, {(void**)&ops->getservent_r, "getservent_r", ERROR_SERV, false}, {(void**)&ops->endservent, "endservent", ERROR_SERV, false}, {NULL, NULL, NULL, false} }; for (i = 0; symbols[i].dest != NULL; i++) { *symbols[i].dest = proxy_dlsym(handle, symbols[i].name, libname); if (*symbols[i].dest == NULL) { DEBUG(SSSDBG_FATAL_FAILURE, "Failed to load _nss_%s_%s, " "error: %s.\n", libname, symbols[i].name, dlerror()); if (symbols[i].custom_error != NULL) { DEBUG(SSSDBG_CRIT_FAILURE, symbols[i].custom_error, libname); } if (symbols[i].is_fatal) { return ELIBBAD; } } } return EOK; }
int sssm_proxy_id_init(struct be_ctx *bectx, struct bet_ops **ops, void **pvt_data) { struct proxy_id_ctx *ctx; char *libname; char *libpath; int ret; ctx = talloc_zero(bectx, struct proxy_id_ctx); if (!ctx) { return ENOMEM; } ctx->be = bectx; ret = confdb_get_string(bectx->cdb, ctx, bectx->conf_path, CONFDB_PROXY_LIBNAME, NULL, &libname); if (ret != EOK) goto done; if (libname == NULL) { ret = ENOENT; goto done; } ret = confdb_get_bool(bectx->cdb, bectx->conf_path, CONFDB_PROXY_FAST_ALIAS, false, &ctx->fast_alias); if (ret != EOK) goto done; libpath = talloc_asprintf(ctx, "libnss_%s.so.2", libname); if (!libpath) { ret = ENOMEM; goto done; } ctx->handle = dlopen(libpath, RTLD_NOW); if (!ctx->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(ctx->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(ctx->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(ctx->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(ctx->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(ctx->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(ctx->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(ctx->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(ctx->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(ctx->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(ctx->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(ctx->handle, "_nss_%s_initgroups_dyn", libname); if (!ctx->ops.initgroups_dyn) { DEBUG(1, ("The '%s' library does not provides the " "_nss_XXX_initgroups_dyn function!\n" "initgroups will be slow as it will require " "full groups enumeration!\n", libname)); } ctx->ops.setnetgrent = proxy_dlsym(ctx->handle, "_nss_%s_setnetgrent", libname); if (!ctx->ops.setnetgrent) { DEBUG(0, ("Failed to load _nss_%s_setnetgrent, error: %s. " "The library does not support netgroups.\n", libname, dlerror())); } ctx->ops.getnetgrent_r = proxy_dlsym(ctx->handle, "_nss_%s_getnetgrent_r", libname); if (!ctx->ops.getgrent_r) { DEBUG(0, ("Failed to load _nss_%s_getnetgrent_r, error: %s. " "The library does not support netgroups.\n", libname, dlerror())); } ctx->ops.endnetgrent = proxy_dlsym(ctx->handle, "_nss_%s_endnetgrent", libname); if (!ctx->ops.endnetgrent) { DEBUG(0, ("Failed to load _nss_%s_endnetgrent, error: %s. " "The library does not support netgroups.\n", libname, dlerror())); } ctx->ops.getservbyname_r = proxy_dlsym(ctx->handle, "_nss_%s_getservbyname_r", libname); if (!ctx->ops.getservbyname_r) { DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to load _nss_%s_getservbyname_r, error: %s. " "The library does not support services.\n", libname, dlerror())); } ctx->ops.getservbyport_r = proxy_dlsym(ctx->handle, "_nss_%s_getservbyport_r", libname); if (!ctx->ops.getservbyport_r) { DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to load _nss_%s_getservbyport_r, error: %s. " "The library does not support services.\n", libname, dlerror())); } ctx->ops.setservent = proxy_dlsym(ctx->handle, "_nss_%s_setservent", libname); if (!ctx->ops.setservent) { DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to load _nss_%s_setservent, error: %s. " "The library does not support services.\n", libname, dlerror())); } ctx->ops.getservent_r = proxy_dlsym(ctx->handle, "_nss_%s_getservent_r", libname); if (!ctx->ops.getservent_r) { DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to load _nss_%s_getservent_r, error: %s. " "The library does not support services.\n", libname, dlerror())); } ctx->ops.endservent = proxy_dlsym(ctx->handle, "_nss_%s_endservent", libname); if (!ctx->ops.endservent) { DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to load _nss_%s_endservent, error: %s. " "The library does not support services.\n", libname, dlerror())); } *ops = &proxy_id_ops; *pvt_data = ctx; ret = EOK; done: if (ret != EOK) { talloc_free(ctx); } return ret; }