/* SSSD nscd.c Copyright (C) Jakub Hrozek 2010 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 "config.h" #include #include #include #include #include #include "util/util.h" #include "tools/tools_util.h" #ifndef NSCD_RELOAD_ARG #define NSCD_RELOAD_ARG "-i" #endif #if defined(NSCD_PATH) && defined(HAVE_NSCD) int flush_nscd_cache(enum nscd_db flush_db) { const char *service; pid_t nscd_pid; int ret, status; switch(flush_db) { case NSCD_DB_PASSWD: service = "passwd"; break; case NSCD_DB_GROUP: service = "group"; break; default: DEBUG(SSSDBG_CRIT_FAILURE, "Unknown nscd database\n"); ret = EINVAL; goto done; } nscd_pid = fork(); switch (nscd_pid) { case 0: execl(NSCD_PATH, "nscd", NSCD_RELOAD_ARG, service, NULL); /* if this returns it is an error */ DEBUG(SSSDBG_CRIT_FAILURE, "execl(3) failed: %d(%s)\n", errno, strerror(errno)); exit(errno); case -1: DEBUG(SSSDBG_CRIT_FAILURE, "fork failed\n"); ret = EFAULT; break; default: do { errno = 0; ret = waitpid(nscd_pid, &status, 0); } while (ret == -1 && errno == EINTR); if (ret > 0) { if (WIFEXITED(status)) { ret = WEXITSTATUS(status); if (ret > 0) { /* The flush fails if nscd is not running, so do not care * about the return code */ DEBUG(SSSDBG_TRACE_INTERNAL, "Error flushing cache, is nscd running?\n"); } } } else { DEBUG(SSSDBG_FUNC_DATA, "Failed to wait for children %d\n", nscd_pid); ret = EIO; } } done: return ret; } #else /* defined(NSCD_PATH) && defined(HAVE_NSCD) */ int flush_nscd_cache(enum nscd_db flush_db) { return EOK; } #endif /* NSCD config file parse and check */ static unsigned int sss_nscd_check_service(char* svc_name) { struct sss_nscd_db { const char *svc_type_name; unsigned int nscd_service_flag; }; int i; unsigned int ret = 0; struct sss_nscd_db db[] = { { "passwd", 0x0001 }, { "group", 0x0010 }, { "netgroup", 0x0100 }, { "services", 0x1000 }, { NULL, 0 } }; if (svc_name == NULL) { return ret; } for (i = 0; db[i].svc_type_name != NULL; i++) { if (!strcmp(db[i].svc_type_name, svc_name)) { ret = db[i].nscd_service_flag; break; } } return ret; } errno_t sss_nscd_parse_conf(const char *conf_path) { FILE *fp; int ret = EOK; unsigned int occured = 0; char *line, *entry, *service, *enabled, *pad; size_t linelen = 0; fp = fopen(conf_path, "r"); if (fp == NULL) { DEBUG(SSSDBG_MINOR_FAILURE, "Couldn't open NSCD configuration " "file [%s]\n", NSCD_CONF_PATH); return ENOENT; } while (getline(&line, &linelen, fp) != -1) { pad = strchr(line, '#'); if (pad != NULL) { *pad = '\0'; } if (line[0] == '\n' || line[0] == '\0') continue; entry = line; while (isspace(*entry) && *entry != '\0') { entry++; } pad = entry; while (!isspace(*pad) && *pad != '\0') { pad++; } service = pad; while (isspace(*service) && *service != '\0') { service++; } *pad = '\0'; pad = service; while (!isspace(*pad) && *pad != '\0') { pad++; } enabled = pad; while (isspace(*enabled) && *enabled != '\0') { enabled++; } *pad = '\0'; pad = enabled; while (!isspace(*pad) && *pad != '\0') { pad++; } *pad = '\0'; if (!strcmp(entry, "enable-cache") && !strcmp(enabled, "yes")) { occured |= sss_nscd_check_service(service); } }; ret = ferror(fp); if (ret) { DEBUG(SSSDBG_MINOR_FAILURE, "Reading NSCD configuration file [%s] " "ended with failure [%d]: %s.\n", NSCD_CONF_PATH, ret, strerror(ret)); ret = ENOENT; goto done; } ret = EOK; if (occured != 0) { ret = EEXIST; goto done; } done: free(line); fclose(fp); return ret; }