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.
This commit is contained in:
Elizabeth Myers 2016-04-30 01:56:06 -05:00
parent d71787ab69
commit 49fd293f20
No known key found for this signature in database
GPG key ID: 1A10EF78D83E317B
6 changed files with 112 additions and 75 deletions

View file

@ -47,26 +47,56 @@
*/ */
#include "stdinc.h" #include "stdinc.h"
#include "rb_dictionary.h" #include "rb_lib.h"
#include "authd.h" #include "authd.h"
#include "provider.h" #include "provider.h"
#include "notice.h" #include "notice.h"
static EVH provider_timeout_event; static EVH provider_timeout_event;
rb_dictionary *auth_clients; rb_dlink_list auth_clients;
rb_dictionary *auth_providers; /* Referenced by name */ rb_dlink_list auth_providers;
static rb_dlink_list free_pids; static rb_dlink_list free_pids;
static uint32_t pid; static uint32_t pid;
static struct ev_entry *timeout_ev; 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 */ /* Initalise all providers */
void void
init_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); timeout_ev = rb_event_addish("provider_timeout_event", provider_timeout_event, NULL, 1);
load_provider(&rdns_provider); load_provider(&rdns_provider);
@ -79,27 +109,29 @@ init_providers(void)
void void
destroy_providers(void) destroy_providers(void)
{ {
rb_dlink_node *ptr; rb_dlink_node *ptr, *nptr;
rb_dictionary_iter iter;
struct auth_client *auth;
struct auth_provider *provider;
/* Cancel outstanding connections */ /* 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", reject_client(auth, UINT32_MAX, "destroy",
"Authentication system is down... try reconnecting in a few seconds"); "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) if(provider->destroy)
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); rb_event_delete(timeout_ev);
} }
@ -141,7 +173,7 @@ load_provider(struct auth_provider *provider)
if(provider->init != NULL) if(provider->init != NULL)
provider->init(); provider->init();
rb_dictionary_add(auth_providers, provider->name, provider); rb_dlinkAdd(provider, &provider->node, &auth_providers);
} }
void void
@ -161,7 +193,7 @@ unload_provider(struct auth_provider *provider)
if(provider->destroy != NULL) if(provider->destroy != NULL)
provider->destroy(); provider->destroy();
rb_dictionary_delete(auth_providers, provider->name); rb_dlinkDelete(&provider->node, &auth_providers);
/* Reclaim ID */ /* Reclaim ID */
rb_dlinkAddAlloc(RB_UINT_TO_POINTER(provider->id), &free_pids); rb_dlinkAddAlloc(RB_UINT_TO_POINTER(provider->id), &free_pids);
@ -175,18 +207,19 @@ cancel_providers(struct auth_client *auth)
{ {
if(auth->refcount > 0) if(auth->refcount > 0)
{ {
rb_dictionary_iter iter; rb_dlink_node *ptr;
struct auth_provider *provider;
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)) if(provider->cancel != NULL && is_provider_running(auth, provider->id))
/* Cancel if required */ /* Cancel if required */
provider->cancel(auth); 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->data);
rb_free(auth); rb_free(auth);
} }
@ -196,8 +229,7 @@ cancel_providers(struct auth_client *auth)
void void
provider_done(struct auth_client *auth, uint32_t id) provider_done(struct auth_client *auth, uint32_t id)
{ {
rb_dictionary_iter iter; rb_dlink_node *ptr;
struct auth_provider *provider;
lrb_assert(is_provider_running(auth, id)); lrb_assert(is_provider_running(auth, id));
lrb_assert(id != UINT32_MAX); lrb_assert(id != UINT32_MAX);
@ -212,8 +244,10 @@ provider_done(struct auth_client *auth, uint32_t id)
return; 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)) if(provider->completed != NULL && is_provider_running(auth, provider->id))
/* Notify pending clients who asked for it */ /* Notify pending clients who asked for it */
provider->completed(auth, id); provider->completed(auth, id);
@ -267,18 +301,17 @@ accept_client(struct auth_client *auth, uint32_t id)
static void static void
start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_ip, const char *c_port) 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)); struct auth_client *auth = rb_malloc(sizeof(struct auth_client));
long lcid = strtol(cid, NULL, 16); long lcid = strtol(cid, NULL, 16);
rb_dictionary_iter iter; rb_dlink_node *ptr;
if(lcid >= UINT32_MAX) if(lcid >= UINT32_MAX)
return; return;
auth->cid = (uint32_t)lcid; auth->cid = (uint32_t)lcid;
if(rb_dictionary_find(auth_clients, RB_UINT_TO_POINTER(auth->cid)) == NULL) if(find_client(auth->cid) == NULL)
rb_dictionary_add(auth_clients, RB_UINT_TO_POINTER(auth->cid), auth); rb_dlinkAdd(auth, &auth->node, &auth_clients);
else else
{ {
warn_opers(L_CRIT, "provider: duplicate client added via start_auth: %x", auth->cid); 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->hostname, "*", sizeof(auth->hostname));
rb_strlcpy(auth->username, "*", sizeof(auth->username)); 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)); sizeof(struct auth_client_data));
auth->providers_starting = true; 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; auth->data[provider->id].provider = provider;
lrb_assert(provider->start != NULL); lrb_assert(provider->start != NULL);
@ -351,7 +386,7 @@ handle_cancel_connection(int parc, char *parv[])
exit(EX_PROVIDER_ERROR); 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. /* This could happen as a race if we've accepted/rejected but they cancel, so don't die here.
* --Elizafox */ * --Elizafox */
@ -365,16 +400,17 @@ static void
provider_timeout_event(void *notused __unused) provider_timeout_event(void *notused __unused)
{ {
struct auth_client *auth; struct auth_client *auth;
rb_dictionary_iter iter;
const time_t curtime = rb_current_time(); 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_client *auth = ptr->data;
struct auth_provider *provider; 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); const time_t timeout = get_provider_timeout(auth, provider->id);
if(is_provider_running(auth, provider->id) && provider->timeout != NULL && if(is_provider_running(auth, provider->id) && provider->timeout != NULL &&

View file

@ -44,6 +44,8 @@ struct auth_client_data
struct auth_client struct auth_client
{ {
rb_dlink_node node;
uint16_t cid; /* Client ID */ uint16_t cid; /* Client ID */
char l_ip[HOSTIPLEN + 1]; /* Listener IP address */ 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 blacklist_provider;
extern struct auth_provider opm_provider; extern struct auth_provider opm_provider;
extern rb_dictionary *auth_providers; extern rb_dlink_list auth_providers;
extern rb_dictionary *auth_clients; 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 load_provider(struct auth_provider *provider);
void unload_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[]); 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 */ /* Get a provider's id by name */
static inline bool static inline bool
get_provider_id(const char *name, uint32_t *id) 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) if(provider != NULL)
{ {

View file

@ -421,11 +421,11 @@ blacklists_cancel(struct auth_client *auth)
static void static void
blacklists_destroy(void) blacklists_destroy(void)
{ {
rb_dictionary_iter iter; rb_dlink_node *ptr, *nptr;
struct auth_client *auth;
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); blacklists_cancel(auth);
} }

View file

@ -275,12 +275,13 @@ get_valid_ident(char *buf)
static void static void
ident_destroy(void) ident_destroy(void)
{ {
struct auth_client *auth; rb_dlink_node *ptr, *nptr;
rb_dictionary_iter iter;
/* Nuke all ident queries */ /* 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) if(get_provider_data(auth, SELF_PID) != NULL)
client_fail(auth, REPORT_FAIL); client_fail(auth, REPORT_FAIL);
} }

View file

@ -196,11 +196,10 @@ read_opm_reply(rb_fde_t *F, void *data)
static void static void
accept_opm(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t len, void *data) 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 opm_listener *listener = data;
struct rb_sockaddr_storage localaddr; struct rb_sockaddr_storage localaddr;
unsigned int llen = sizeof(struct rb_sockaddr_storage); unsigned int llen = sizeof(struct rb_sockaddr_storage);
rb_dictionary_iter iter; rb_dlink_node *ptr;
if(status != 0 || listener == NULL) 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) */ /* 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)) if(GET_SS_FAMILY(&auth->c_addr) != GET_SS_FAMILY(&localaddr))
continue; continue;
@ -467,10 +468,9 @@ establish_connection(struct auth_client *auth, struct opm_proxy *proxy)
static bool static bool
create_listener(const char *ip, uint16_t port) create_listener(const char *ip, uint16_t port)
{ {
struct auth_client *auth;
struct opm_listener *listener; struct opm_listener *listener;
struct rb_sockaddr_storage addr; struct rb_sockaddr_storage addr;
rb_dictionary_iter iter; rb_dlink_node *ptr, *nptr;
rb_fde_t *F; rb_fde_t *F;
int opt = 1; int opt = 1;
@ -560,8 +560,9 @@ create_listener(const char *ip, uint16_t port)
/* Cancel clients that may be on old listener /* Cancel clients that may be on old listener
* XXX - should rescan clients that need it * 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); opm_cancel(auth);
} }
@ -674,12 +675,12 @@ opm_cancel(struct auth_client *auth)
static void static void
opm_destroy(void) opm_destroy(void)
{ {
struct auth_client *auth; rb_dlink_node *ptr, *nptr;
rb_dictionary_iter iter;
/* Nuke all opm lookups */ /* 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); 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) if(listeners[LISTEN_IPV4].F != NULL || listeners[LISTEN_IPV6].F != NULL)
{ {
struct auth_client *auth; rb_dlink_node *ptr, *nptr;
rb_dictionary_iter iter;
/* Close the listening socket */ /* Close the listening socket */
if(listeners[LISTEN_IPV4].F != NULL) 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; 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); opm_cancel(auth);
} }
} }
@ -814,11 +815,10 @@ create_opm_scanner(const char *key __unused, int parc __unused, const char **par
static void static void
delete_opm_scanner(const char *key __unused, int parc __unused, const char **parv) delete_opm_scanner(const char *key __unused, int parc __unused, const char **parv)
{ {
struct auth_client *auth;
struct opm_proxy *proxy; struct opm_proxy *proxy;
protocol_t proto = get_protocol_from_string(parv[0]); protocol_t proto = get_protocol_from_string(parv[0]);
int iport = atoi(parv[1]); int iport = atoi(parv[1]);
rb_dictionary_iter iter; rb_dlink_node *ptr, *nptr;
if(iport <= 0 || iport > 65535) 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 */ /* 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); struct opm_lookup *lookup = get_provider_data(auth, SELF_PID);
rb_dlink_node *optr;
if(lookup == NULL) if(lookup == NULL)
continue; 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) 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 static void
delete_opm_scanner_all(const char *key __unused, int parc __unused, const char **parv __unused) 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_dlink_node *ptr, *nptr;
rb_dictionary_iter iter;
RB_DLINK_FOREACH_SAFE(ptr, nptr, proxy_scanners.head) 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_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); opm_cancel(auth);
} }

View file

@ -112,11 +112,12 @@ client_success(struct auth_client *auth)
static void static void
rdns_destroy(void) rdns_destroy(void)
{ {
struct auth_client *auth; rb_dlink_node *ptr, *nptr;
rb_dictionary_iter iter;
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) if(get_provider_data(auth, SELF_PID) != NULL)
client_fail(auth, REPORT_FAIL); client_fail(auth, REPORT_FAIL);
} }