From 49fd293f200e3ecdd5665e62c6fdc18f33a9cdd1 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 30 Apr 2016 01:56:06 -0500 Subject: [PATCH] authd: change to lists instead of dictionaries for various things Iteration is the primary thing done on these, so using a dictionary doesn't help a lot. Furthermore (and most importantly), they are not safe to delete from. --- authd/provider.c | 106 ++++++++++++++++++++++++------------ authd/provider.h | 19 +++---- authd/providers/blacklist.c | 6 +- authd/providers/ident.c | 7 ++- authd/providers/opm.c | 42 +++++++------- authd/providers/rdns.c | 7 ++- 6 files changed, 112 insertions(+), 75 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index 57aa963d..8c498b50 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -47,26 +47,56 @@ */ #include "stdinc.h" -#include "rb_dictionary.h" +#include "rb_lib.h" #include "authd.h" #include "provider.h" #include "notice.h" static EVH provider_timeout_event; -rb_dictionary *auth_clients; -rb_dictionary *auth_providers; /* Referenced by name */ +rb_dlink_list auth_clients; +rb_dlink_list auth_providers; static rb_dlink_list free_pids; static uint32_t pid; static struct ev_entry *timeout_ev; +struct auth_client * +find_client(uint16_t cid) +{ + rb_dlink_node *ptr; + + RB_DLINK_FOREACH(ptr, auth_clients.head) + { + struct auth_client *auth = ptr->data; + + if(auth->cid == cid) + return auth; + } + + return NULL; +} + +struct auth_provider * +find_provider(const char *name) +{ + rb_dlink_node *ptr; + + RB_DLINK_FOREACH(ptr, auth_providers.head) + { + struct auth_provider *provider = ptr->data; + + if(strcasecmp(provider->name, name) == 0) + return provider; + } + + return NULL; +} + /* Initalise all providers */ void init_providers(void) { - auth_clients = rb_dictionary_create("pending auth clients", rb_uint32cmp); - auth_providers = rb_dictionary_create("auth providers", strcmp); timeout_ev = rb_event_addish("provider_timeout_event", provider_timeout_event, NULL, 1); load_provider(&rdns_provider); @@ -79,27 +109,29 @@ init_providers(void) void destroy_providers(void) { - rb_dlink_node *ptr; - rb_dictionary_iter iter; - struct auth_client *auth; - struct auth_provider *provider; + rb_dlink_node *ptr, *nptr; /* Cancel outstanding connections */ - RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) + RB_DLINK_FOREACH_SAFE(ptr, nptr, auth_clients.head) { - /* TBD - is this the right thing? */ + struct auth_client *auth = ptr->data; + + /* XXX - Is it right to reject clients like this? + * XXX - double iteration */ reject_client(auth, UINT32_MAX, "destroy", "Authentication system is down... try reconnecting in a few seconds"); } - RB_DICTIONARY_FOREACH(provider, &iter, auth_providers) + RB_DLINK_FOREACH_SAFE(ptr, nptr, auth_providers.head) { + struct auth_provider *provider = ptr->data; + if(provider->destroy) provider->destroy(); + + rb_dlinkDelete(ptr, &auth_providers); } - rb_dictionary_destroy(auth_clients, NULL, NULL); - rb_dictionary_destroy(auth_providers, NULL, NULL); rb_event_delete(timeout_ev); } @@ -141,7 +173,7 @@ load_provider(struct auth_provider *provider) if(provider->init != NULL) provider->init(); - rb_dictionary_add(auth_providers, provider->name, provider); + rb_dlinkAdd(provider, &provider->node, &auth_providers); } void @@ -161,7 +193,7 @@ unload_provider(struct auth_provider *provider) if(provider->destroy != NULL) provider->destroy(); - rb_dictionary_delete(auth_providers, provider->name); + rb_dlinkDelete(&provider->node, &auth_providers); /* Reclaim ID */ rb_dlinkAddAlloc(RB_UINT_TO_POINTER(provider->id), &free_pids); @@ -175,18 +207,19 @@ cancel_providers(struct auth_client *auth) { if(auth->refcount > 0) { - rb_dictionary_iter iter; - struct auth_provider *provider; + rb_dlink_node *ptr; - RB_DICTIONARY_FOREACH(provider, &iter, auth_providers) + RB_DLINK_FOREACH(ptr, auth_providers.head) { + struct auth_provider *provider = ptr->data; + if(provider->cancel != NULL && is_provider_running(auth, provider->id)) /* Cancel if required */ provider->cancel(auth); } } - rb_dictionary_delete(auth_clients, RB_UINT_TO_POINTER(auth->cid)); + rb_dlinkDelete(&auth->node, &auth_clients); rb_free(auth->data); rb_free(auth); } @@ -196,8 +229,7 @@ cancel_providers(struct auth_client *auth) void provider_done(struct auth_client *auth, uint32_t id) { - rb_dictionary_iter iter; - struct auth_provider *provider; + rb_dlink_node *ptr; lrb_assert(is_provider_running(auth, id)); lrb_assert(id != UINT32_MAX); @@ -212,8 +244,10 @@ provider_done(struct auth_client *auth, uint32_t id) return; } - RB_DICTIONARY_FOREACH(provider, &iter, auth_providers) + RB_DLINK_FOREACH(ptr, auth_providers.head) { + struct auth_provider *provider = ptr->data; + if(provider->completed != NULL && is_provider_running(auth, provider->id)) /* Notify pending clients who asked for it */ provider->completed(auth, id); @@ -267,18 +301,17 @@ accept_client(struct auth_client *auth, uint32_t id) static void start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_ip, const char *c_port) { - struct auth_provider *provider; struct auth_client *auth = rb_malloc(sizeof(struct auth_client)); long lcid = strtol(cid, NULL, 16); - rb_dictionary_iter iter; + rb_dlink_node *ptr; if(lcid >= UINT32_MAX) return; auth->cid = (uint32_t)lcid; - if(rb_dictionary_find(auth_clients, RB_UINT_TO_POINTER(auth->cid)) == NULL) - rb_dictionary_add(auth_clients, RB_UINT_TO_POINTER(auth->cid), auth); + if(find_client(auth->cid) == NULL) + rb_dlinkAdd(auth, &auth->node, &auth_clients); else { warn_opers(L_CRIT, "provider: duplicate client added via start_auth: %x", auth->cid); @@ -298,12 +331,14 @@ start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_ rb_strlcpy(auth->hostname, "*", sizeof(auth->hostname)); rb_strlcpy(auth->username, "*", sizeof(auth->username)); - auth->data = rb_malloc(rb_dictionary_size(auth_providers) * + auth->data = rb_malloc(rb_dlink_list_length(&auth_providers) * sizeof(struct auth_client_data)); auth->providers_starting = true; - RB_DICTIONARY_FOREACH(provider, &iter, auth_providers) + RB_DLINK_FOREACH(ptr, auth_providers.head) { + struct auth_provider *provider = ptr->data; + auth->data[provider->id].provider = provider; lrb_assert(provider->start != NULL); @@ -351,7 +386,7 @@ handle_cancel_connection(int parc, char *parv[]) exit(EX_PROVIDER_ERROR); } - if((auth = rb_dictionary_retrieve(auth_clients, RB_UINT_TO_POINTER((uint32_t)lcid))) == NULL) + if((auth = find_client(lcid)) == NULL) { /* This could happen as a race if we've accepted/rejected but they cancel, so don't die here. * --Elizafox */ @@ -365,16 +400,17 @@ static void provider_timeout_event(void *notused __unused) { struct auth_client *auth; - rb_dictionary_iter iter; const time_t curtime = rb_current_time(); + rb_dlink_node *ptr, *nptr; - RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) + RB_DLINK_FOREACH_SAFE(ptr, nptr, auth_clients.head) { - rb_dictionary_iter iter2; - struct auth_provider *provider; + struct auth_client *auth = ptr->data; + rb_dlink_node *ptr2; - RB_DICTIONARY_FOREACH(provider, &iter2, auth_providers) + RB_DLINK_FOREACH(ptr2, auth_providers.head) { + struct auth_provider *provider = ptr2->data; const time_t timeout = get_provider_timeout(auth, provider->id); if(is_provider_running(auth, provider->id) && provider->timeout != NULL && diff --git a/authd/provider.h b/authd/provider.h index a4f2ed8c..dc493509 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -44,6 +44,8 @@ struct auth_client_data struct auth_client { + rb_dlink_node node; + uint16_t cid; /* Client ID */ char l_ip[HOSTIPLEN + 1]; /* Listener IP address */ @@ -104,8 +106,12 @@ extern struct auth_provider ident_provider; extern struct auth_provider blacklist_provider; extern struct auth_provider opm_provider; -extern rb_dictionary *auth_providers; -extern rb_dictionary *auth_clients; +extern rb_dlink_list auth_providers; +extern rb_dlink_list auth_clients; + +struct auth_client * find_client(uint16_t cid); + +struct auth_provider * find_provider(const char *name); void load_provider(struct auth_provider *provider); void unload_provider(struct auth_provider *provider); @@ -122,18 +128,11 @@ void handle_new_connection(int parc, char *parv[]); void handle_cancel_connection(int parc, char *parv[]); -/* Get a provider by name */ -static inline struct auth_provider * -get_provider(const char *name) -{ - return rb_dictionary_retrieve(auth_providers, name); -} - /* Get a provider's id by name */ static inline bool get_provider_id(const char *name, uint32_t *id) { - struct auth_provider *provider = get_provider(name); + struct auth_provider *provider = find_provider(name); if(provider != NULL) { diff --git a/authd/providers/blacklist.c b/authd/providers/blacklist.c index 769a34a4..2579b655 100644 --- a/authd/providers/blacklist.c +++ b/authd/providers/blacklist.c @@ -421,11 +421,11 @@ blacklists_cancel(struct auth_client *auth) static void blacklists_destroy(void) { - rb_dictionary_iter iter; - struct auth_client *auth; + rb_dlink_node *ptr, *nptr; - RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) + RB_DLINK_FOREACH_SAFE(ptr, nptr, auth_clients.head) { + struct auth_client *auth = ptr->data; blacklists_cancel(auth); } diff --git a/authd/providers/ident.c b/authd/providers/ident.c index 959bdb57..0cccfd32 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -275,12 +275,13 @@ get_valid_ident(char *buf) static void ident_destroy(void) { - struct auth_client *auth; - rb_dictionary_iter iter; + rb_dlink_node *ptr, *nptr; /* Nuke all ident queries */ - RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) + RB_DLINK_FOREACH_SAFE(ptr, nptr, auth_clients.head) { + struct auth_client *auth = ptr->data; + if(get_provider_data(auth, SELF_PID) != NULL) client_fail(auth, REPORT_FAIL); } diff --git a/authd/providers/opm.c b/authd/providers/opm.c index ca3cfd2b..bfa61815 100644 --- a/authd/providers/opm.c +++ b/authd/providers/opm.c @@ -196,11 +196,10 @@ read_opm_reply(rb_fde_t *F, void *data) static void accept_opm(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t len, void *data) { - struct auth_client *auth = NULL; struct opm_listener *listener = data; struct rb_sockaddr_storage localaddr; unsigned int llen = sizeof(struct rb_sockaddr_storage); - rb_dictionary_iter iter; + rb_dlink_node *ptr; if(status != 0 || listener == NULL) { @@ -216,8 +215,10 @@ accept_opm(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t len, voi } /* Correlate connection with client(s) */ - RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) + RB_DLINK_FOREACH(ptr, auth_clients.head) { + struct auth_client *auth = ptr->data; + if(GET_SS_FAMILY(&auth->c_addr) != GET_SS_FAMILY(&localaddr)) continue; @@ -467,10 +468,9 @@ establish_connection(struct auth_client *auth, struct opm_proxy *proxy) static bool create_listener(const char *ip, uint16_t port) { - struct auth_client *auth; struct opm_listener *listener; struct rb_sockaddr_storage addr; - rb_dictionary_iter iter; + rb_dlink_node *ptr, *nptr; rb_fde_t *F; int opt = 1; @@ -560,8 +560,9 @@ create_listener(const char *ip, uint16_t port) /* Cancel clients that may be on old listener * XXX - should rescan clients that need it */ - RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) + RB_DLINK_FOREACH_SAFE(ptr, nptr, auth_clients.head) { + struct auth_client *auth = ptr->data; opm_cancel(auth); } @@ -674,12 +675,12 @@ opm_cancel(struct auth_client *auth) static void opm_destroy(void) { - struct auth_client *auth; - rb_dictionary_iter iter; + rb_dlink_node *ptr, *nptr; /* Nuke all opm lookups */ - RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) + RB_DLINK_FOREACH_SAFE(ptr, nptr, auth_clients.head) { + struct auth_client *auth = ptr->data; opm_cancel(auth); } } @@ -708,8 +709,7 @@ set_opm_enabled(const char *key __unused, int parc __unused, const char **parv) { if(listeners[LISTEN_IPV4].F != NULL || listeners[LISTEN_IPV6].F != NULL) { - struct auth_client *auth; - rb_dictionary_iter iter; + rb_dlink_node *ptr, *nptr; /* Close the listening socket */ if(listeners[LISTEN_IPV4].F != NULL) @@ -720,8 +720,9 @@ set_opm_enabled(const char *key __unused, int parc __unused, const char **parv) listeners[LISTEN_IPV4].F = listeners[LISTEN_IPV6].F = NULL; - RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) + RB_DLINK_FOREACH_SAFE(ptr, nptr, auth_clients.head) { + struct auth_client *auth = ptr->data; opm_cancel(auth); } } @@ -814,11 +815,10 @@ create_opm_scanner(const char *key __unused, int parc __unused, const char **par static void delete_opm_scanner(const char *key __unused, int parc __unused, const char **parv) { - struct auth_client *auth; struct opm_proxy *proxy; protocol_t proto = get_protocol_from_string(parv[0]); int iport = atoi(parv[1]); - rb_dictionary_iter iter; + rb_dlink_node *ptr, *nptr; if(iport <= 0 || iport > 65535) { @@ -839,17 +839,18 @@ delete_opm_scanner(const char *key __unused, int parc __unused, const char **par } /* Abort remaining clients on this scanner */ - RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) + RB_DLINK_FOREACH_SAFE(ptr, nptr, auth_clients.head) { - rb_dlink_node *ptr; + struct auth_client *auth = ptr->data; struct opm_lookup *lookup = get_provider_data(auth, SELF_PID); + rb_dlink_node *optr; if(lookup == NULL) continue; - RB_DLINK_FOREACH(ptr, lookup->scans.head) + RB_DLINK_FOREACH(optr, lookup->scans.head) { - struct opm_scan *scan = ptr->data; + struct opm_scan *scan = optr->data; if(scan->proxy->port == proxy->port && scan->proxy->proto == proxy->proto) { @@ -875,9 +876,7 @@ delete_opm_scanner(const char *key __unused, int parc __unused, const char **par static void delete_opm_scanner_all(const char *key __unused, int parc __unused, const char **parv __unused) { - struct auth_client *auth; rb_dlink_node *ptr, *nptr; - rb_dictionary_iter iter; RB_DLINK_FOREACH_SAFE(ptr, nptr, proxy_scanners.head) { @@ -885,8 +884,9 @@ delete_opm_scanner_all(const char *key __unused, int parc __unused, const char * rb_dlinkDelete(ptr, &proxy_scanners); } - RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) + RB_DLINK_FOREACH_SAFE(ptr, nptr, auth_clients.head) { + struct auth_client *auth = ptr->data; opm_cancel(auth); } diff --git a/authd/providers/rdns.c b/authd/providers/rdns.c index d263415a..243a5698 100644 --- a/authd/providers/rdns.c +++ b/authd/providers/rdns.c @@ -112,11 +112,12 @@ client_success(struct auth_client *auth) static void rdns_destroy(void) { - struct auth_client *auth; - rb_dictionary_iter iter; + rb_dlink_node *ptr, *nptr; - RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) + RB_DLINK_FOREACH_SAFE(ptr, nptr, auth_clients.head) { + struct auth_client *auth = ptr->data; + if(get_provider_data(auth, SELF_PID) != NULL) client_fail(auth, REPORT_FAIL); }