From 79602e4b19dcb35febc5b3fd2ee8e6a65c1b701b Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Tue, 16 Dec 2014 03:56:07 -0500 Subject: it now works for a first query, then crashes --- nslcd/cfg.c | 1 + nslcd/db_pam.c | 6 ++- nslcd/db_passwd.c | 10 +++-- nslcd/db_shadow.c | 7 +-- nslcd/hackers.c | 42 +++++++++++++----- nslcd/hackers.h | 14 +++--- nslcd/hackers_parse.c | 18 ++------ nslcd/hackers_parse.h | 14 ++++++ nslcd/hackers_watch.c | 120 ++++++++++++++++++++++++++++++++++++-------------- nslcd/hackers_watch.h | 5 ++- nslcd/nslcd.c | 14 +++--- 11 files changed, 168 insertions(+), 83 deletions(-) diff --git a/nslcd/cfg.c b/nslcd/cfg.c index cd5b213..b0a4847 100644 --- a/nslcd/cfg.c +++ b/nslcd/cfg.c @@ -467,6 +467,7 @@ static void cfg_defaults(struct nslcd_config *cfg) { int i; memset(cfg, 0, sizeof(struct nslcd_config)); + handle_yamldir(__FILE__, __LINE__, "", "/var/cache/parabola-hackers/users", cfg); cfg->threads = 5; cfg->pagesize = 0; cfg->nss_initgroups_ignoreusers = NULL; diff --git a/nslcd/db_pam.c b/nslcd/db_pam.c index e93a04d..c617573 100644 --- a/nslcd/db_pam.c +++ b/nslcd/db_pam.c @@ -105,8 +105,9 @@ NSLCD_HANDLE_UID(PAM, AUTHC { if (STR_CMP(username, session->users[i].pw_name)==0) { *rcp = 0; + size_t n = i; i = session->cnt; - user = &(session->users[i]); + user = &(session->users[n]); } } if (user == NULL) @@ -168,8 +169,9 @@ NSLCD_HANDLE(PAM, AUTHZ { if (STR_CMP(username, session->users[i].pw_name)==0) { *rcp = 0; + size_t n = i; i = session->cnt; - user = &(session->users[i]); + user = &(session->users[n]); } } if (user == NULL) diff --git a/nslcd/db_passwd.c b/nslcd/db_passwd.c index 3ff1181..743f4bc 100644 --- a/nslcd/db_passwd.c +++ b/nslcd/db_passwd.c @@ -99,11 +99,12 @@ NSLCD_HANDLE_UID(PASSWD, BYNAME static size_t i = 0; for (; i < session->cnt; i++) { - if (session->users[i].pw_uid > 0 && + if (session->users[i].pw_uid != UID_INVALID && STR_CMP(name, session->users[i].pw_name)==0) { *rcp = 0; + size_t n = i; i = session->cnt; - return &(session->users[i]); + return &(session->users[n]); } } return NULL; @@ -135,8 +136,9 @@ NSLCD_HANDLE_UID(PASSWD, BYUID { if (uid == session->users[i].pw_uid) { *rcp = 0; + size_t n = i; i = session->cnt; - return &(session->users[i]); + return &(session->users[n]); } } return NULL; @@ -156,7 +158,7 @@ NSLCD_HANDLE_UID(PASSWD, ALL static size_t i = 0; for (; i < session->cnt; i++) { - if (session->users[i].pw_uid > 0) { + if (session->users[i].pw_uid != UID_INVALID) { *rcp = 0; return &(session->users[i]); } diff --git a/nslcd/db_shadow.c b/nslcd/db_shadow.c index d7adf6c..4e4d8e1 100644 --- a/nslcd/db_shadow.c +++ b/nslcd/db_shadow.c @@ -90,12 +90,13 @@ NSLCD_HANDLE_UID(SHADOW, BYNAME static size_t i = 0; for (; i < session->cnt; i++) { - if (session->users[i].pw_uid > 0 && + if (session->users[i].pw_uid != UID_INVALID && STR_CMP(name, session->users[i].pw_name)==0) { *rcp = 0; + size_t n = i; i = session->cnt; - passwd2shadow(&(session->users[i]), &ret); + passwd2shadow(&(session->users[n]), &ret); return &ret; } } @@ -116,7 +117,7 @@ NSLCD_HANDLE_UID(SHADOW, ALL static size_t i = 0; for (; i < session->cnt; i++) { - if (session->users[i].pw_uid > 0) { + if (session->users[i].pw_uid != UID_INVALID) { *rcp = 0; passwd2shadow(&(session->users[i]), &ret); return &ret; diff --git a/nslcd/hackers.c b/nslcd/hackers.c index e7b2525..8f3e6f4 100644 --- a/nslcd/hackers.c +++ b/nslcd/hackers.c @@ -6,38 +6,56 @@ #include "hackers_watch.h" #include "log.h" -void *hackers_session_worker(void *sess) { - hackers_worker(sess); +static +void * +session_worker(void *sess) { + hackers_session_worker(sess); return NULL; } -struct session *hackers_session_create(pthread_t *thread, const char *yamldir) { - struct session *session = malloc(sizeof(struct session)); +struct session * +session_create(const struct nslcd_config *cfg, pthread_t *thread) { + struct session *session = hackers_session_allocate(); if (session == NULL) { - log_log(LOG_CRIT, "hackers_session_create(): malloc() failed to allocate memory"); exit(EXIT_FAILURE); } - hackers_init(yamldir, session); - if (pthread_create(thread, NULL, hackers_session_worker, (void*)session)) { + + if (hackers_session_open(session, cfg->yamldir) != 0) { + exit(EXIT_FAILURE); + } + + if (pthread_create(thread, NULL, session_worker, (void*)session)) { log_log(LOG_ERR, "unable to start hackers worker thread: %s", strerror(errno)); exit(EXIT_FAILURE); } + return session; } -void hackers_session_check(struct session *sess) { +void +session_check(struct session *sess) { /* do nothing */ } -void hackers_session_close(struct session *sess) { - /* do nothing */ +void +session_close(struct session *sess) { + /*hackers_session_close(sess);*/ +} + +void +session_refresh(struct session *sess, const struct nslcd_config *cfg) { + if (hackers_session_open(sess, cfg->yamldir) != 0) { + exit(EXIT_FAILURE); + } } -void hackers_session_messup(struct session *sess) { +void +session_messup(struct session *sess) { pthread_rwlock_rdlock(&(sess->lock)); } -void hackers_session_cleanup(struct session *sess) { +void +session_cleanup(struct session *sess) { pthread_rwlock_unlock(&(sess->lock)); } diff --git a/nslcd/hackers.h b/nslcd/hackers.h index 22643af..b271fee 100644 --- a/nslcd/hackers.h +++ b/nslcd/hackers.h @@ -3,6 +3,7 @@ #include #include +#include "cfg.h" #define GID_INVALID ((gid_t)-1) #define UID_INVALID ((uid_t)-1) @@ -19,12 +20,13 @@ struct session { int in_wd_yaml; }; -/*struct session *hackers_session_create(void);*/ /* create */ -struct session *hackers_session_create(pthread_t *, const char *); -void hackers_session_check(struct session *); /* maintain */ -void hackers_session_close(struct session *); /* destroy */ +/*struct session *session_create(const nslcd_config *);*/ /* create */ +struct session *session_create(const struct nslcd_config *, pthread_t *); +void session_check(struct session *); /* maintain */ +void session_close(struct session *); /* destroy */ +void session_refresh(struct session *, const struct nslcd_config *); /* refresh */ -void hackers_session_messup(struct session *); /* before dispatch */ -void hackers_session_cleanup(struct session *); /* after dispatch */ +void session_messup(struct session *); /* before dispatch */ +void session_cleanup(struct session *); /* after dispatch */ #endif diff --git a/nslcd/hackers_parse.c b/nslcd/hackers_parse.c index 7eb0e4f..1cb1681 100644 --- a/nslcd/hackers_parse.c +++ b/nslcd/hackers_parse.c @@ -52,19 +52,6 @@ ((char*)(node)->data.scalar.value); \ })) -#define MALLOC(size) REALLOC(NULL, size) - -#define REALLOC(ptr, size) \ - (__extension__ ({ \ - errno = 0; \ - void *ret = realloc(ptr, size); \ - if (ret == (ptr)) { \ - error(0, errno, "could not (re)allocate memory"); \ - goto error; \ - }; \ - ret; \ - })) - /* Bitmask flags for the completion of the fields in * 'struct passwd' (which is defined in ) */ #define PW_NAME (1 << 0) @@ -209,10 +196,11 @@ load_user_yaml(const char *filename, struct passwd *user) { for (yaml_node_item_t *itemp = val->data.sequence.items.start; itemp < val->data.sequence.items.top; itemp++) { - yaml_node_t *item = NODE(*itemp); + /*yaml_node_t *item = NODE(*itemp);*/ if (itemp == val->data.sequence.items.start) { /* primary group */ - char *grp_name = STR_VALUE(item); + /* TODO */ + char *grp_name = "users"/*STR_VALUE(item)*/; ASSERT((user->pw_gid = name2gid(grp_name)) != GID_INVALID); flags |= PW_GID; } else { diff --git a/nslcd/hackers_parse.h b/nslcd/hackers_parse.h index 1a092f6..97c779b 100644 --- a/nslcd/hackers_parse.h +++ b/nslcd/hackers_parse.h @@ -5,6 +5,19 @@ #include /* for free(3) */ #include /* for 'struct passwd' */ +#define MALLOC(size) REALLOC(NULL, size) + +#define REALLOC(ptr, size) \ + (__extension__ ({ \ + errno = 0; \ + void *ret = realloc(ptr, size); \ + if (ret == (ptr)) { \ + error(0, errno, "could not (re)allocate memory"); \ + goto error; \ + }; \ + ret; \ + })) + #define ZERO(var) memset(&(var), 0, sizeof(var)) /* Free+zero a 'struct passwd' */ @@ -16,6 +29,7 @@ free((user).pw_dir); \ free((user).pw_shell); \ ZERO(user); \ + (user).pw_uid = UID_INVALID; \ })) /** Returns 0 on error, or the UID on success. Only handles "normal diff --git a/nslcd/hackers_watch.c b/nslcd/hackers_watch.c index 7289c59..e2222fc 100644 --- a/nslcd/hackers_watch.c +++ b/nslcd/hackers_watch.c @@ -26,6 +26,7 @@ #include "common/inotify_helpers.h" #include "hackers_parse.h" #include "hackers_watch.h" +#include "log.h" #define EVENT_FILE_IS(event, str) \ (((event)->len == sizeof(str)) && (strcmp((event)->name, str) == 0)) @@ -44,17 +45,6 @@ } \ } while(0) -#define REALLOC(ptr, size) \ - (__extension__ ({ \ - errno = 0; \ - void *ret = realloc(ptr, size); \ - if (ret == (ptr)) { \ - error(0, errno, "could not (re)allocate memory"); \ - goto error; \ - }; \ - ret; \ - })) - #define WATCH_HOMEDIR(session, i) \ do { \ session->in_user_wds[i] = \ @@ -64,18 +54,85 @@ if (session->in_user_wds[i] < 0) { \ error(0, errno, "could not watch: %s", \ session->users[i].pw_dir); \ - goto error; \ + /* don't goto error, it OK here */ \ } \ } while(0) +struct session * +hackers_session_allocate() { + int err = 0; + struct session *sess; + sess = MALLOC(sizeof(struct session)); + if ((err = pthread_rwlock_init(&(sess->lock), NULL)) != 0) { + error(0, err, "could not initialize session rwlock"); + goto error; + } + sess->cnt = 0; + sess->users = NULL; + sess->yamldir = NULL; + sess->in_user_wds = NULL; + sess->in_fd = -1; + sess->in_wd_home = -1; + sess->in_wd_yaml = -1; + return sess; + error: + return NULL; +} + +static +int +hackers_session_resize(struct session *sess, size_t num_users) { + log_log(LOG_DEBUG, "resizing session to %zu users", num_users); + + if (num_users <= sess->cnt) + return 0; + + sess->users = + REALLOC(sess->users , num_users * sizeof(sess->users[0])); + sess->in_user_wds = + REALLOC(sess->in_user_wds, num_users * sizeof(sess->in_user_wds[0])); + + for (size_t i = sess->cnt; i < num_users; i++) { + ZERO(sess->users[i]); + sess->users[i].pw_uid = UID_INVALID; + sess->in_user_wds[i] = -1; + } + sess->cnt = num_users; + + return 0; + error: + return -1; +} + +/* does NOT mess with the lock */ +static +void +hackers_session_close(struct session *sess) { + log_log(LOG_DEBUG, "closing session"); + + for (size_t i = 0; i < sess->cnt; i++) { + PASSWD_FREE(sess->users[i]); + } + free(sess->users); sess->users = NULL; + sess->cnt = 0; + + free(sess->yamldir); sess->yamldir = NULL; + free(sess->in_user_wds); sess->in_user_wds = NULL; + close(sess->in_fd); sess->in_fd = -1; + sess->in_wd_home = -1; + sess->in_wd_yaml = -1; +} + int -hackers_init(const char *yamldir, struct session *sess) { +hackers_session_open(struct session *sess, const char *yamldir) { + log_log(LOG_DEBUG, "opening session at `%s'", yamldir); char *glob_pattern; glob_t glob_results; char *filename; + hackers_session_close(sess); ASSERT((sess->yamldir = strdup(yamldir)) != NULL); - ASSERT((errno = pthread_rwlock_init(&(sess->lock), NULL)) >= 0); + ASSERT((sess->in_fd = inotify_init()) >= 0); ASSERT((sess->in_wd_yaml = inotify_add_watch(sess->in_fd, yamldir, EVENT_CHILD_ANY)) >= 0); ASSERT((sess->in_wd_home = inotify_add_watch(sess->in_fd, "/home" , EVENT_CHILD_ADD)) >= 0); @@ -83,16 +140,16 @@ hackers_init(const char *yamldir, struct session *sess) { ASSERT(asprintf(&glob_pattern, "%s/*.yml", yamldir) > 0); ASSERT(glob(glob_pattern, 0, NULL, &glob_results) == 0); free(glob_pattern); - - sess->cnt = glob_results.gl_pathc - glob_results.gl_offs; - ASSERT((sess->users = calloc(sess->cnt, sizeof(struct passwd))) != NULL); - ASSERT((sess->in_user_wds = calloc(sess->cnt, sizeof(int))) != NULL); + ASSERT(hackers_session_resize(sess, glob_results.gl_pathc - glob_results.gl_offs)==0); for (size_t i = 0; i < sess->cnt; i++) { filename = glob_results.gl_pathv[glob_results.gl_offs+i]; + log_log(LOG_DEBUG, "loading yaml file: %s", filename); if (load_user_yaml(filename, &(sess->users[i]))==0) { + log_log(LOG_DEBUG, "... and watching homedir"); WATCH_HOMEDIR(sess, i); } else { + log_log(LOG_DEBUG, "... error"); sess->users[i].pw_uid = UID_INVALID; sess->in_user_wds[i] = -1; } @@ -101,7 +158,9 @@ hackers_init(const char *yamldir, struct session *sess) { globfree(&glob_results); return 0; + error: + hackers_session_close(sess); return -1; } @@ -121,20 +180,17 @@ worker_watch_homedirs(struct session *sess) { } } pthread_rwlock_unlock(&(sess->lock)); - return; - error: - exit(1); } static -void +int worker_handle_add_yaml(struct session *sess, struct passwd *newdata) { /* We have to first see if this is for an existing UID, then * if it's not, we need to find an empty slot, potentially * realloc()ing the array. */ - pthread_rwlock_wrlock(&(sess->lock)); ssize_t spot = -1; + pthread_rwlock_wrlock(&(sess->lock)); for (size_t i = 0; i < sess->cnt; i++) { if (spot < 0 && sess->users[i].pw_uid == UID_INVALID) { spot = i; @@ -146,18 +202,17 @@ worker_handle_add_yaml(struct session *sess, struct passwd *newdata) { } if (spot < 0) { /* must grow the array */ - spot = sess->cnt++; - sess->users = REALLOC(sess->users , sess->cnt * sizeof(struct passwd)); - sess->in_user_wds = REALLOC(sess->in_user_wds, sess->cnt * sizeof(int)); - ZERO(sess->users[spot]); + if (hackers_session_resize(sess, sess->cnt+1) != 0) + goto error; } else if (sess->users[spot].pw_uid != UID_INVALID) { PASSWD_FREE(sess->users[spot]); } sess->users[spot] = *newdata; pthread_rwlock_unlock(&(sess->lock)); - return; + return 0; error: - exit(1); + pthread_rwlock_unlock(&(sess->lock)); + return -1; } static @@ -175,7 +230,7 @@ worker_handle_del_yaml(struct session *sess, uid_t uid) { } int -hackers_worker(struct session *sess) { +hackers_session_worker(struct session *sess) { if (chdir(sess->yamldir) < 0) return -1; for (INOTIFY_ITERATOR(sess->in_fd, event)) { @@ -185,7 +240,8 @@ hackers_worker(struct session *sess) { struct passwd user; ZERO(user); if (load_user_yaml(event->name, &user)==0) { /* User added/updated */ - worker_handle_add_yaml(sess, &user); + if (worker_handle_add_yaml(sess, &user) !=0) + return -1; } else if (user.pw_uid != UID_INVALID) { /* User became invalid */ worker_handle_del_yaml(sess, @@ -193,7 +249,7 @@ hackers_worker(struct session *sess) { } } else if (event->mask & EVENT_CHILD_DEL) { uid_t uid = filename2uid(event->name); - if (uid > 0) { + if (uid != UID_INVALID) { worker_handle_del_yaml(sess, uid); } } diff --git a/nslcd/hackers_watch.h b/nslcd/hackers_watch.h index 91e6319..8c7a297 100644 --- a/nslcd/hackers_watch.h +++ b/nslcd/hackers_watch.h @@ -3,7 +3,8 @@ #include "hackers.h" -int hackers_init(const char *yamldir, struct session *session); -int hackers_worker(struct session *session); +struct session * hackers_session_allocate(); +int hackers_session_open(struct session *, const char *yamldir); +int hackers_session_worker(struct session *); #endif diff --git a/nslcd/nslcd.c b/nslcd/nslcd.c index 4a3fd26..d7891e6 100644 --- a/nslcd/nslcd.c +++ b/nslcd/nslcd.c @@ -255,9 +255,9 @@ static void handleconnection(int sock, struct session *session) return; } /* handle request */ - hackers_session_messup(session); + session_messup(session); dispatch(fp, action, session, uid); - hackers_session_cleanup(session); + session_cleanup(session); (void)tio_close(fp); return; @@ -282,7 +282,7 @@ static void install_sighandler(int signum, void (*handler) (int)) static void worker_cleanup(void *arg) { struct session *session = (struct session *)arg; - hackers_session_close(session); + session_close(session); } static void *worker(void *_sess) @@ -294,14 +294,14 @@ static void *worker(void *_sess) socklen_t alen; fd_set fds; /* create a new session */ - /*session = hackers_session_create();*/ + /*session = session_create();*/ /* clean up the session if we're done */ pthread_cleanup_push(worker_cleanup, session); /* start waiting for incoming connections */ while (1) { /* perform any maintenance on the session */ - hackers_session_check(session); + session_check(session); /* set up the set of fds to wait on */ FD_ZERO(&fds); FD_SET(nslcd_serversocket, &fds); @@ -466,7 +466,7 @@ int main(int argc, char *argv[]) log_log(LOG_CRIT, "main(): malloc() failed to allocate memory"); exit(EXIT_FAILURE); } - struct session *session = hackers_session_create(&nslcd_threads[0], nslcd_cfg->yamldir); + struct session *session = session_create(nslcd_cfg, &nslcd_threads[0]); for (i = 1; i < nslcd_cfg->threads; i++) { if (pthread_create(&nslcd_threads[i], NULL, worker, (void*)session)) @@ -495,7 +495,7 @@ int main(int argc, char *argv[]) { log_log(LOG_INFO, "caught signal %s (%d), refresh retries", signame(nslcd_receivedsignal), nslcd_receivedsignal); - /* TODO: force reload yamldir */ + session_refresh(session, nslcd_cfg); nslcd_receivedsignal = 0; } } -- cgit v1.2.3