From 05e17ac20826a699fea98d19001222d6550010b5 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 01:50:36 -0600 Subject: [PATCH 01/96] authd: initial authentication framework implementation Not plugged into anything yet, but compile-tested. --- authd/Makefile.am | 2 +- authd/auth.c | 250 ++++++++++++++++++++++++++++++++++++++++++++++ authd/auth.h | 107 ++++++++++++++++++++ 3 files changed, 358 insertions(+), 1 deletion(-) create mode 100644 authd/auth.c create mode 100644 authd/auth.h diff --git a/authd/Makefile.am b/authd/Makefile.am index e1b705e1..ce7fb4bf 100644 --- a/authd/Makefile.am +++ b/authd/Makefile.am @@ -3,5 +3,5 @@ AM_CFLAGS=$(WARNFLAGS) AM_CPPFLAGS = -I../include -I../librb/include -authd_SOURCES = authd.c res.c reslib.c dns.c +authd_SOURCES = auth.c authd.c res.c reslib.c dns.c authd_LDADD = ../librb/src/librb.la diff --git a/authd/auth.c b/authd/auth.c new file mode 100644 index 00000000..26f89cc0 --- /dev/null +++ b/authd/auth.c @@ -0,0 +1,250 @@ +/* authd/auth.c - authentication provider framework + * Copyright (c) 2016 Elizabeth Myers + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* So the basic design here is to have "authentication providers" that do + * things like query ident and blacklists and even open proxies. + * + * Providers are registered statically in the struct auth_providers array. You will + * probably want to add an item to the provider_t enum also. + * + * Providers can either return failure immediately, immediate acceptance, or + * do work in the background (calling set_provider to signal this). + * + * It is up to providers to keep their own state on clients if they need to. + * + * All providers must implement at a minimum a perform_provider function. You + * don't have to implement the others if you don't need them. + * + * Providers may kick clients off by rejecting them. Upon rejection, all + * providers are cancelled. They can also unconditionally accept them. + * + * When a provider has done its work, it should call provider_done. + * + * --Elizafox, 9 March 2016 + */ + +#include "authd.h" +#include "auth.h" + +/*****************************************************************************/ +/* This is just some test code for the system */ +bool dummy_init(void) +{ + /* Do a dummy init */ + return true; +} + +void dummy_destroy(void) +{ + /* Do a dummy destroy */ +} + +bool dummy_start(struct auth_client *auth) +{ + /* Set the client's username to testhost as a test */ + strcpy(auth->username, "testhost"); + return true; +} + +void dummy_cancel(struct auth_client *auth) +{ + /* Does nothing */ +} +/*****************************************************************************/ + +#define NULL_PROVIDER { \ + .provider = PROVIDER_NULL, \ + .init = NULL, \ + .destroy = NULL, \ + .start = NULL, \ + .cancel = NULL, \ + .completed = NULL, \ +} + +#define DUMMY_PROVIDER { \ + .provider = PROVIDER_DUMMY, \ + .init = dummy_init, \ + .destroy = dummy_destroy, \ + .start = dummy_start, \ + .cancel = dummy_cancel, \ + .completed = NULL, \ +} + +/* Providers */ +static struct auth_provider auth_providers[] = +{ + NULL_PROVIDER, + DUMMY_PROVIDER +}; + +/* Clients waiting */ +struct auth_client auth_clients[MAX_CLIENTS]; + +/* Initalise all providers */ +void init_providers(void) +{ + struct auth_provider *pptr; + + AUTH_PROVIDER_FOREACH(pptr) + { + if(pptr->init && !pptr->init()) + /* Provider failed to init, time to go */ + exit(1); + } +} + +/* Terminate all providers */ +void destroy_providerss(void) +{ + struct auth_provider *pptr; + + /* Cancel outstanding connections */ + for (size_t i = 0; i < MAX_CLIENTS; i++) + { + if(auth_clients[i].cid) + { + /* TBD - is this the right thing? + * (NOTE - this error message is designed for morons) */ + reject_client(&auth_clients[i], + "IRC server reloading... try reconnecting in a few seconds"); + } + } + + AUTH_PROVIDER_FOREACH(pptr) + { + if(pptr->destroy) + pptr->destroy(); + } +} + +/* Cancel outstanding providers for a client */ +void cancel_providers(struct auth_client *auth) +{ + struct auth_provider *pptr; + + AUTH_PROVIDER_FOREACH(pptr) + { + if(pptr->cancel && is_provider(auth, pptr->provider)) + /* Cancel if required */ + pptr->cancel(auth); + } +} + +/* Provider is done */ +void provider_done(struct auth_client *auth, provider_t provider) +{ + struct auth_provider *pptr; + + unset_provider(auth, provider); + + if(!auth->providers) + { + /* No more providers, done */ + accept_client(auth); + return; + } + + AUTH_PROVIDER_FOREACH(pptr) + { + if(pptr->completed && is_provider(auth, pptr->provider)) + /* Notify pending clients who asked for it */ + pptr->completed(auth, provider); + } +} + +/* Reject a client, cancel outstanding providers if any */ +void reject_client(struct auth_client *auth, const char *reason) +{ + uint16_t cid = auth->cid; + + rb_helper_write(authd_helper, "R %x :%s", auth->cid, reason); + + if(auth->providers) + cancel_providers(auth); + + memset(&auth_clients[cid], 0, sizeof(struct auth_client)); +} + +/* Accept a client, cancel outstanding providers if any */ +void accept_client(struct auth_client *auth) +{ + uint16_t cid = auth->cid; + + rb_helper_write(authd_helper, "A %x %s %s", auth->cid, auth->username, auth->hostname); + + if(auth->providers) + cancel_providers(auth); + + memset(&auth_clients[cid], 0, sizeof(struct auth_client)); +} + +/* Send a notice to a client */ +void notice_client(struct auth_client *auth, const char *notice) +{ + rb_helper_write(authd_helper, "N %x :%s", auth->cid, notice); +} + +/* Begin authenticating user */ +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 *pptr; + struct auth_client *auth; + long lcid = strtol(cid, NULL, 16); + + if(lcid >= MAX_CLIENTS) + return; + + auth = &auth_clients[lcid]; + if(auth->cid != 0) + /* Shouldn't get here */ + return; + + auth->cid = (uint16_t)lcid; + + rb_strlcpy(auth->l_ip, l_ip, sizeof(auth->l_ip)); + auth->l_port = (uint16_t)atoi(l_port); /* Safe cast, port shouldn't exceed 16 bits */ + + rb_strlcpy(auth->c_ip, c_ip, sizeof(auth->c_ip)); + auth->c_port = (uint16_t)atoi(c_port); + + AUTH_PROVIDER_FOREACH(pptr) + { + /* Execute providers */ + if(!pptr->start(auth)) + { + /* Rejected immediately */ + cancel_providers(auth); + return; + } + } + + /* If no providers are running, accept the client */ + if(!auth->providers) + accept_client(auth); +} + +/* Callback for the initiation */ +void handle_new_connection(int parc, char *parv[]) +{ + if(parc < 5) + return; + + start_auth(parv[1], parv[2], parv[3], parv[4], parv[5]); +} diff --git a/authd/auth.h b/authd/auth.h new file mode 100644 index 00000000..5cc05c06 --- /dev/null +++ b/authd/auth.h @@ -0,0 +1,107 @@ +/* authd/auth.h - authentication provider framework + * Copyright (c) 2016 Elizabeth Myers + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __CHARYBDIS_AUTHD_AUTH_H__ +#define __CHARYBDIS_AUTHD_AUTH_H__ + +#include "stdinc.h" + +/* Arbitrary limit */ +#define MAX_CLIENTS 1024 + +/* Registered providers */ +typedef enum +{ + PROVIDER_NULL = 0x0, /* Dummy value */ + PROVIDER_RDNS = 0x1, + PROVIDER_IDENT = 0x2, + PROVIDER_BLACKLIST = 0x4, + PROVIDER_DUMMY = 0x8, +} provider_t; + +struct auth_client +{ + uint16_t cid; /* Client ID */ + + char l_ip[HOSTIPLEN + 1]; /* Listener IP address */ + uint16_t l_port; /* Listener port */ + + char c_ip[HOSTIPLEN + 1]; /* Client IP address */ + uint16_t c_port; /* Client port */ + + char hostname[IRCD_RES_HOSTLEN + 1]; /* Used for DNS lookup */ + char username[USERLEN + 1]; /* Used for ident lookup */ + + unsigned int providers; /* Providers at work, + * none left when set to 0 */ +}; + +typedef bool (*provider_init_t)(void); +typedef bool (*provider_perform_t)(struct auth_client *); +typedef void (*provider_complete_t)(struct auth_client *, provider_t provider); +typedef void (*provider_cancel_t)(struct auth_client *); +typedef void (*provider_destroy_t)(void); + +struct auth_provider +{ + provider_t provider; + + provider_init_t init; /* Initalise the provider */ + provider_destroy_t destroy; /* Terminate the provider */ + + provider_perform_t start; /* Perform authentication */ + provider_cancel_t cancel; /* Authentication cancelled */ + provider_complete_t completed; /* Callback for when other performers complete (think dependency chains) */ +}; + +#define AUTH_PROVIDER_FOREACH(a) for((a) = auth_providers; (a)->provider; (a)++) + +void init_providers(void); +void destroy_providers(void); +void cancel_providers(struct auth_client *auth); + +void provider_done(struct auth_client *auth, provider_t provider); + +void reject_client(struct auth_client *auth, const char *reason); +void accept_client(struct auth_client *auth); +void notice_client(struct auth_client *auth, const char *notice); + +void start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_ip, const char *c_port); +void handle_new_connection(int parc, char *parv[]); + +/* Provider is operating on this auth_client (set this if you have async work to do) */ +static inline void set_provider(struct auth_client *auth, provider_t provider) +{ + auth->providers |= provider; +} + +/* Provider is no longer operating on this auth client (you should use provider_done) */ +static inline void unset_provider(struct auth_client *auth, provider_t provider) +{ + auth->providers &= ~provider; +} + +/* Check if provider is operating on this auth client */ +static inline bool is_provider(struct auth_client *auth, provider_t provider) +{ + return auth->providers & provider; +} + +#endif /* __CHARYBDIS_AUTHD_AUTH_H__ */ From f42aa1a9e5bdfebab774deb07c9cb95dd654bc3f Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 01:59:37 -0600 Subject: [PATCH 02/96] auth: minor changes --- authd/auth.c | 56 ++++++++++++---------------------------------------- authd/auth.h | 4 ++-- 2 files changed, 15 insertions(+), 45 deletions(-) diff --git a/authd/auth.c b/authd/auth.c index 26f89cc0..b65da845 100644 --- a/authd/auth.c +++ b/authd/auth.c @@ -35,7 +35,9 @@ * Providers may kick clients off by rejecting them. Upon rejection, all * providers are cancelled. They can also unconditionally accept them. * - * When a provider has done its work, it should call provider_done. + * When a provider is done and is neutral on accepting/rejecting a client, it + * should call provider_done. Do NOT call this if you have accepted or rejected + * the client. * * --Elizafox, 9 March 2016 */ @@ -43,32 +45,6 @@ #include "authd.h" #include "auth.h" -/*****************************************************************************/ -/* This is just some test code for the system */ -bool dummy_init(void) -{ - /* Do a dummy init */ - return true; -} - -void dummy_destroy(void) -{ - /* Do a dummy destroy */ -} - -bool dummy_start(struct auth_client *auth) -{ - /* Set the client's username to testhost as a test */ - strcpy(auth->username, "testhost"); - return true; -} - -void dummy_cancel(struct auth_client *auth) -{ - /* Does nothing */ -} -/*****************************************************************************/ - #define NULL_PROVIDER { \ .provider = PROVIDER_NULL, \ .init = NULL, \ @@ -78,20 +54,10 @@ void dummy_cancel(struct auth_client *auth) .completed = NULL, \ } -#define DUMMY_PROVIDER { \ - .provider = PROVIDER_DUMMY, \ - .init = dummy_init, \ - .destroy = dummy_destroy, \ - .start = dummy_start, \ - .cancel = dummy_cancel, \ - .completed = NULL, \ -} - /* Providers */ static struct auth_provider auth_providers[] = { NULL_PROVIDER, - DUMMY_PROVIDER }; /* Clients waiting */ @@ -111,7 +77,7 @@ void init_providers(void) } /* Terminate all providers */ -void destroy_providerss(void) +void destroy_providers(void) { struct auth_provider *pptr; @@ -122,7 +88,7 @@ void destroy_providerss(void) { /* TBD - is this the right thing? * (NOTE - this error message is designed for morons) */ - reject_client(&auth_clients[i], + reject_client(&auth_clients[i], 0, "IRC server reloading... try reconnecting in a few seconds"); } } @@ -157,7 +123,7 @@ void provider_done(struct auth_client *auth, provider_t provider) if(!auth->providers) { /* No more providers, done */ - accept_client(auth); + accept_client(auth, 0); return; } @@ -170,12 +136,14 @@ void provider_done(struct auth_client *auth, provider_t provider) } /* Reject a client, cancel outstanding providers if any */ -void reject_client(struct auth_client *auth, const char *reason) +void reject_client(struct auth_client *auth, provider_t provider, const char *reason) { uint16_t cid = auth->cid; rb_helper_write(authd_helper, "R %x :%s", auth->cid, reason); + unset_provider(auth, provider); + if(auth->providers) cancel_providers(auth); @@ -183,12 +151,14 @@ void reject_client(struct auth_client *auth, const char *reason) } /* Accept a client, cancel outstanding providers if any */ -void accept_client(struct auth_client *auth) +void accept_client(struct auth_client *auth, provider_t provider) { uint16_t cid = auth->cid; rb_helper_write(authd_helper, "A %x %s %s", auth->cid, auth->username, auth->hostname); + unset_provider(auth, provider); + if(auth->providers) cancel_providers(auth); @@ -237,7 +207,7 @@ void start_auth(const char *cid, const char *l_ip, const char *l_port, const cha /* If no providers are running, accept the client */ if(!auth->providers) - accept_client(auth); + accept_client(auth, 0); } /* Callback for the initiation */ diff --git a/authd/auth.h b/authd/auth.h index 5cc05c06..8f47e909 100644 --- a/authd/auth.h +++ b/authd/auth.h @@ -78,9 +78,9 @@ void destroy_providers(void); void cancel_providers(struct auth_client *auth); void provider_done(struct auth_client *auth, provider_t provider); +void reject_client(struct auth_client *auth, provider_t provider, const char *reason); +void accept_client(struct auth_client *auth, provider_t provider); -void reject_client(struct auth_client *auth, const char *reason); -void accept_client(struct auth_client *auth); void notice_client(struct auth_client *auth, const char *notice); void start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_ip, const char *c_port); From 4cc131fc4824db6e315be2509dfc046c7a359eb0 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 02:37:52 -0600 Subject: [PATCH 03/96] [ci skip] remove useless bit in auth.h --- authd/auth.h | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/authd/auth.h b/authd/auth.h index 8f47e909..eca662a2 100644 --- a/authd/auth.h +++ b/authd/auth.h @@ -33,24 +33,22 @@ typedef enum PROVIDER_RDNS = 0x1, PROVIDER_IDENT = 0x2, PROVIDER_BLACKLIST = 0x4, - PROVIDER_DUMMY = 0x8, } provider_t; struct auth_client { - uint16_t cid; /* Client ID */ + uint16_t cid; /* Client ID */ - char l_ip[HOSTIPLEN + 1]; /* Listener IP address */ - uint16_t l_port; /* Listener port */ + char *l_ip; /* Listener IP address */ + uint16_t l_port; /* Listener port */ - char c_ip[HOSTIPLEN + 1]; /* Client IP address */ - uint16_t c_port; /* Client port */ + char *c_ip; /* Client IP address */ + uint16_t c_port; /* Client port */ - char hostname[IRCD_RES_HOSTLEN + 1]; /* Used for DNS lookup */ - char username[USERLEN + 1]; /* Used for ident lookup */ + char *hostname; /* Used for DNS lookup */ + char *username; /* Used for ident lookup */ - unsigned int providers; /* Providers at work, - * none left when set to 0 */ + unsigned int providers; /* Providers at work, 0 = none left */ }; typedef bool (*provider_init_t)(void); From be67cfca84c744acbbb5c9815a633e93ce306f8c Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 02:42:18 -0600 Subject: [PATCH 04/96] Revert "[ci skip] remove useless bit in auth.h" This reverts commit 4cc131fc4824db6e315be2509dfc046c7a359eb0. --- authd/auth.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/authd/auth.h b/authd/auth.h index eca662a2..8f47e909 100644 --- a/authd/auth.h +++ b/authd/auth.h @@ -33,22 +33,24 @@ typedef enum PROVIDER_RDNS = 0x1, PROVIDER_IDENT = 0x2, PROVIDER_BLACKLIST = 0x4, + PROVIDER_DUMMY = 0x8, } provider_t; struct auth_client { - uint16_t cid; /* Client ID */ + uint16_t cid; /* Client ID */ - char *l_ip; /* Listener IP address */ - uint16_t l_port; /* Listener port */ + char l_ip[HOSTIPLEN + 1]; /* Listener IP address */ + uint16_t l_port; /* Listener port */ - char *c_ip; /* Client IP address */ - uint16_t c_port; /* Client port */ + char c_ip[HOSTIPLEN + 1]; /* Client IP address */ + uint16_t c_port; /* Client port */ - char *hostname; /* Used for DNS lookup */ - char *username; /* Used for ident lookup */ + char hostname[IRCD_RES_HOSTLEN + 1]; /* Used for DNS lookup */ + char username[USERLEN + 1]; /* Used for ident lookup */ - unsigned int providers; /* Providers at work, 0 = none left */ + unsigned int providers; /* Providers at work, + * none left when set to 0 */ }; typedef bool (*provider_init_t)(void); From 2c01da6b7e718226cad95c458d7c0b83f585eecc Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 02:42:40 -0600 Subject: [PATCH 05/96] Once more with feeling, remove useless enum bit Now with 50% less experimental changes --- authd/auth.h | 1 - 1 file changed, 1 deletion(-) diff --git a/authd/auth.h b/authd/auth.h index 8f47e909..f7cf8b43 100644 --- a/authd/auth.h +++ b/authd/auth.h @@ -33,7 +33,6 @@ typedef enum PROVIDER_RDNS = 0x1, PROVIDER_IDENT = 0x2, PROVIDER_BLACKLIST = 0x4, - PROVIDER_DUMMY = 0x8, } provider_t; struct auth_client From 99e538670dd4349e37884638e2d66cd4152380dc Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 03:02:16 -0600 Subject: [PATCH 06/96] authd: convert auth stuff to use a linked list. This allows runtime loadable providers. --- authd/auth.c | 91 ++++++++++++++++++++++++++++++---------------------- authd/auth.h | 6 ++-- 2 files changed, 56 insertions(+), 41 deletions(-) diff --git a/authd/auth.c b/authd/auth.c index b65da845..fe7cb9ee 100644 --- a/authd/auth.c +++ b/authd/auth.c @@ -45,32 +45,35 @@ #include "authd.h" #include "auth.h" -#define NULL_PROVIDER { \ - .provider = PROVIDER_NULL, \ - .init = NULL, \ - .destroy = NULL, \ - .start = NULL, \ - .cancel = NULL, \ - .completed = NULL, \ -} - -/* Providers */ -static struct auth_provider auth_providers[] = -{ - NULL_PROVIDER, -}; +rb_dlink_list auth_providers; /* Clients waiting */ struct auth_client auth_clients[MAX_CLIENTS]; +/* Load a provider */ +void load_provider(struct auth_provider *provider) +{ + provider->init(); + rb_dlinkAdd(provider, &provider->node, &auth_providers); +} + +void unload_provider(struct auth_provider *provider) +{ + provider->destroy(); + rb_dlinkDelete(&provider->node, &auth_providers); +} + /* Initalise all providers */ void init_providers(void) { - struct auth_provider *pptr; + rb_dlink_node *ptr; + struct auth_provider *provider; - AUTH_PROVIDER_FOREACH(pptr) + RB_DLINK_FOREACH(ptr, auth_providers.head) { - if(pptr->init && !pptr->init()) + provider = ptr->data; + + if(provider->init && !provider->init()) /* Provider failed to init, time to go */ exit(1); } @@ -79,7 +82,8 @@ void init_providers(void) /* Terminate all providers */ void destroy_providers(void) { - struct auth_provider *pptr; + rb_dlink_node *ptr; + struct auth_provider *provider; /* Cancel outstanding connections */ for (size_t i = 0; i < MAX_CLIENTS; i++) @@ -93,32 +97,38 @@ void destroy_providers(void) } } - AUTH_PROVIDER_FOREACH(pptr) + RB_DLINK_FOREACH(ptr, auth_providers.head) { - if(pptr->destroy) - pptr->destroy(); + provider = ptr->data; + + if(provider->destroy) + provider->destroy(); } } /* Cancel outstanding providers for a client */ void cancel_providers(struct auth_client *auth) { - struct auth_provider *pptr; + rb_dlink_node *ptr; + struct auth_provider *provider; - AUTH_PROVIDER_FOREACH(pptr) + RB_DLINK_FOREACH(ptr, auth_providers.head) { - if(pptr->cancel && is_provider(auth, pptr->provider)) + provider = ptr->data; + + if(provider->cancel && is_provider(auth, provider->id)) /* Cancel if required */ - pptr->cancel(auth); + provider->cancel(auth); } } /* Provider is done */ -void provider_done(struct auth_client *auth, provider_t provider) +void provider_done(struct auth_client *auth, provider_t id) { - struct auth_provider *pptr; + rb_dlink_node *ptr; + struct auth_provider *provider; - unset_provider(auth, provider); + unset_provider(auth, id); if(!auth->providers) { @@ -127,22 +137,24 @@ void provider_done(struct auth_client *auth, provider_t provider) return; } - AUTH_PROVIDER_FOREACH(pptr) + RB_DLINK_FOREACH(ptr, auth_providers.head) { - if(pptr->completed && is_provider(auth, pptr->provider)) + provider = ptr->data; + + if(provider->completed && is_provider(auth, provider->id)) /* Notify pending clients who asked for it */ - pptr->completed(auth, provider); + provider->completed(auth, id); } } /* Reject a client, cancel outstanding providers if any */ -void reject_client(struct auth_client *auth, provider_t provider, const char *reason) +void reject_client(struct auth_client *auth, provider_t id, const char *reason) { uint16_t cid = auth->cid; rb_helper_write(authd_helper, "R %x :%s", auth->cid, reason); - unset_provider(auth, provider); + unset_provider(auth, id); if(auth->providers) cancel_providers(auth); @@ -151,13 +163,13 @@ void reject_client(struct auth_client *auth, provider_t provider, const char *re } /* Accept a client, cancel outstanding providers if any */ -void accept_client(struct auth_client *auth, provider_t provider) +void accept_client(struct auth_client *auth, provider_t id) { uint16_t cid = auth->cid; rb_helper_write(authd_helper, "A %x %s %s", auth->cid, auth->username, auth->hostname); - unset_provider(auth, provider); + unset_provider(auth, id); if(auth->providers) cancel_providers(auth); @@ -174,7 +186,8 @@ void notice_client(struct auth_client *auth, const char *notice) /* Begin authenticating user */ 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 *pptr; + rb_dlink_node *ptr; + struct auth_provider *provider; struct auth_client *auth; long lcid = strtol(cid, NULL, 16); @@ -194,10 +207,12 @@ void start_auth(const char *cid, const char *l_ip, const char *l_port, const cha rb_strlcpy(auth->c_ip, c_ip, sizeof(auth->c_ip)); auth->c_port = (uint16_t)atoi(c_port); - AUTH_PROVIDER_FOREACH(pptr) + RB_DLINK_FOREACH(ptr, auth_providers.head) { + provider = ptr->data; + /* Execute providers */ - if(!pptr->start(auth)) + if(!provider->start(auth)) { /* Rejected immediately */ cancel_providers(auth); diff --git a/authd/auth.h b/authd/auth.h index f7cf8b43..c5a481f2 100644 --- a/authd/auth.h +++ b/authd/auth.h @@ -60,7 +60,9 @@ typedef void (*provider_destroy_t)(void); struct auth_provider { - provider_t provider; + rb_dlink_node node; + + provider_t id; provider_init_t init; /* Initalise the provider */ provider_destroy_t destroy; /* Terminate the provider */ @@ -70,8 +72,6 @@ struct auth_provider provider_complete_t completed; /* Callback for when other performers complete (think dependency chains) */ }; -#define AUTH_PROVIDER_FOREACH(a) for((a) = auth_providers; (a)->provider; (a)++) - void init_providers(void); void destroy_providers(void); void cancel_providers(struct auth_client *auth); From 0f95a2749f0e8e6f746b01f4d0655f1ec043f5d4 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 03:07:52 -0600 Subject: [PATCH 07/96] rename auth.[ch] to provider.[ch] This name is less confusing and more descriptive. --- authd/Makefile.am | 2 +- authd/{auth.c => provider.c} | 4 ++-- authd/{auth.h => provider.h} | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) rename authd/{auth.c => provider.c} (98%) rename authd/{auth.h => provider.h} (95%) diff --git a/authd/Makefile.am b/authd/Makefile.am index ce7fb4bf..b394aacf 100644 --- a/authd/Makefile.am +++ b/authd/Makefile.am @@ -3,5 +3,5 @@ AM_CFLAGS=$(WARNFLAGS) AM_CPPFLAGS = -I../include -I../librb/include -authd_SOURCES = auth.c authd.c res.c reslib.c dns.c +authd_SOURCES = provider.c authd.c res.c reslib.c dns.c authd_LDADD = ../librb/src/librb.la diff --git a/authd/auth.c b/authd/provider.c similarity index 98% rename from authd/auth.c rename to authd/provider.c index fe7cb9ee..a36fc0c4 100644 --- a/authd/auth.c +++ b/authd/provider.c @@ -1,4 +1,4 @@ -/* authd/auth.c - authentication provider framework +/* authd/provider.c - authentication provider framework * Copyright (c) 2016 Elizabeth Myers * * Permission to use, copy, modify, and/or distribute this software for any @@ -43,7 +43,7 @@ */ #include "authd.h" -#include "auth.h" +#include "provider.h" rb_dlink_list auth_providers; diff --git a/authd/auth.h b/authd/provider.h similarity index 95% rename from authd/auth.h rename to authd/provider.h index c5a481f2..87a859d9 100644 --- a/authd/auth.h +++ b/authd/provider.h @@ -1,4 +1,4 @@ -/* authd/auth.h - authentication provider framework +/* authd/provider.h - authentication provider framework * Copyright (c) 2016 Elizabeth Myers * * Permission to use, copy, modify, and/or distribute this software for any @@ -18,8 +18,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __CHARYBDIS_AUTHD_AUTH_H__ -#define __CHARYBDIS_AUTHD_AUTH_H__ +#ifndef __CHARYBDIS_AUTHD_PROVIDER_H__ +#define __CHARYBDIS_AUTHD_PROVIDER_H__ #include "stdinc.h" @@ -103,4 +103,4 @@ static inline bool is_provider(struct auth_client *auth, provider_t provider) return auth->providers & provider; } -#endif /* __CHARYBDIS_AUTHD_AUTH_H__ */ +#endif /* __CHARYBDIS_AUTHD_PROVIDER_H__ */ From 9b5b2dedc0a7d98efc392fe0e5f123d1e6a3fee7 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 03:15:03 -0600 Subject: [PATCH 08/96] authd/provider: add these to provider.h --- authd/provider.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/authd/provider.h b/authd/provider.h index 87a859d9..0b2161da 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -72,6 +72,13 @@ struct auth_provider provider_complete_t completed; /* Callback for when other performers complete (think dependency chains) */ }; +extern rb_dlink_list auth_providers; + +extern struct auth_client auth_clients[MAX_CLIENTS]; + +void load_provider(struct auth_provider *provider); +void unload_provider(struct auth_provider *provider); + void init_providers(void); void destroy_providers(void); void cancel_providers(struct auth_client *auth); From f169fc88422c27c0512aeaebfa216b81022d3c11 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 05:40:21 -0600 Subject: [PATCH 09/96] authd: add address families to provider processing. ircd knows about them so let's not reinvent checking for address types and stuff. --- authd/provider.c | 10 +++++++--- authd/provider.h | 5 +++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index a36fc0c4..b31cd37b 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -184,7 +184,9 @@ void notice_client(struct auth_client *auth, const char *notice) } /* Begin authenticating user */ -void start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_ip, const char *c_port) +static void start_auth(const char *cid, const char *l_ip, const char *l_port, + const char *l_family, const char *c_ip, const char *c_port, + const char *c_family) { rb_dlink_node *ptr; struct auth_provider *provider; @@ -203,9 +205,11 @@ void start_auth(const char *cid, const char *l_ip, const char *l_port, const cha rb_strlcpy(auth->l_ip, l_ip, sizeof(auth->l_ip)); auth->l_port = (uint16_t)atoi(l_port); /* Safe cast, port shouldn't exceed 16 bits */ + auth->l_family = atoi(l_family); rb_strlcpy(auth->c_ip, c_ip, sizeof(auth->c_ip)); auth->c_port = (uint16_t)atoi(c_port); + auth->c_family = atoi(c_family); RB_DLINK_FOREACH(ptr, auth_providers.head) { @@ -228,8 +232,8 @@ void start_auth(const char *cid, const char *l_ip, const char *l_port, const cha /* Callback for the initiation */ void handle_new_connection(int parc, char *parv[]) { - if(parc < 5) + if(parc < 7) return; - start_auth(parv[1], parv[2], parv[3], parv[4], parv[5]); + start_auth(parv[1], parv[2], parv[3], parv[4], parv[5], parv[6], parv[7]); } diff --git a/authd/provider.h b/authd/provider.h index 0b2161da..63016f7e 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -24,7 +24,7 @@ #include "stdinc.h" /* Arbitrary limit */ -#define MAX_CLIENTS 1024 +#define MAX_CLIENTS 4096 /* Registered providers */ typedef enum @@ -41,9 +41,11 @@ struct auth_client char l_ip[HOSTIPLEN + 1]; /* Listener IP address */ uint16_t l_port; /* Listener port */ + int l_family; /* AF_INET or AF_INET6 */ char c_ip[HOSTIPLEN + 1]; /* Client IP address */ uint16_t c_port; /* Client port */ + int c_family; /* AF_INET or AF_INET6 */ char hostname[IRCD_RES_HOSTLEN + 1]; /* Used for DNS lookup */ char username[USERLEN + 1]; /* Used for ident lookup */ @@ -89,7 +91,6 @@ void accept_client(struct auth_client *auth, provider_t provider); void notice_client(struct auth_client *auth, const char *notice); -void start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_ip, const char *c_port); void handle_new_connection(int parc, char *parv[]); /* Provider is operating on this auth_client (set this if you have async work to do) */ From 1c99f551e3398777590d25ed24a4e78834d1c53b Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 05:57:33 -0600 Subject: [PATCH 10/96] dns: add format_address function --- authd/dns.c | 45 ++++++++++++++++++++++++--------------------- authd/dns.h | 1 + 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/authd/dns.c b/authd/dns.c index ddac5be4..893581e9 100644 --- a/authd/dns.c +++ b/authd/dns.c @@ -22,6 +22,29 @@ #include "dns.h" #include "res.h" +void +format_address(struct rb_sockaddr_storage *addr, char *buffer, size_t length) +{ + if(GET_SS_FAMILY(addr) == AF_INET) + { + rb_inet_ntop_sock((struct sockaddr *)addr, buffer, length); + } + else if(GET_SS_FAMILY(addr) == AF_INET6) + { + char tmpbuf[length]; + + rb_inet_ntop_sock((struct sockaddr *)addr, tmpbuf, length); + + if(*tmpbuf == ':') + { + rb_strlcpy(buffer, "0", length); + rb_strlcat(buffer, tmpbuf, length); + } + else + rb_strlcpy(buffer, tmpbuf, length); + } +} + static void submit_dns_answer(void *userdata, struct DNSReply *reply) { @@ -38,29 +61,9 @@ submit_dns_answer(void *userdata, struct DNSReply *reply) switch (req->type) { case '4': - if (GET_SS_FAMILY(&reply->addr) == AF_INET) - { - status = 'O'; - rb_inet_ntop_sock((struct sockaddr *) &reply->addr, response, sizeof(response)); - } - break; #ifdef RB_IPV6 case '6': - if (GET_SS_FAMILY(&reply->addr) == AF_INET6) - { - char tmpres[63]; - rb_inet_ntop_sock((struct sockaddr *) &reply->addr, tmpres, sizeof(tmpres)); - - if (*tmpres == ':') - { - rb_strlcpy(response, "0", sizeof(response)); - rb_strlcat(response, tmpres, sizeof(response)); - } - else - rb_strlcpy(response, tmpres, sizeof(response)); - - status = 'O'; - } + format_address(&reply->addr, response, sizeof(response)); break; #endif case 'R': diff --git a/authd/dns.h b/authd/dns.h index 3e43520a..66497a69 100644 --- a/authd/dns.h +++ b/authd/dns.h @@ -34,6 +34,7 @@ struct dns_request char type; }; +extern void format_address(struct rb_sockaddr_storage *addr, char *buffer, size_t length); extern void resolve_dns(int parc, char *parv[]); extern void enumerate_nameservers(const char *rid, const char letter); extern void reload_nameservers(const char letter); From b3265d7afb97d1cee466c6066a002f99d3a33bc7 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 06:32:25 -0600 Subject: [PATCH 11/96] dns: create sockcmp function. --- authd/dns.c | 57 ++++++++++++++++++++++++++++++++--------------------- authd/dns.h | 2 ++ 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/authd/dns.c b/authd/dns.c index 893581e9..41b6fc79 100644 --- a/authd/dns.c +++ b/authd/dns.c @@ -29,6 +29,7 @@ format_address(struct rb_sockaddr_storage *addr, char *buffer, size_t length) { rb_inet_ntop_sock((struct sockaddr *)addr, buffer, length); } +#ifdef RB_IPV6 else if(GET_SS_FAMILY(addr) == AF_INET6) { char tmpbuf[length]; @@ -43,6 +44,32 @@ format_address(struct rb_sockaddr_storage *addr, char *buffer, size_t length) else rb_strlcpy(buffer, tmpbuf, length); } +#endif +} + +bool +sockcmp(struct rb_sockaddr_storage *addr, struct rb_sockaddr_storage *addr2, int family) +{ + if(family == AF_INET) + { + struct sockaddr_in *ip, *ip2; + ip = (struct sockaddr_in *)addr; + ip2 = (struct sockaddr_in *)addr2; + + return ip->sin_addr.s_addr == ip2->sin_addr.s_addr; + } +#ifdef RB_IPV6 + else if(family == AF_INET6) + { + struct sockaddr_in6 *ip, *ip2; + ip = (struct sockaddr_in6 *) addr; + ip2 = (struct sockaddr_in6 *) addr2; + + return(memcmp(&ip->sin6_addr, &ip2->sin6_addr, sizeof(struct in6_addr)) == 0); + } +#endif + + return false; } static void @@ -51,6 +78,7 @@ submit_dns_answer(void *userdata, struct DNSReply *reply) struct dns_request *req = userdata; char response[64] = "*"; char status = 'E'; + int family = AF_INET; if (reply == NULL) { @@ -66,34 +94,17 @@ submit_dns_answer(void *userdata, struct DNSReply *reply) format_address(&reply->addr, response, sizeof(response)); break; #endif - case 'R': - { - struct sockaddr_in *ip, *ip_fwd; - ip = (struct sockaddr_in *) &req->addr; - ip_fwd = (struct sockaddr_in *) &reply->addr; - - if(ip->sin_addr.s_addr == ip_fwd->sin_addr.s_addr && strlen(reply->h_name) < 63) - { - rb_strlcpy(response, reply->h_name, sizeof(response)); - status = 'O'; - } - } - break; #ifdef RB_IPV6 case 'S': + family = AF_INET6; +#endif + case 'R': + if(sockcmp(&req->addr, &reply->addr, family) && strlen(reply->h_name) < 63) { - struct sockaddr_in6 *ip, *ip_fwd; - ip = (struct sockaddr_in6 *) &req->addr; - ip_fwd = (struct sockaddr_in6 *) &reply->addr; - - if(memcmp(&ip->sin6_addr, &ip_fwd->sin6_addr, sizeof(struct in6_addr)) == 0 && strlen(reply->h_name) < 63) - { - rb_strlcpy(response, reply->h_name, sizeof(response)); - status = 'O'; - } + rb_strlcpy(response, reply->h_name, sizeof(response)); + status = 'O'; } break; -#endif default: exit(7); } diff --git a/authd/dns.h b/authd/dns.h index 66497a69..a173f252 100644 --- a/authd/dns.h +++ b/authd/dns.h @@ -23,6 +23,7 @@ #define DNS_REQ_IDLEN 10 +#include "stdinc.h" #include "res.h" #include "reslib.h" @@ -35,6 +36,7 @@ struct dns_request }; extern void format_address(struct rb_sockaddr_storage *addr, char *buffer, size_t length); +extern bool sockcmp(struct rb_sockaddr_storage *addr, struct rb_sockaddr_storage *addr2, int family); extern void resolve_dns(int parc, char *parv[]); extern void enumerate_nameservers(const char *rid, const char letter); extern void reload_nameservers(const char letter); From 5bfc606fa4af0149921a296aa36c8cf5d6504464 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 07:25:22 -0600 Subject: [PATCH 12/96] authd/provider: use rb_sockaddr_storage for IP addresses. --- authd/provider.c | 12 ++++-------- authd/provider.h | 8 +++----- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index b31cd37b..f63b9be8 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -184,9 +184,7 @@ void notice_client(struct auth_client *auth, const char *notice) } /* Begin authenticating user */ -static void start_auth(const char *cid, const char *l_ip, const char *l_port, - const char *l_family, const char *c_ip, const char *c_port, - const char *c_family) +static void start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_ip, const char *c_port) { rb_dlink_node *ptr; struct auth_provider *provider; @@ -203,13 +201,11 @@ static void start_auth(const char *cid, const char *l_ip, const char *l_port, auth->cid = (uint16_t)lcid; - rb_strlcpy(auth->l_ip, l_ip, sizeof(auth->l_ip)); + (void)rb_inet_pton_sock(l_ip, (struct sockaddr *)&auth->l_ip); auth->l_port = (uint16_t)atoi(l_port); /* Safe cast, port shouldn't exceed 16 bits */ - auth->l_family = atoi(l_family); - rb_strlcpy(auth->c_ip, c_ip, sizeof(auth->c_ip)); + (void)rb_inet_pton_sock(c_ip, (struct sockaddr *)&auth->c_ip); auth->c_port = (uint16_t)atoi(c_port); - auth->c_family = atoi(c_family); RB_DLINK_FOREACH(ptr, auth_providers.head) { @@ -235,5 +231,5 @@ void handle_new_connection(int parc, char *parv[]) if(parc < 7) return; - start_auth(parv[1], parv[2], parv[3], parv[4], parv[5], parv[6], parv[7]); + start_auth(parv[1], parv[2], parv[3], parv[4], parv[5]); } diff --git a/authd/provider.h b/authd/provider.h index 63016f7e..60aefd77 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -39,15 +39,13 @@ struct auth_client { uint16_t cid; /* Client ID */ - char l_ip[HOSTIPLEN + 1]; /* Listener IP address */ + struct rb_sockaddr_storage l_ip; /* Listener IP address */ uint16_t l_port; /* Listener port */ - int l_family; /* AF_INET or AF_INET6 */ - char c_ip[HOSTIPLEN + 1]; /* Client IP address */ + struct rb_sockaddr_storage c_ip; /* Client IP address */ uint16_t c_port; /* Client port */ - int c_family; /* AF_INET or AF_INET6 */ - char hostname[IRCD_RES_HOSTLEN + 1]; /* Used for DNS lookup */ + char hostname[HOSTLEN + 1]; /* Used for DNS lookup */ char username[USERLEN + 1]; /* Used for ident lookup */ unsigned int providers; /* Providers at work, From 187643195c6c3b429f79c6d55828c06051e8bc88 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 08:04:17 -0600 Subject: [PATCH 13/96] authd: add rdns provider (compile-tested) --- authd/Makefile.am | 8 +- authd/provider.c | 16 +-- authd/provider.h | 3 +- authd/providers/rdns.c | 226 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 238 insertions(+), 15 deletions(-) create mode 100644 authd/providers/rdns.c diff --git a/authd/Makefile.am b/authd/Makefile.am index b394aacf..8848b761 100644 --- a/authd/Makefile.am +++ b/authd/Makefile.am @@ -3,5 +3,11 @@ AM_CFLAGS=$(WARNFLAGS) AM_CPPFLAGS = -I../include -I../librb/include -authd_SOURCES = provider.c authd.c res.c reslib.c dns.c +authd_SOURCES = provider.c \ + authd.c \ + res.c \ + reslib.c \ + dns.c \ + providers/rdns.c + authd_LDADD = ../librb/src/librb.la diff --git a/authd/provider.c b/authd/provider.c index f63b9be8..c83e5761 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -66,17 +66,7 @@ void unload_provider(struct auth_provider *provider) /* Initalise all providers */ void init_providers(void) { - rb_dlink_node *ptr; - struct auth_provider *provider; - - RB_DLINK_FOREACH(ptr, auth_providers.head) - { - provider = ptr->data; - - if(provider->init && !provider->init()) - /* Provider failed to init, time to go */ - exit(1); - } + load_provider(&rdns_provider); } /* Terminate all providers */ @@ -184,7 +174,7 @@ void notice_client(struct auth_client *auth, const char *notice) } /* Begin authenticating user */ -static void start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_ip, const char *c_port) +static void start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_addr, const char *c_port) { rb_dlink_node *ptr; struct auth_provider *provider; @@ -204,7 +194,7 @@ static void start_auth(const char *cid, const char *l_ip, const char *l_port, co (void)rb_inet_pton_sock(l_ip, (struct sockaddr *)&auth->l_ip); auth->l_port = (uint16_t)atoi(l_port); /* Safe cast, port shouldn't exceed 16 bits */ - (void)rb_inet_pton_sock(c_ip, (struct sockaddr *)&auth->c_ip); + (void)rb_inet_pton_sock(c_addr, (struct sockaddr *)&auth->c_addr); auth->c_port = (uint16_t)atoi(c_port); RB_DLINK_FOREACH(ptr, auth_providers.head) diff --git a/authd/provider.h b/authd/provider.h index 60aefd77..8bd4d18f 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -42,7 +42,7 @@ struct auth_client struct rb_sockaddr_storage l_ip; /* Listener IP address */ uint16_t l_port; /* Listener port */ - struct rb_sockaddr_storage c_ip; /* Client IP address */ + struct rb_sockaddr_storage c_addr; /* Client IP address */ uint16_t c_port; /* Client port */ char hostname[HOSTLEN + 1]; /* Used for DNS lookup */ @@ -73,6 +73,7 @@ struct auth_provider }; extern rb_dlink_list auth_providers; +extern struct auth_provider rdns_provider; extern struct auth_client auth_clients[MAX_CLIENTS]; diff --git a/authd/providers/rdns.c b/authd/providers/rdns.c new file mode 100644 index 00000000..92f53822 --- /dev/null +++ b/authd/providers/rdns.c @@ -0,0 +1,226 @@ +/* authd/providers/rdns.c - rDNS lookup provider for authd + * Copyright (c) 2016 Elizabeth Myers + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stdinc.h" +#include "rb_commio.h" +#include "authd.h" +#include "provider.h" +#include "res.h" +#include "dns.h" + +struct dns_query +{ + rb_dlink_node node; + + struct auth_client *auth; /* Our client */ + struct DNSQuery query; /* DNS query */ + time_t timeout; /* When the request times out */ +}; + +/* Goinked from old s_auth.c --Elizabeth */ +static const char *messages[] = +{ + "*** Looking up your hostname...", + "*** Found your hostname", + "*** Couldn't look up your hostname", + "*** Your hostname is too long, ignoring hostname", +}; + +typedef enum +{ + REPORT_LOOKUP, + REPORT_FOUND, + REPORT_FAIL, + REPORT_TOOLONG, +} dns_message; + +static EVH timeout_dns_queries_event; +static void client_fail(struct dns_query *query, dns_message message); +static void client_success(struct dns_query *query); +static void get_dns_answer(void *userdata, struct DNSReply *reply); + +rb_dlink_list queries; +static struct ev_entry *timeout_ev; +int timeout = 30; + + +bool client_dns_init(void) +{ + timeout_ev = rb_event_addish("timeout_dns_queries_event", timeout_dns_queries_event, NULL, 1); + return (timeout_ev != NULL); +} + +void client_dns_destroy(void) +{ + rb_dlink_node *ptr, *nptr; + struct dns_query *query; + + RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) + { + client_fail(ptr->data, REPORT_FAIL); + rb_dlinkDelete(ptr, &queries); + rb_free(ptr); + } + + rb_event_delete(timeout_ev); +} + +bool client_dns_start(struct auth_client *auth) +{ + struct dns_query *query = rb_malloc(sizeof(struct dns_query)); + + query->auth = auth; + query->timeout = rb_current_time() + timeout; + + query->query.ptr = query; + query->query.callback = get_dns_answer; + + gethost_byaddr(&auth->c_addr, &query->query); + notice_client(auth, messages[REPORT_LOOKUP]); + return true; +} + +void client_dns_cancel(struct auth_client *auth) +{ + rb_dlink_node *ptr; + + /* Bah, the stupid DNS resolver code doesn't have a cancellation + * func... */ + RB_DLINK_FOREACH(ptr, queries.head) + { + struct dns_query *query = ptr->data; + + if(query->auth == auth) + { + /* This will get cleaned up later by the DNS stuff */ + client_fail(query, REPORT_FAIL); + return; + } + } +} + +static void +get_dns_answer(void *userdata, struct DNSReply *reply) +{ + struct dns_query *query = userdata; + struct auth_client *auth = query->auth; + rb_dlink_node *ptr, *nptr; + bool fail = false; + dns_message response; + + if(reply == NULL || auth == NULL) + { + response = REPORT_FAIL; + fail = true; + goto cleanup; + } + + if(!sockcmp(&auth->c_addr, &reply->addr, GET_SS_FAMILY(&auth->c_addr))) + { + response = REPORT_FAIL; + fail = true; + goto cleanup; + } + + if(strlen(reply->h_name) > HOSTLEN) + { + /* Ah well. */ + response = REPORT_TOOLONG; + fail = true; + goto cleanup; + } + + rb_strlcpy(auth->hostname, reply->h_name, HOSTLEN + 1); + +cleanup: + /* Clean us up off the pending queries list */ + RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) + { + struct dns_query *query_l = ptr->data; + + if(query == query_l) + { + /* Found */ + if(fail) + client_fail(query, response); + else + client_success(query); + + rb_dlinkDelete(ptr, &queries); + rb_free(query); + return; + } + } +} + +/* Timeout outstanding queries */ +static void timeout_dns_queries_event(void *notused) +{ + rb_dlink_node *ptr; + + /* NOTE - we do not delete queries from the list from a timeout, when + * the query times out later it will be deleted. + */ + RB_DLINK_FOREACH(ptr, queries.head) + { + struct dns_query *query = ptr->data; + + if(query->auth && query->timeout < rb_current_time()) + { + client_fail(query, REPORT_FAIL); + return; + } + } +} + +static void client_fail(struct dns_query *query, dns_message report) +{ + struct auth_client *auth = query->auth; + + if(auth) + { + rb_strlcpy(auth->hostname, "*", sizeof(auth->hostname)); + notice_client(auth, messages[report]); + provider_done(auth, PROVIDER_RDNS); + query->auth = NULL; + } +} + +static void client_success(struct dns_query *query) +{ + struct auth_client *auth = query->auth; + + if(auth) + { + notice_client(auth, messages[REPORT_FOUND]); + provider_done(auth, PROVIDER_RDNS); + query->auth = NULL; + } +} + +struct auth_provider rdns_provider = +{ + .id = PROVIDER_RDNS, + .init = client_dns_init, + .destroy = client_dns_destroy, + .start = client_dns_start, + .cancel = client_dns_cancel, + .completed = NULL, +}; From 8dc9aa85b6707709052b10c94175869725f78707 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 08:06:57 -0600 Subject: [PATCH 14/96] authd: crap, C was taken already, rename reload to H. --- authd/authd.c | 2 +- include/setup.h.in | 5 ++++- ircd/dns.c | 2 +- librb/include/librb_config.h.in | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/authd/authd.c b/authd/authd.c index 298d3c4f..62336833 100644 --- a/authd/authd.c +++ b/authd/authd.c @@ -28,7 +28,7 @@ static void handle_stat(int parc, char *parv[]); rb_helper *authd_helper = NULL; authd_cmd_handler authd_cmd_handlers[256] = { - ['C'] = handle_reload, + ['H'] = handle_reload, ['D'] = resolve_dns, ['S'] = handle_stat, }; diff --git a/include/setup.h.in b/include/setup.h.in index fce3acbb..a66efc10 100644 --- a/include/setup.h.in +++ b/include/setup.h.in @@ -169,7 +169,7 @@ /* Define to 1 if you have the `socketpair' function. */ #undef HAVE_SOCKETPAIR -/* Define to 1 if you have the header file. */ +/* Define to 1 if stdbool.h conforms to C99. */ #undef HAVE_STDBOOL_H /* Define to 1 if you have the header file. */ @@ -241,6 +241,9 @@ /* This value is set to 1 to indicate that the system argz facility works */ #undef HAVE_WORKING_ARGZ +/* Define to 1 if the system has the type `_Bool'. */ +#undef HAVE__BOOL + /* Prefix where help files are installed. */ #undef HELP_DIR diff --git a/ircd/dns.c b/ircd/dns.c index 4b067ba6..055c6b33 100644 --- a/ircd/dns.c +++ b/ircd/dns.c @@ -330,7 +330,7 @@ reload_nameservers(void) /* Shit */ return false; } - rb_helper_write(authd_helper, "C D"); + rb_helper_write(authd_helper, "H D"); init_nameserver_cache(); return true; } diff --git a/librb/include/librb_config.h.in b/librb/include/librb_config.h.in index 66125669..95d88994 100644 --- a/librb/include/librb_config.h.in +++ b/librb/include/librb_config.h.in @@ -264,12 +264,12 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION -/* Defined to mark profiling is enabled */ -#undef RB_PROFILE - /* Prefix where librb is installed. */ #undef RB_PREFIX +/* Defined to mark profiling is enabled */ +#undef RB_PROFILE + /* Define to 1 if sockaddr has a 'sa_len' member. */ #undef SOCKADDR_IN_HAS_LEN From cafe4dd8df1c0f6221a047dcaa6f20d100a3558c Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 08:09:16 -0600 Subject: [PATCH 15/96] authd: plug in new C type. --- authd/authd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/authd/authd.c b/authd/authd.c index 62336833..50333004 100644 --- a/authd/authd.c +++ b/authd/authd.c @@ -20,6 +20,7 @@ #include "authd.h" #include "dns.h" +#include "provider.h" #define MAXPARA 10 @@ -28,8 +29,9 @@ static void handle_stat(int parc, char *parv[]); rb_helper *authd_helper = NULL; authd_cmd_handler authd_cmd_handlers[256] = { - ['H'] = handle_reload, + ['C'] = handle_new_connection, ['D'] = resolve_dns, + ['H'] = handle_reload, ['S'] = handle_stat, }; From 9eb410b34795d7595a1f8aba6fba6c8904a17cbf Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 08:28:22 -0600 Subject: [PATCH 16/96] rdns: properly set provider --- authd/providers/rdns.c | 1 + 1 file changed, 1 insertion(+) diff --git a/authd/providers/rdns.c b/authd/providers/rdns.c index 92f53822..34cd1674 100644 --- a/authd/providers/rdns.c +++ b/authd/providers/rdns.c @@ -94,6 +94,7 @@ bool client_dns_start(struct auth_client *auth) gethost_byaddr(&auth->c_addr, &query->query); notice_client(auth, messages[REPORT_LOOKUP]); + set_provider(auth, PROVIDER_RDNS); return true; } From c70ae2e5cbb5fb492e0163f35d5d4efe16162e1f Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 08:43:46 -0600 Subject: [PATCH 17/96] authd: properly iterate through all outstanding rdns queries on timeout --- authd/providers/rdns.c | 1 - 1 file changed, 1 deletion(-) diff --git a/authd/providers/rdns.c b/authd/providers/rdns.c index 34cd1674..611a41a6 100644 --- a/authd/providers/rdns.c +++ b/authd/providers/rdns.c @@ -186,7 +186,6 @@ static void timeout_dns_queries_event(void *notused) if(query->auth && query->timeout < rb_current_time()) { client_fail(query, REPORT_FAIL); - return; } } } From b74739c247f516dcbdc3f96b815df1f655a7a6b7 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 09:32:37 -0600 Subject: [PATCH 18/96] auth: use sockaddr_storage to store ports --- authd/provider.c | 21 ++++++++++++++++----- authd/provider.h | 5 +---- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index c83e5761..51ee9ee0 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -174,7 +174,7 @@ void notice_client(struct auth_client *auth, const char *notice) } /* Begin authenticating user */ -static void start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_addr, const char *c_port) +static void start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_ip, const char *c_port) { rb_dlink_node *ptr; struct auth_provider *provider; @@ -191,11 +191,22 @@ static void start_auth(const char *cid, const char *l_ip, const char *l_port, co auth->cid = (uint16_t)lcid; - (void)rb_inet_pton_sock(l_ip, (struct sockaddr *)&auth->l_ip); - auth->l_port = (uint16_t)atoi(l_port); /* Safe cast, port shouldn't exceed 16 bits */ + (void)rb_inet_pton_sock(l_ip, (struct sockaddr *)&auth->l_addr); +#ifdef RB_IPV6 + if(GET_SS_FAMILY(&auth->l_addr) == AF_INET6) + ((struct sockaddr_in6 *)&auth->l_addr)->sin6_port = htons(atoi(l_ip)); + else +#endif + ((struct sockaddr_in *)&auth->l_addr)->sin_port = htons(atoi(l_ip)); + + (void)rb_inet_pton_sock(c_ip, (struct sockaddr *)&auth->c_addr); +#ifdef RB_IPV6 + if(GET_SS_FAMILY(&auth->c_addr) == AF_INET6) + ((struct sockaddr_in6 *)&auth->c_addr)->sin6_port = htons(atoi(c_ip)); + else +#endif + ((struct sockaddr_in *)&auth->c_addr)->sin_port = htons(atoi(c_ip)); - (void)rb_inet_pton_sock(c_addr, (struct sockaddr *)&auth->c_addr); - auth->c_port = (uint16_t)atoi(c_port); RB_DLINK_FOREACH(ptr, auth_providers.head) { diff --git a/authd/provider.h b/authd/provider.h index 8bd4d18f..a7a7905a 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -39,11 +39,8 @@ struct auth_client { uint16_t cid; /* Client ID */ - struct rb_sockaddr_storage l_ip; /* Listener IP address */ - uint16_t l_port; /* Listener port */ - + struct rb_sockaddr_storage l_addr; /* Listener IP address */ struct rb_sockaddr_storage c_addr; /* Client IP address */ - uint16_t c_port; /* Client port */ char hostname[HOSTLEN + 1]; /* Used for DNS lookup */ char username[USERLEN + 1]; /* Used for ident lookup */ From f1861e48e695bba274f719e0b7d7110613f57053 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 10:00:46 -0600 Subject: [PATCH 19/96] authd: identd fixes --- authd/Makefile.am | 3 +- authd/provider.h | 1 + authd/providers/ident.c | 405 ++++++++++++++++++++++++++++++++++++++++ authd/providers/rdns.c | 8 +- 4 files changed, 412 insertions(+), 5 deletions(-) create mode 100644 authd/providers/ident.c diff --git a/authd/Makefile.am b/authd/Makefile.am index 8848b761..cc15db5a 100644 --- a/authd/Makefile.am +++ b/authd/Makefile.am @@ -8,6 +8,7 @@ authd_SOURCES = provider.c \ res.c \ reslib.c \ dns.c \ - providers/rdns.c + providers/rdns.c \ + providers/ident.c authd_LDADD = ../librb/src/librb.la diff --git a/authd/provider.h b/authd/provider.h index a7a7905a..494e3328 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -71,6 +71,7 @@ struct auth_provider extern rb_dlink_list auth_providers; extern struct auth_provider rdns_provider; +extern struct auth_provider ident_provider; extern struct auth_client auth_clients[MAX_CLIENTS]; diff --git a/authd/providers/ident.c b/authd/providers/ident.c new file mode 100644 index 00000000..0b943b48 --- /dev/null +++ b/authd/providers/ident.c @@ -0,0 +1,405 @@ +/* authd/providers/ident.c - ident lookup provider for authd + * Copyright (c) 2016 Elizabeth Myers + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stdinc.h" +#include "match.h" +#include "authd.h" +#include "provider.h" +#include "res.h" + +#define IDENT_BUFSIZE 128 + +struct ident_query +{ + rb_dlink_node node; + + struct auth_client *auth; /* Our client */ + time_t timeout; /* Timeout interval */ + rb_fde_t *F; /* Our FD */ +}; + +/* Goinked from old s_auth.c --Elizafox */ +static const char *messages[] = +{ + ":*** Checking Ident", + ":*** Got Ident response", + ":*** No Ident response", +}; + +typedef enum +{ + REPORT_LOOKUP, + REPORT_FOUND, + REPORT_FAIL, +} ident_message; + +static EVH timeout_ident_queries_event; +static CNCB ident_connected; +static PF read_ident_reply; + +static void client_fail(struct ident_query *query, ident_message message); +static void client_success(struct ident_query *query); +static void cleanup_query(struct ident_query *query); +static char * get_valid_ident(char *buf); + +static rb_dlink_list queries; +static struct ev_entry *timeout_ev; +static int ident_timeout = 5; + + +bool ident_init(void) +{ + timeout_ev = rb_event_addish("timeout_ident_queries_event", timeout_ident_queries_event, NULL, 1); + return (timeout_ev != NULL); +} + +void ident_destroy(void) +{ + rb_dlink_node *ptr, *nptr; + + /* Nuke all ident queries */ + RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) + { + struct ident_query *query = ptr->data; + + notice_client(query->auth, messages[REPORT_FAIL]); + + rb_close(query->F); + rb_free(query); + rb_dlinkDelete(ptr, &queries); + } +} + +bool ident_start(struct auth_client *auth) +{ + struct ident_query *query = rb_malloc(sizeof(struct ident_query)); + struct rb_sockaddr_storage localaddr, clientaddr; + int family; + rb_fde_t *F; + + query->auth = auth; + query->timeout = rb_current_time() + ident_timeout; + + if((F = rb_socket(family, SOCK_STREAM, 0, "ident")) == NULL) + { + client_fail(query, REPORT_FAIL); + return true; /* Not a fatal error */ + } + + query->F = F; + + /* Build sockaddr_storages for rb_connect_tcp below */ + memcpy(&localaddr, &auth->l_addr, sizeof(struct rb_sockaddr_storage)); + memcpy(&clientaddr, &auth->c_addr, sizeof(struct rb_sockaddr_storage)); + + /* Set the ports correctly */ +#ifdef RB_IPV6 + if(GET_SS_FAMILY(&localaddr) == AF_INET6) + ((struct sockaddr_in6 *)&localaddr)->sin6_port = 0; + else +#endif + ((struct sockaddr_in *)&localaddr)->sin_port = 0; + +#ifdef RB_IPV6 + if(GET_SS_FAMILY(&clientaddr) == AF_INET6) + ((struct sockaddr_in6 *)&clientaddr)->sin6_port = htons(113); + else +#endif + ((struct sockaddr_in *)&clientaddr)->sin_port = htons(113); + + rb_connect_tcp(F, (struct sockaddr *)&auth->c_addr, + (struct sockaddr *)&auth->l_addr, + GET_SS_LEN(&auth->l_addr), ident_connected, + query, ident_timeout); + + set_provider(auth, PROVIDER_IDENT); + + rb_dlinkAdd(query, &query->node, &queries); + + notice_client(auth, messages[REPORT_LOOKUP]); + + return true; +} + +void ident_cancel(struct auth_client *auth) +{ + rb_dlink_node *ptr, *nptr; + + RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) + { + struct ident_query *query = ptr->data; + + if(query->auth == auth) + { + client_fail(query, REPORT_FAIL); + + rb_close(query->F); + rb_free(query); + rb_dlinkDelete(ptr, &queries); + + return; + } + } +} + +/* Timeout outstanding queries */ +static void timeout_ident_queries_event(void *notused) +{ + rb_dlink_node *ptr, *nptr; + + RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) + { + struct ident_query *query = ptr->data; + + if(query->timeout < rb_current_time()) + { + client_fail(query, REPORT_FAIL); + + rb_close(query->F); + rb_free(query); + rb_dlinkDelete(ptr, &queries); + } + } +} + +/* + * ident_connected() - deal with the result of rb_connect_tcp() + * + * If the connection failed, we simply close the auth fd and report + * a failure. If the connection suceeded send the ident server a query + * giving "theirport , ourport". The write is only attempted *once* so + * it is deemed to be a fail if the entire write doesn't write all the + * data given. This shouldnt be a problem since the socket should have + * a write buffer far greater than this message to store it in should + * problems arise. -avalon + */ +static void ident_connected(rb_fde_t *F, int error, void *data) +{ + struct ident_query *query = data; + struct auth_client *auth = query->auth; + uint16_t c_port, l_port; + char authbuf[32]; + int authlen; + + /* Check the error */ + if(error != RB_OK) + { + /* We had an error during connection :( */ + client_fail(query, REPORT_FAIL); + cleanup_query(query); + return; + } + +#ifdef RB_IPV6 + if(GET_SS_FAMILY(&auth->c_addr) == AF_INET6) + c_port = ntohs(((struct sockaddr_in6 *)&auth->c_addr)->sin6_port); + else +#endif + c_port = ntohs(((struct sockaddr_in *)&auth->c_addr)->sin_port); + +#ifdef RB_IPV6 + if(GET_SS_FAMILY(&auth->l_addr) == AF_INET6) + l_port = ntohs(((struct sockaddr_in6 *)&auth->l_addr)->sin6_port); + else +#endif + l_port = ntohs(((struct sockaddr_in *)&auth->l_addr)->sin_port); + + + snprintf(authbuf, sizeof(authbuf), "%u , %u\r\n", + c_port, l_port); + authlen = strlen(authbuf); + + if(rb_write(query->F, authbuf, authlen) != authlen) + { + client_fail(query, REPORT_FAIL); + return; + } + + read_ident_reply(query->F, query); +} + +static void +read_ident_reply(rb_fde_t *F, void *data) +{ + struct ident_query *query = data; + struct auth_client *auth = query->auth; + char *s = NULL; + char *t = NULL; + int len; + int count; + char buf[IDENT_BUFSIZE + 1]; /* buffer to read auth reply into */ + + len = rb_read(F, buf, IDENT_BUFSIZE); + if(len < 0 && rb_ignore_errno(errno)) + { + rb_setselect(F, RB_SELECT_READ, read_ident_reply, query); + return; + } + + if(len > 0) + { + buf[len] = '\0'; + + if((s = get_valid_ident(buf))) + { + t = auth->username; + + while (*s == '~' || *s == '^') + s++; + + for (count = USERLEN; *s && count; s++) + { + if(*s == '@') + { + break; + } + if(*s != ' ' && *s != ':' && *s != '[') + { + *t++ = *s; + count--; + } + } + *t = '\0'; + } + } + + if(s == NULL) + client_fail(query, REPORT_FAIL); + else + client_success(query); + + cleanup_query(query); +} + +static void client_fail(struct ident_query *query, ident_message report) +{ + struct auth_client *auth = query->auth; + + if(auth) + { + rb_strlcpy(auth->username, "*", sizeof(auth->username)); + notice_client(auth, messages[report]); + provider_done(auth, PROVIDER_IDENT); + } +} + +static void client_success(struct ident_query *query) +{ + struct auth_client *auth = query->auth; + + if(auth) + { + notice_client(auth, messages[REPORT_FOUND]); + provider_done(auth, PROVIDER_IDENT); + } +} + +static void cleanup_query(struct ident_query *query) +{ + rb_dlink_node *ptr, *nptr; + + RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) + { + struct ident_query *query_l = ptr->data; + + if(query_l == query) + { + rb_close(query->F); + rb_free(query); + rb_dlinkDelete(ptr, &queries); + } + } +} + +/* get_valid_ident + * parse ident query reply from identd server + * + * Torn out of old s_auth.c because there was nothing wrong with it + * --Elizafox + * + * Inputs - pointer to ident buf + * Outputs - NULL if no valid ident found, otherwise pointer to name + * Side effects - None + */ +static char * +get_valid_ident(char *buf) +{ + int remp = 0; + int locp = 0; + char *colon1Ptr; + char *colon2Ptr; + char *colon3Ptr; + char *commaPtr; + char *remotePortString; + + /* All this to get rid of a sscanf() fun. */ + remotePortString = buf; + + colon1Ptr = strchr(remotePortString, ':'); + if(!colon1Ptr) + return 0; + + *colon1Ptr = '\0'; + colon1Ptr++; + colon2Ptr = strchr(colon1Ptr, ':'); + if(!colon2Ptr) + return 0; + + *colon2Ptr = '\0'; + colon2Ptr++; + commaPtr = strchr(remotePortString, ','); + + if(!commaPtr) + return 0; + + *commaPtr = '\0'; + commaPtr++; + + remp = atoi(remotePortString); + if(!remp) + return 0; + + locp = atoi(commaPtr); + if(!locp) + return 0; + + /* look for USERID bordered by first pair of colons */ + if(!strstr(colon1Ptr, "USERID")) + return 0; + + colon3Ptr = strchr(colon2Ptr, ':'); + if(!colon3Ptr) + return 0; + + *colon3Ptr = '\0'; + colon3Ptr++; + return (colon3Ptr); +} + + +struct auth_provider ident_provider = +{ + .id = PROVIDER_IDENT, + .init = ident_init, + .destroy = ident_destroy, + .start = ident_start, + .cancel = ident_cancel, + .completed = NULL, +}; diff --git a/authd/providers/rdns.c b/authd/providers/rdns.c index 611a41a6..f06bbf0a 100644 --- a/authd/providers/rdns.c +++ b/authd/providers/rdns.c @@ -56,14 +56,14 @@ static void client_fail(struct dns_query *query, dns_message message); static void client_success(struct dns_query *query); static void get_dns_answer(void *userdata, struct DNSReply *reply); -rb_dlink_list queries; +static rb_dlink_list queries; static struct ev_entry *timeout_ev; -int timeout = 30; +static int rdns_timeout = 30; bool client_dns_init(void) { - timeout_ev = rb_event_addish("timeout_dns_queries_event", timeout_dns_queries_event, NULL, 1); + timeout_ev = rb_event_addish("timeout_dns_queries_event", timeout_dns_queries_event, NULL, 5); return (timeout_ev != NULL); } @@ -87,7 +87,7 @@ bool client_dns_start(struct auth_client *auth) struct dns_query *query = rb_malloc(sizeof(struct dns_query)); query->auth = auth; - query->timeout = rb_current_time() + timeout; + query->timeout = rb_current_time() + rdns_timeout; query->query.ptr = query; query->query.callback = get_dns_answer; From 8b4544c9dcb20bfb42b0a4e0f520865767a872e6 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 10:01:41 -0600 Subject: [PATCH 20/96] authd: load ident provider --- authd/provider.c | 1 + 1 file changed, 1 insertion(+) diff --git a/authd/provider.c b/authd/provider.c index 51ee9ee0..9c3ba81f 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -67,6 +67,7 @@ void unload_provider(struct auth_provider *provider) void init_providers(void) { load_provider(&rdns_provider); + load_provider(&ident_provider); } /* Terminate all providers */ From c2222d7e9a7071350f15c125e7906b36e3240260 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 10:04:35 -0600 Subject: [PATCH 21/96] authd: actually init providers on startup. (Yay, it doesn't crash!) --- authd/authd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/authd/authd.c b/authd/authd.c index 50333004..bb01be82 100644 --- a/authd/authd.c +++ b/authd/authd.c @@ -153,6 +153,7 @@ main(int argc, char *argv[]) rb_set_time(); setup_signals(); init_resolver(); + init_providers(); rb_init_prng(NULL, RB_PRNG_DEFAULT); rb_helper_loop(authd_helper, 0); From df32819e04d966b898a7baa024b1554008fb6c68 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 11:27:07 -0600 Subject: [PATCH 22/96] authd: tag rejection type. --- authd/provider.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/authd/provider.c b/authd/provider.c index 9c3ba81f..97a2e882 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -142,8 +142,26 @@ void provider_done(struct auth_client *auth, provider_t id) void reject_client(struct auth_client *auth, provider_t id, const char *reason) { uint16_t cid = auth->cid; + char reject; - rb_helper_write(authd_helper, "R %x :%s", auth->cid, reason); + switch(id) + { + case PROVIDER_RDNS: + reject = 'D'; + break; + case PROVIDER_IDENT: + reject = 'I'; + break; + case PROVIDER_BLACKLIST: + reject = 'B'; + break; + case PROVIDER_NULL: + default: + reject = 'N'; + break; + } + + rb_helper_write(authd_helper, "R %x %c :%s", auth->cid, reject, reason); unset_provider(auth, id); From 91f870b39b86a5800ab520c7962097de808f22dc Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 11:30:09 -0600 Subject: [PATCH 23/96] auth: enable soft reject of clients. This doesn't cancel callbacks in progress. This is useful in cases where you're not sure you want to reject a client yet. --- authd/provider.c | 13 +++++++------ authd/provider.h | 6 +++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index 97a2e882..bd46f53c 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -83,7 +83,7 @@ void destroy_providers(void) { /* TBD - is this the right thing? * (NOTE - this error message is designed for morons) */ - reject_client(&auth_clients[i], 0, + reject_client(&auth_clients[i], 0, true, "IRC server reloading... try reconnecting in a few seconds"); } } @@ -138,8 +138,8 @@ void provider_done(struct auth_client *auth, provider_t id) } } -/* Reject a client, cancel outstanding providers if any */ -void reject_client(struct auth_client *auth, provider_t id, const char *reason) +/* Reject a client, cancel outstanding providers if any if hard set to true */ +void reject_client(struct auth_client *auth, provider_t id, bool hard, const char *reason) { uint16_t cid = auth->cid; char reject; @@ -165,10 +165,11 @@ void reject_client(struct auth_client *auth, provider_t id, const char *reason) unset_provider(auth, id); - if(auth->providers) + if(hard && auth->providers) + { cancel_providers(auth); - - memset(&auth_clients[cid], 0, sizeof(struct auth_client)); + memset(&auth_clients[cid], 0, sizeof(struct auth_client)); + } } /* Accept a client, cancel outstanding providers if any */ diff --git a/authd/provider.h b/authd/provider.h index 494e3328..4f3c57a9 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -82,9 +82,9 @@ void init_providers(void); void destroy_providers(void); void cancel_providers(struct auth_client *auth); -void provider_done(struct auth_client *auth, provider_t provider); -void reject_client(struct auth_client *auth, provider_t provider, const char *reason); -void accept_client(struct auth_client *auth, provider_t provider); +void provider_done(struct auth_client *auth, provider_t id); +void accept_client(struct auth_client *auth, provider_t id); +void reject_client(struct auth_client *auth, provider_t id, bool hard, const char *reason); void notice_client(struct auth_client *auth, const char *notice); From 43f599bb87de80e16c4117aadf195694d0f9d5df Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 11:32:46 -0600 Subject: [PATCH 24/96] Stop building this branch plzkthxbai --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 4329ca7a..48c28dc5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,6 +44,10 @@ matrix: compiler: clang env: COMPILER=clang LIBTOOLIZE=glibtoolize +branches: + only: + - master + osx_image: xcode7.3 cache: From b63612893f59930cb89734902f36ae3e5eba4c06 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 10 Mar 2016 11:42:37 -0600 Subject: [PATCH 25/96] What I really meant to say. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 48c28dc5..ad8efb37 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,8 +45,8 @@ matrix: env: COMPILER=clang LIBTOOLIZE=glibtoolize branches: - only: - - master + except: + - authd-framework osx_image: xcode7.3 From 2b0cc3d36a1c494bec926b4d087e3fe9240a94e9 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 17 Mar 2016 16:23:27 -0500 Subject: [PATCH 26/96] Redo of the authd-framework branch. This is basically most of the code from the authd-framework branch, but written to the new DNS code in master. Not quite done yet but getting there. --- authd/Makefile.am | 9 +- authd/dns.c | 31 ++-- authd/dns.h | 2 +- authd/provider.c | 245 +++++++++++++++++++++++++ authd/provider.h | 114 ++++++++++++ authd/providers/ident.c | 392 ++++++++++++++++++++++++++++++++++++++++ authd/providers/rdns.c | 210 +++++++++++++++++++++ 7 files changed, 986 insertions(+), 17 deletions(-) create mode 100644 authd/provider.c create mode 100644 authd/provider.h create mode 100644 authd/providers/ident.c create mode 100644 authd/providers/rdns.c diff --git a/authd/Makefile.am b/authd/Makefile.am index e1b705e1..fd8299e6 100644 --- a/authd/Makefile.am +++ b/authd/Makefile.am @@ -2,6 +2,13 @@ pkglibexec_PROGRAMS = authd AM_CFLAGS=$(WARNFLAGS) AM_CPPFLAGS = -I../include -I../librb/include +authd_SOURCES = \ + authd.c \ + res.c \ + reslib.c \ + dns.c \ + provider.c \ + providers/rdns.c \ + providers/ident.c -authd_SOURCES = authd.c res.c reslib.c dns.c authd_LDADD = ../librb/src/librb.la diff --git a/authd/dns.c b/authd/dns.c index 52e3191c..198a4ad3 100644 --- a/authd/dns.c +++ b/authd/dns.c @@ -69,9 +69,10 @@ lookup_ip(const char *host, int aftype, DNSCB callback, void *data) /* See lookup_ip's comment */ struct dns_query * -lookup_hostname(const char *ip, int aftype, DNSCB callback, void *data) +lookup_hostname(const char *ip, DNSCB callback, void *data) { struct dns_query *query = rb_malloc(sizeof(struct dns_query)); + int aftype; if(!rb_inet_pton_sock(ip, (struct sockaddr *)&query->addr)) { @@ -79,6 +80,8 @@ lookup_hostname(const char *ip, int aftype, DNSCB callback, void *data) return NULL; } + aftype = GET_SS_FAMILY(&query->addr); + if(aftype == AF_INET) query->type = QUERY_PTR_A; #ifdef RB_IPV6 @@ -121,10 +124,10 @@ handle_lookup_ip_reply(void *data, struct DNSReply *reply) if(!query) /* Shouldn't happen */ exit(2); - + type = query->type; - if(!reply) + if(reply == NULL) goto end; switch(query->type) @@ -165,13 +168,13 @@ handle_lookup_hostname_reply(void *data, struct DNSReply *reply) char *hostname = NULL; query_type type = QUERY_INVALID; - if(!query) + if(query == NULL) /* Shouldn't happen */ exit(4); type = query->type; - if(!reply) + if(reply == NULL) goto end; if(query->type == QUERY_PTR_A) @@ -180,7 +183,7 @@ handle_lookup_hostname_reply(void *data, struct DNSReply *reply) ip = (struct sockaddr_in *) &query->addr; ip_fwd = (struct sockaddr_in *) &reply->addr; - if(ip->sin_addr.s_addr == ip_fwd->sin_addr.s_addr && strlen(reply->h_name) < 63) + if(ip->sin_addr.s_addr == ip_fwd->sin_addr.s_addr) hostname = reply->h_name; } #ifdef RB_IPV6 @@ -190,7 +193,7 @@ handle_lookup_hostname_reply(void *data, struct DNSReply *reply) ip = (struct sockaddr_in6 *) &query->addr; ip_fwd = (struct sockaddr_in6 *) &reply->addr; - if(memcmp(&ip->sin6_addr, &ip_fwd->sin6_addr, sizeof(struct in6_addr)) == 0 && strlen(reply->h_name) < 63) + if(memcmp(&ip->sin6_addr, &ip_fwd->sin6_addr, sizeof(struct in6_addr)) == 0) hostname = reply->h_name; } #endif @@ -212,7 +215,7 @@ submit_dns_answer(const char *reply, bool status, query_type type, void *data) if(!id || type == QUERY_INVALID) exit(6); - if(!reply || !status) + if(reply == NULL || status == false) { rb_helper_write(authd_helper, "E %s E %c *", id, type); rb_free(id); @@ -243,10 +246,9 @@ resolve_dns(int parc, char *parv[]) break; #ifdef RB_IPV6 case 'S': - aftype = AF_INET6; #endif case 'R': - if(!lookup_hostname(record, aftype, submit_dns_answer, id)) + if(!lookup_hostname(record, submit_dns_answer, id)) submit_dns_answer(NULL, false, qtype, NULL); break; default: @@ -257,7 +259,7 @@ resolve_dns(int parc, char *parv[]) void enumerate_nameservers(const char *rid, const char letter) { - char buf[40 * IRCD_MAXNS]; /* Plenty */ + char buf[(HOSTIPLEN + 1) * IRCD_MAXNS]; char *c = buf; int i; @@ -270,8 +272,7 @@ enumerate_nameservers(const char *rid, const char letter) for(i = 0; i < irc_nscount; i++) { - char addr[40]; - int ret; + char addr[HOSTIPLEN]; rb_inet_ntop_sock((struct sockaddr *)&irc_nsaddr_list[i], addr, sizeof(addr)); @@ -282,8 +283,8 @@ enumerate_nameservers(const char *rid, const char letter) return; } - ret = snprintf(c, 40, "%s ", addr); - c += (size_t)ret; + (void)snprintf(c, HOSTIPLEN + 1, "%s ", addr); + c += strlen(addr) + 1; } *(--c) = '\0'; diff --git a/authd/dns.h b/authd/dns.h index 4a977b28..a21d9858 100644 --- a/authd/dns.h +++ b/authd/dns.h @@ -50,7 +50,7 @@ struct dns_query void *data; }; -extern struct dns_query *lookup_hostname(const char *ip, int aftype, DNSCB callback, void *data); +extern struct dns_query *lookup_hostname(const char *ip, DNSCB callback, void *data); extern struct dns_query *lookup_ip(const char *host, int aftype, DNSCB callback, void *data); extern void cancel_query(struct dns_query *query); diff --git a/authd/provider.c b/authd/provider.c new file mode 100644 index 00000000..fc695bc0 --- /dev/null +++ b/authd/provider.c @@ -0,0 +1,245 @@ +/* authd/provider.c - authentication provider framework + * Copyright (c) 2016 Elizabeth Myers + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* So the basic design here is to have "authentication providers" that do + * things like query ident and blacklists and even open proxies. + * + * Providers are registered statically in the struct auth_providers array. You will + * probably want to add an item to the provider_t enum also. + * + * Providers can either return failure immediately, immediate acceptance, or + * do work in the background (calling set_provider to signal this). + * + * It is up to providers to keep their own state on clients if they need to. + * + * All providers must implement at a minimum a perform_provider function. You + * don't have to implement the others if you don't need them. + * + * Providers may kick clients off by rejecting them. Upon rejection, all + * providers are cancelled. They can also unconditionally accept them. + * + * When a provider is done and is neutral on accepting/rejecting a client, it + * should call provider_done. Do NOT call this if you have accepted or rejected + * the client. + * + * --Elizafox, 9 March 2016 + */ + +#include "authd.h" +#include "provider.h" + +rb_dlink_list auth_providers; + +/* Clients waiting */ +struct auth_client auth_clients[MAX_CLIENTS]; + +/* Load a provider */ +void load_provider(struct auth_provider *provider) +{ + provider->init(); + rb_dlinkAdd(provider, &provider->node, &auth_providers); +} + +void unload_provider(struct auth_provider *provider) +{ + provider->destroy(); + rb_dlinkDelete(&provider->node, &auth_providers); +} + +/* Initalise all providers */ +void init_providers(void) +{ + load_provider(&rdns_provider); + load_provider(&ident_provider); +} + +/* Terminate all providers */ +void destroy_providers(void) +{ + rb_dlink_node *ptr; + struct auth_provider *provider; + + /* Cancel outstanding connections */ + for (size_t i = 0; i < MAX_CLIENTS; i++) + { + if(auth_clients[i].cid) + { + /* TBD - is this the right thing? + * (NOTE - this error message is designed for morons) */ + reject_client(&auth_clients[i], 0, true, + "IRC server reloading... try reconnecting in a few seconds"); + } + } + + RB_DLINK_FOREACH(ptr, auth_providers.head) + { + provider = ptr->data; + + if(provider->destroy) + provider->destroy(); + } +} + +/* Cancel outstanding providers for a client */ +void cancel_providers(struct auth_client *auth) +{ + rb_dlink_node *ptr; + struct auth_provider *provider; + + RB_DLINK_FOREACH(ptr, auth_providers.head) + { + provider = ptr->data; + + if(provider->cancel && is_provider(auth, provider->id)) + /* Cancel if required */ + provider->cancel(auth); + } +} + +/* Provider is done */ +void provider_done(struct auth_client *auth, provider_t id) +{ + rb_dlink_node *ptr; + struct auth_provider *provider; + + unset_provider(auth, id); + + if(!auth->providers) + { + /* No more providers, done */ + accept_client(auth, 0); + return; + } + + RB_DLINK_FOREACH(ptr, auth_providers.head) + { + provider = ptr->data; + + if(provider->completed && is_provider(auth, provider->id)) + /* Notify pending clients who asked for it */ + provider->completed(auth, id); + } +} + +/* Reject a client, cancel outstanding providers if any if hard set to true */ +void reject_client(struct auth_client *auth, provider_t id, bool hard, const char *reason) +{ + uint16_t cid = auth->cid; + char reject; + + switch(id) + { + case PROVIDER_RDNS: + reject = 'D'; + break; + case PROVIDER_IDENT: + reject = 'I'; + break; + case PROVIDER_BLACKLIST: + reject = 'B'; + break; + case PROVIDER_NULL: + default: + reject = 'N'; + break; + } + + rb_helper_write(authd_helper, "R %x %c :%s", auth->cid, reject, reason); + + unset_provider(auth, id); + + if(hard && auth->providers) + { + cancel_providers(auth); + memset(&auth_clients[cid], 0, sizeof(struct auth_client)); + } +} + +/* Accept a client, cancel outstanding providers if any */ +void accept_client(struct auth_client *auth, provider_t id) +{ + uint16_t cid = auth->cid; + + rb_helper_write(authd_helper, "A %x %s %s", auth->cid, auth->username, auth->hostname); + + unset_provider(auth, id); + + if(auth->providers) + cancel_providers(auth); + + memset(&auth_clients[cid], 0, sizeof(struct auth_client)); +} + +/* Send a notice to a client */ +void notice_client(struct auth_client *auth, const char *notice) +{ + rb_helper_write(authd_helper, "N %x :%s", auth->cid, notice); +} + +/* Begin authenticating user */ +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; + long lcid = strtol(cid, NULL, 16); + rb_dlink_node *ptr; + + if(lcid >= MAX_CLIENTS) + return; + + auth = &auth_clients[lcid]; + if(auth->cid != 0) + /* Shouldn't get here */ + return; + + auth->cid = (uint16_t)lcid; + + rb_strlcpy(auth->l_ip, l_ip, sizeof(auth->l_ip)); + auth->l_port = (uint16_t)atoi(l_port); /* should be safe */ + + rb_strlcpy(auth->c_ip, c_ip, sizeof(auth->c_ip)); + auth->c_port = (uint16_t)atoi(c_port); + + RB_DLINK_FOREACH(ptr, auth_providers.head) + { + provider = ptr->data; + + /* Execute providers */ + if(!provider->start(auth)) + { + /* Rejected immediately */ + cancel_providers(auth); + return; + } + } + + /* If no providers are running, accept the client */ + if(!auth->providers) + accept_client(auth, 0); +} + +/* Callback for the initiation */ +void handle_new_connection(int parc, char *parv[]) +{ + if(parc < 7) + return; + + start_auth(parv[1], parv[2], parv[3], parv[4], parv[5]); +} diff --git a/authd/provider.h b/authd/provider.h new file mode 100644 index 00000000..8ce7e53e --- /dev/null +++ b/authd/provider.h @@ -0,0 +1,114 @@ +/* authd/provider.h - authentication provider framework + * Copyright (c) 2016 Elizabeth Myers + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __CHARYBDIS_AUTHD_PROVIDER_H__ +#define __CHARYBDIS_AUTHD_PROVIDER_H__ + +#include "stdinc.h" + +/* Arbitrary limit */ +#define MAX_CLIENTS 4096 + +/* Registered providers */ +typedef enum +{ + PROVIDER_NULL = 0x0, /* Dummy value */ + PROVIDER_RDNS = 0x1, + PROVIDER_IDENT = 0x2, + PROVIDER_BLACKLIST = 0x4, +} provider_t; + +struct auth_client +{ + uint16_t cid; /* Client ID */ + + char l_ip[HOSTIPLEN + 1]; /* Listener IP address */ + uint16_t l_port; /* Listener port */ + + char c_ip[HOSTIPLEN + 1]; /* Client IP address */ + uint16_t c_port; /* Client port */ + + char hostname[HOSTLEN + 1]; /* Used for DNS lookup */ + char username[USERLEN + 1]; /* Used for ident lookup */ + + unsigned int providers; /* Providers at work, + * none left when set to 0 */ +}; + +typedef bool (*provider_init_t)(void); +typedef bool (*provider_perform_t)(struct auth_client *); +typedef void (*provider_complete_t)(struct auth_client *, provider_t provider); +typedef void (*provider_cancel_t)(struct auth_client *); +typedef void (*provider_destroy_t)(void); + +struct auth_provider +{ + rb_dlink_node node; + + provider_t id; + + provider_init_t init; /* Initalise the provider */ + provider_destroy_t destroy; /* Terminate the provider */ + + provider_perform_t start; /* Perform authentication */ + provider_cancel_t cancel; /* Authentication cancelled */ + provider_complete_t completed; /* Callback for when other performers complete (think dependency chains) */ +}; + +extern rb_dlink_list auth_providers; +extern struct auth_provider rdns_provider; +extern struct auth_provider ident_provider; + +extern struct auth_client auth_clients[MAX_CLIENTS]; + +void load_provider(struct auth_provider *provider); +void unload_provider(struct auth_provider *provider); + +void init_providers(void); +void destroy_providers(void); +void cancel_providers(struct auth_client *auth); + +void provider_done(struct auth_client *auth, provider_t id); +void accept_client(struct auth_client *auth, provider_t id); +void reject_client(struct auth_client *auth, provider_t id, bool hard, const char *reason); + +void notice_client(struct auth_client *auth, const char *notice); + +void handle_new_connection(int parc, char *parv[]); + +/* Provider is operating on this auth_client (set this if you have async work to do) */ +static inline void set_provider(struct auth_client *auth, provider_t provider) +{ + auth->providers |= provider; +} + +/* Provider is no longer operating on this auth client (you should use provider_done) */ +static inline void unset_provider(struct auth_client *auth, provider_t provider) +{ + auth->providers &= ~provider; +} + +/* Check if provider is operating on this auth client */ +static inline bool is_provider(struct auth_client *auth, provider_t provider) +{ + return auth->providers & provider; +} + +#endif /* __CHARYBDIS_AUTHD_PROVIDER_H__ */ diff --git a/authd/providers/ident.c b/authd/providers/ident.c new file mode 100644 index 00000000..d633d172 --- /dev/null +++ b/authd/providers/ident.c @@ -0,0 +1,392 @@ +/* authd/providers/ident.c - ident lookup provider for authd + * Copyright (c) 2016 Elizabeth Myers + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stdinc.h" +#include "match.h" +#include "authd.h" +#include "provider.h" +#include "res.h" + +#define IDENT_BUFSIZE 128 + +struct ident_query +{ + rb_dlink_node node; + + struct auth_client *auth; /* Our client */ + time_t timeout; /* Timeout interval */ + rb_fde_t *F; /* Our FD */ +}; + +/* Goinked from old s_auth.c --Elizafox */ +static const char *messages[] = +{ + ":*** Checking Ident", + ":*** Got Ident response", + ":*** No Ident response", +}; + +typedef enum +{ + REPORT_LOOKUP, + REPORT_FOUND, + REPORT_FAIL, +} ident_message; + +static EVH timeout_ident_queries_event; +static CNCB ident_connected; +static PF read_ident_reply; + +static void client_fail(struct ident_query *query, ident_message message); +static void client_success(struct ident_query *query); +static void cleanup_query(struct ident_query *query); +static char * get_valid_ident(char *buf); + +static rb_dlink_list queries; +static struct ev_entry *timeout_ev; +static int ident_timeout = 5; + + +bool ident_init(void) +{ + timeout_ev = rb_event_addish("timeout_ident_queries_event", timeout_ident_queries_event, NULL, 1); + return (timeout_ev != NULL); +} + +void ident_destroy(void) +{ + rb_dlink_node *ptr, *nptr; + + /* Nuke all ident queries */ + RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) + { + struct ident_query *query = ptr->data; + + notice_client(query->auth, messages[REPORT_FAIL]); + + rb_close(query->F); + rb_free(query); + rb_dlinkDelete(ptr, &queries); + } +} + +bool ident_start(struct auth_client *auth) +{ + struct ident_query *query = rb_malloc(sizeof(struct ident_query)); + struct rb_sockaddr_storage l_addr, c_addr; + int family; + rb_fde_t *F; + + query->auth = auth; + query->timeout = rb_current_time() + ident_timeout; + + if((F = rb_socket(family, SOCK_STREAM, 0, "ident")) == NULL) + { + client_fail(query, REPORT_FAIL); + return true; /* Not a fatal error */ + } + + query->F = F; + + /* Build sockaddr_storages for rb_connect_tcp below */ + if(!rb_inet_ntop_sock((struct sockaddr *)&l_addr, auth->l_ip, sizeof(l_addr)) || + !rb_inet_ntop_sock((struct sockaddr *)&c_addr, auth->c_ip, sizeof(c_addr))) + { + client_fail(query, REPORT_FAIL); + return true; + } + + /* Set the ports correctly */ +#ifdef RB_IPV6 + if(GET_SS_FAMILY(&l_addr) == AF_INET6) + ((struct sockaddr_in6 *)&l_addr)->sin6_port = 0; + else +#endif + ((struct sockaddr_in *)&l_addr)->sin_port = 0; + +#ifdef RB_IPV6 + if(GET_SS_FAMILY(&c_addr) == AF_INET6) + ((struct sockaddr_in6 *)&c_addr)->sin6_port = htons(113); + else +#endif + ((struct sockaddr_in *)&c_addr)->sin_port = htons(113); + + rb_connect_tcp(F, (struct sockaddr *)&c_addr, + (struct sockaddr *)&l_addr, + GET_SS_LEN(&l_addr), ident_connected, + query, ident_timeout); + + rb_dlinkAdd(query, &query->node, &queries); + + set_provider(auth, PROVIDER_IDENT); + notice_client(auth, messages[REPORT_LOOKUP]); + + return true; +} + +void ident_cancel(struct auth_client *auth) +{ + rb_dlink_node *ptr, *nptr; + + RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) + { + struct ident_query *query = ptr->data; + + if(query->auth == auth) + { + client_fail(query, REPORT_FAIL); + + rb_close(query->F); + rb_free(query); + rb_dlinkDelete(ptr, &queries); + + return; + } + } +} + +/* Timeout outstanding queries */ +static void timeout_ident_queries_event(void *notused) +{ + rb_dlink_node *ptr, *nptr; + + RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) + { + struct ident_query *query = ptr->data; + + if(query->timeout < rb_current_time()) + { + client_fail(query, REPORT_FAIL); + + rb_close(query->F); + rb_free(query); + rb_dlinkDelete(ptr, &queries); + } + } +} + +/* + * ident_connected() - deal with the result of rb_connect_tcp() + * + * If the connection failed, we simply close the auth fd and report + * a failure. If the connection suceeded send the ident server a query + * giving "theirport , ourport". The write is only attempted *once* so + * it is deemed to be a fail if the entire write doesn't write all the + * data given. This shouldnt be a problem since the socket should have + * a write buffer far greater than this message to store it in should + * problems arise. -avalon + */ +static void ident_connected(rb_fde_t *F, int error, void *data) +{ + struct ident_query *query = data; + struct auth_client *auth = query->auth; + char authbuf[32]; + int authlen; + + /* Check the error */ + if(error != RB_OK) + { + /* We had an error during connection :( */ + client_fail(query, REPORT_FAIL); + cleanup_query(query); + return; + } + + snprintf(authbuf, sizeof(authbuf), "%u , %u\r\n", + auth->c_port, auth->l_port); + authlen = strlen(authbuf); + + if(rb_write(query->F, authbuf, authlen) != authlen) + { + client_fail(query, REPORT_FAIL); + return; + } + + read_ident_reply(query->F, query); +} + +static void +read_ident_reply(rb_fde_t *F, void *data) +{ + struct ident_query *query = data; + struct auth_client *auth = query->auth; + char *s = NULL; + char *t = NULL; + int len; + int count; + char buf[IDENT_BUFSIZE + 1]; /* buffer to read auth reply into */ + + len = rb_read(F, buf, IDENT_BUFSIZE); + if(len < 0 && rb_ignore_errno(errno)) + { + rb_setselect(F, RB_SELECT_READ, read_ident_reply, query); + return; + } + + if(len > 0) + { + buf[len] = '\0'; + + if((s = get_valid_ident(buf))) + { + t = auth->username; + + while (*s == '~' || *s == '^') + s++; + + for (count = USERLEN; *s && count; s++) + { + if(*s == '@') + { + break; + } + if(*s != ' ' && *s != ':' && *s != '[') + { + *t++ = *s; + count--; + } + } + *t = '\0'; + } + } + + if(s == NULL) + client_fail(query, REPORT_FAIL); + else + client_success(query); + + cleanup_query(query); +} + +static void client_fail(struct ident_query *query, ident_message report) +{ + struct auth_client *auth = query->auth; + + if(auth) + { + rb_strlcpy(auth->username, "*", sizeof(auth->username)); + notice_client(auth, messages[report]); + provider_done(auth, PROVIDER_IDENT); + } +} + +static void client_success(struct ident_query *query) +{ + struct auth_client *auth = query->auth; + + if(auth) + { + notice_client(auth, messages[REPORT_FOUND]); + provider_done(auth, PROVIDER_IDENT); + } +} + +static void cleanup_query(struct ident_query *query) +{ + rb_dlink_node *ptr, *nptr; + + RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) + { + struct ident_query *query_l = ptr->data; + + if(query_l == query) + { + rb_close(query->F); + rb_free(query); + rb_dlinkDelete(ptr, &queries); + } + } +} + +/* get_valid_ident + * parse ident query reply from identd server + * + * Torn out of old s_auth.c because there was nothing wrong with it + * --Elizafox + * + * Inputs - pointer to ident buf + * Outputs - NULL if no valid ident found, otherwise pointer to name + * Side effects - None + */ +static char * +get_valid_ident(char *buf) +{ + int remp = 0; + int locp = 0; + char *colon1Ptr; + char *colon2Ptr; + char *colon3Ptr; + char *commaPtr; + char *remotePortString; + + /* All this to get rid of a sscanf() fun. */ + remotePortString = buf; + + colon1Ptr = strchr(remotePortString, ':'); + if(!colon1Ptr) + return 0; + + *colon1Ptr = '\0'; + colon1Ptr++; + colon2Ptr = strchr(colon1Ptr, ':'); + if(!colon2Ptr) + return 0; + + *colon2Ptr = '\0'; + colon2Ptr++; + commaPtr = strchr(remotePortString, ','); + + if(!commaPtr) + return 0; + + *commaPtr = '\0'; + commaPtr++; + + remp = atoi(remotePortString); + if(!remp) + return 0; + + locp = atoi(commaPtr); + if(!locp) + return 0; + + /* look for USERID bordered by first pair of colons */ + if(!strstr(colon1Ptr, "USERID")) + return 0; + + colon3Ptr = strchr(colon2Ptr, ':'); + if(!colon3Ptr) + return 0; + + *colon3Ptr = '\0'; + colon3Ptr++; + return (colon3Ptr); +} + + +struct auth_provider ident_provider = +{ + .id = PROVIDER_IDENT, + .init = ident_init, + .destroy = ident_destroy, + .start = ident_start, + .cancel = ident_cancel, + .completed = NULL, +}; diff --git a/authd/providers/rdns.c b/authd/providers/rdns.c new file mode 100644 index 00000000..0a3c2e5e --- /dev/null +++ b/authd/providers/rdns.c @@ -0,0 +1,210 @@ +/* authd/providers/rdns.c - rDNS lookup provider for authd + * Copyright (c) 2016 Elizabeth Myers + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stdinc.h" +#include "rb_commio.h" +#include "authd.h" +#include "provider.h" +#include "res.h" +#include "dns.h" + +struct user_query +{ + rb_dlink_node node; + + struct auth_client *auth; /* Our client */ + struct dns_query *query; /* Pending DNS query */ + time_t timeout; /* When the request times out */ +}; + +/* Goinked from old s_auth.c --Elizabeth */ +static const char *messages[] = +{ + "*** Looking up your hostname...", + "*** Found your hostname", + "*** Couldn't look up your hostname", + "*** Your hostname is too long, ignoring hostname", +}; + +typedef enum +{ + REPORT_LOOKUP, + REPORT_FOUND, + REPORT_FAIL, + REPORT_TOOLONG, +} dns_message; + +static void client_fail(struct user_query *query, dns_message message); +static void client_success(struct user_query *query); +static void get_dns_answer(const char *res, bool status, query_type type, void *data); + +static struct ev_entry *timeout_ev; +static EVH timeout_dns_queries_event; +static int rdns_timeout = 30; +static rb_dlink_list queries; /* Stored here for easy timeout */ + + +bool client_dns_init(void) +{ + timeout_ev = rb_event_addish("timeout_dns_queries_event", timeout_dns_queries_event, NULL, 5); + return (timeout_ev != NULL); +} + +void client_dns_destroy(void) +{ + rb_dlink_node *ptr, *nptr; + struct user_query *query; + + RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) + { + client_fail(ptr->data, REPORT_FAIL); + rb_dlinkDelete(ptr, &queries); + rb_free(ptr); + } + + rb_event_delete(timeout_ev); +} + +bool client_dns_start(struct auth_client *auth) +{ + struct user_query *query = rb_malloc(sizeof(struct user_query)); + + query->auth = auth; + query->timeout = rb_current_time() + rdns_timeout; + + query->query = lookup_hostname(auth->c_ip, get_dns_answer, query); + + notice_client(auth, messages[REPORT_LOOKUP]); + set_provider(auth, PROVIDER_RDNS); + return true; +} + +void client_dns_cancel(struct auth_client *auth) +{ + rb_dlink_node *ptr, *nptr; + + RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) + { + struct user_query *query = ptr->data; + + if(query->auth == auth) + { + /* Victim found */ + client_fail(query, REPORT_FAIL); + rb_dlinkDelete(ptr, &queries); + rb_free(query); + return; + } + } +} + +static void +get_dns_answer(const char *res, bool status, query_type type, void *data) +{ + struct user_query *query = data; + struct auth_client *auth = query->auth; + bool fail = false; + dns_message response; + rb_dlink_node *ptr, *nptr; + + if(res == NULL || status == false) + { + response = REPORT_FAIL; + fail = true; + goto cleanup; + } + else if(strlen(res) > HOSTLEN) + { + /* Ah well. */ + response = REPORT_TOOLONG; + fail = true; + goto cleanup; + } + + rb_strlcpy(auth->hostname, res, HOSTLEN + 1); + +cleanup: + /* Clean us up off the pending queries list */ + RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) + { + struct user_query *query_l = ptr->data; + + if(query == query_l) + { + /* Found */ + if(fail) + client_fail(query, response); + else + client_success(query); + + rb_dlinkDelete(ptr, &queries); + rb_free(query); + return; + } + } +} + +/* Timeout outstanding queries */ +static void timeout_dns_queries_event(void *notused) +{ + rb_dlink_node *ptr, *nptr; + + RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) + { + struct user_query *query = ptr->data; + + if(query->auth && query->timeout < rb_current_time()) + { + client_fail(query, REPORT_FAIL); + rb_dlinkDelete(ptr, &queries); + rb_free(query); + return; + } + } +} + +static void client_fail(struct user_query *query, dns_message report) +{ + struct auth_client *auth = query->auth; + + rb_strlcpy(auth->hostname, "*", sizeof(auth->hostname)); + notice_client(auth, messages[report]); + cancel_query(query->query); + provider_done(auth, PROVIDER_RDNS); +} + +static void client_success(struct user_query *query) +{ + struct auth_client *auth = query->auth; + + notice_client(auth, messages[REPORT_FOUND]); + cancel_query(query->query); + provider_done(auth, PROVIDER_RDNS); +} + +struct auth_provider rdns_provider = +{ + .id = PROVIDER_RDNS, + .init = client_dns_init, + .destroy = client_dns_destroy, + .start = client_dns_start, + .cancel = client_dns_cancel, + .completed = NULL, +}; From a16b484f275a1888d46061ccb507fa90a04cbd1b Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 17 Mar 2016 16:25:58 -0500 Subject: [PATCH 27/96] Import this from authd-framework branch --- authd/authd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/authd/authd.c b/authd/authd.c index 62336833..bb01be82 100644 --- a/authd/authd.c +++ b/authd/authd.c @@ -20,6 +20,7 @@ #include "authd.h" #include "dns.h" +#include "provider.h" #define MAXPARA 10 @@ -28,8 +29,9 @@ static void handle_stat(int parc, char *parv[]); rb_helper *authd_helper = NULL; authd_cmd_handler authd_cmd_handlers[256] = { - ['H'] = handle_reload, + ['C'] = handle_new_connection, ['D'] = resolve_dns, + ['H'] = handle_reload, ['S'] = handle_stat, }; @@ -151,6 +153,7 @@ main(int argc, char *argv[]) rb_set_time(); setup_signals(); init_resolver(); + init_providers(); rb_init_prng(NULL, RB_PRNG_DEFAULT); rb_helper_loop(authd_helper, 0); From f7b37c1dc110f13c10a72d1f1b3e3b5f9bce22dd Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 19 Mar 2016 15:02:11 -0500 Subject: [PATCH 28/96] authd: add provider-specific data to auth_client via a dictionary. --- authd/provider.c | 23 +++++++++++++---------- authd/provider.h | 4 +++- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index fc695bc0..c9b3d318 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -21,13 +21,13 @@ /* So the basic design here is to have "authentication providers" that do * things like query ident and blacklists and even open proxies. * - * Providers are registered statically in the struct auth_providers array. You will - * probably want to add an item to the provider_t enum also. + * Providers are registered in the auth_providers linked list. It is planned to + * use a bitmap to store provider ID's later. * * Providers can either return failure immediately, immediate acceptance, or * do work in the background (calling set_provider to signal this). * - * It is up to providers to keep their own state on clients if they need to. + * A dictionary is provided in auth_client for storage of provider-specific data. * * All providers must implement at a minimum a perform_provider function. You * don't have to implement the others if you don't need them. @@ -81,10 +81,9 @@ void destroy_providers(void) { if(auth_clients[i].cid) { - /* TBD - is this the right thing? - * (NOTE - this error message is designed for morons) */ - reject_client(&auth_clients[i], 0, true, - "IRC server reloading... try reconnecting in a few seconds"); + /* TBD - is this the right thing? */ + reject_client(&auth_clients[i], 0, + "Authentication system is down... try reconnecting in a few seconds"); } } @@ -138,8 +137,8 @@ void provider_done(struct auth_client *auth, provider_t id) } } -/* Reject a client, cancel outstanding providers if any if hard set to true */ -void reject_client(struct auth_client *auth, provider_t id, bool hard, const char *reason) +/* Reject a client */ +void reject_client(struct auth_client *auth, provider_t id, const char *reason) { uint16_t cid = auth->cid; char reject; @@ -165,7 +164,7 @@ void reject_client(struct auth_client *auth, provider_t id, bool hard, const cha unset_provider(auth, id); - if(hard && auth->providers) + if(auth->providers) { cancel_providers(auth); memset(&auth_clients[cid], 0, sizeof(struct auth_client)); @@ -199,6 +198,7 @@ static void start_auth(const char *cid, const char *l_ip, const char *l_port, co struct auth_provider *provider; struct auth_client *auth; long lcid = strtol(cid, NULL, 16); + char name[20]; rb_dlink_node *ptr; if(lcid >= MAX_CLIENTS) @@ -217,6 +217,9 @@ static void start_auth(const char *cid, const char *l_ip, const char *l_port, co rb_strlcpy(auth->c_ip, c_ip, sizeof(auth->c_ip)); auth->c_port = (uint16_t)atoi(c_port); + snprintf("%d provider data", sizeof(name), auth->cid); + auth->data = rb_dictionary_create(name, rb_uint32cmp); + RB_DLINK_FOREACH(ptr, auth_providers.head) { provider = ptr->data; diff --git a/authd/provider.h b/authd/provider.h index 8ce7e53e..d443c0bb 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -50,6 +50,8 @@ struct auth_client unsigned int providers; /* Providers at work, * none left when set to 0 */ + + struct Dictionary *data; /* Provider-specific data */ }; typedef bool (*provider_init_t)(void); @@ -87,7 +89,7 @@ void cancel_providers(struct auth_client *auth); void provider_done(struct auth_client *auth, provider_t id); void accept_client(struct auth_client *auth, provider_t id); -void reject_client(struct auth_client *auth, provider_t id, bool hard, const char *reason); +void reject_client(struct auth_client *auth, provider_t id, const char *reason); void notice_client(struct auth_client *auth, const char *notice); From 893a92e7b3b3f43960928d9ef2802cde14ba718c Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 19 Mar 2016 15:58:30 -0500 Subject: [PATCH 29/96] rb_dictionary: add include needed for int types. --- librb/include/rb_dictionary.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/librb/include/rb_dictionary.h b/librb/include/rb_dictionary.h index 8008f932..88774dd6 100644 --- a/librb/include/rb_dictionary.h +++ b/librb/include/rb_dictionary.h @@ -25,6 +25,8 @@ #ifndef __RB_DICTIONARY_H__ #define __RB_DICTIONARY_H__ +#include "librb-config.h" + struct Dictionary; /* defined in src/dictionary.c */ typedef int (*DCF)(/* const void *a, const void *b */); From 46d17a88b4c8edfe156f4ae7d757fd9c014a409e Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 19 Mar 2016 15:58:48 -0500 Subject: [PATCH 30/96] provider: compile fixes --- authd/provider.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index c9b3d318..81c8dfc0 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -42,6 +42,7 @@ * --Elizafox, 9 March 2016 */ +#include "rb_dictionary.h" #include "authd.h" #include "provider.h" @@ -110,6 +111,10 @@ void cancel_providers(struct auth_client *auth) /* Cancel if required */ provider->cancel(auth); } + + /* All data should be already destroyed */ + rb_dictionary_destroy(auth->data, NULL, NULL); + auth->data = NULL; } /* Provider is done */ @@ -160,15 +165,12 @@ void reject_client(struct auth_client *auth, provider_t id, const char *reason) break; } + /* TODO send back ident */ rb_helper_write(authd_helper, "R %x %c :%s", auth->cid, reject, reason); unset_provider(auth, id); - - if(auth->providers) - { - cancel_providers(auth); - memset(&auth_clients[cid], 0, sizeof(struct auth_client)); - } + cancel_providers(auth); + memset(&auth_clients[cid], 0, sizeof(struct auth_client)); } /* Accept a client, cancel outstanding providers if any */ @@ -179,10 +181,7 @@ void accept_client(struct auth_client *auth, provider_t id) rb_helper_write(authd_helper, "A %x %s %s", auth->cid, auth->username, auth->hostname); unset_provider(auth, id); - - if(auth->providers) - cancel_providers(auth); - + cancel_providers(auth); memset(&auth_clients[cid], 0, sizeof(struct auth_client)); } @@ -217,7 +216,7 @@ static void start_auth(const char *cid, const char *l_ip, const char *l_port, co rb_strlcpy(auth->c_ip, c_ip, sizeof(auth->c_ip)); auth->c_port = (uint16_t)atoi(c_port); - snprintf("%d provider data", sizeof(name), auth->cid); + snprintf(name, sizeof(name), "%d provider data", auth->cid); auth->data = rb_dictionary_create(name, rb_uint32cmp); RB_DLINK_FOREACH(ptr, auth_providers.head) From 3e875f629fd79c94d29ee441a8fdacb25f31911d Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Tue, 22 Mar 2016 19:13:54 -0500 Subject: [PATCH 31/96] authd/provider: overhaul storage of various pieces of data Clients are stored in a dictionary referenced by id (to allow for UINT32_MAX auth clients, which is plenty). Each provider now has a data slot (this limits the number of providers to 32 for now, but that's plenty for now) which they can use to attach data to auth_clients. This consolidates data, aids in debugging, and makes it easier to just pass around auth_client structures. --- authd/provider.c | 48 ++++++-------- authd/provider.h | 25 ++++---- authd/providers/ident.c | 138 ++++++++++++++-------------------------- authd/providers/rdns.c | 117 +++++++++++++--------------------- 4 files changed, 121 insertions(+), 207 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index 81c8dfc0..ecbb45c5 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -27,7 +27,8 @@ * Providers can either return failure immediately, immediate acceptance, or * do work in the background (calling set_provider to signal this). * - * A dictionary is provided in auth_client for storage of provider-specific data. + * Provider-specific data for each client can be kept in an index of the data + * struct member (using the provider's ID). * * All providers must implement at a minimum a perform_provider function. You * don't have to implement the others if you don't need them. @@ -49,11 +50,15 @@ rb_dlink_list auth_providers; /* Clients waiting */ -struct auth_client auth_clients[MAX_CLIENTS]; +struct Dictionary *auth_clients; /* Load a provider */ void load_provider(struct auth_provider *provider) { + if(rb_dlink_list_length(&auth_providers) >= MAX_PROVIDERS) + /* XXX should probably warn here */ + return; + provider->init(); rb_dlinkAdd(provider, &provider->node, &auth_providers); } @@ -67,6 +72,7 @@ void unload_provider(struct auth_provider *provider) /* Initalise all providers */ void init_providers(void) { + auth_clients = rb_dictionary_create("pending auth clients", rb_uint32cmp); load_provider(&rdns_provider); load_provider(&ident_provider); } @@ -75,17 +81,15 @@ void init_providers(void) void destroy_providers(void) { rb_dlink_node *ptr; + struct DictionaryIter iter; + struct auth_client *auth; struct auth_provider *provider; /* Cancel outstanding connections */ - for (size_t i = 0; i < MAX_CLIENTS; i++) + DICTIONARY_FOREACH(auth, &iter, auth_clients) { - if(auth_clients[i].cid) - { - /* TBD - is this the right thing? */ - reject_client(&auth_clients[i], 0, - "Authentication system is down... try reconnecting in a few seconds"); - } + /* TBD - is this the right thing? */ + reject_client(auth, 0, "Authentication system is down... try reconnecting in a few seconds"); } RB_DLINK_FOREACH(ptr, auth_providers.head) @@ -112,9 +116,8 @@ void cancel_providers(struct auth_client *auth) provider->cancel(auth); } - /* All data should be already destroyed */ - rb_dictionary_destroy(auth->data, NULL, NULL); - auth->data = NULL; + rb_dictionary_delete(auth_clients, RB_UINT_TO_POINTER(auth->cid)); + rb_free(auth); } /* Provider is done */ @@ -145,7 +148,6 @@ void provider_done(struct auth_client *auth, provider_t id) /* Reject a client */ void reject_client(struct auth_client *auth, provider_t id, const char *reason) { - uint16_t cid = auth->cid; char reject; switch(id) @@ -159,7 +161,6 @@ void reject_client(struct auth_client *auth, provider_t id, const char *reason) case PROVIDER_BLACKLIST: reject = 'B'; break; - case PROVIDER_NULL: default: reject = 'N'; break; @@ -170,19 +171,17 @@ void reject_client(struct auth_client *auth, provider_t id, const char *reason) unset_provider(auth, id); cancel_providers(auth); - memset(&auth_clients[cid], 0, sizeof(struct auth_client)); } /* Accept a client, cancel outstanding providers if any */ void accept_client(struct auth_client *auth, provider_t id) { - uint16_t cid = auth->cid; + uint32_t cid = auth->cid; rb_helper_write(authd_helper, "A %x %s %s", auth->cid, auth->username, auth->hostname); unset_provider(auth, id); cancel_providers(auth); - memset(&auth_clients[cid], 0, sizeof(struct auth_client)); } /* Send a notice to a client */ @@ -195,20 +194,14 @@ void notice_client(struct auth_client *auth, const char *notice) 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; + struct auth_client *auth = rb_malloc(sizeof(struct auth_client)); long lcid = strtol(cid, NULL, 16); - char name[20]; rb_dlink_node *ptr; - if(lcid >= MAX_CLIENTS) + if(lcid >= UINT32_MAX) return; - auth = &auth_clients[lcid]; - if(auth->cid != 0) - /* Shouldn't get here */ - return; - - auth->cid = (uint16_t)lcid; + auth->cid = (uint32_t)lcid; rb_strlcpy(auth->l_ip, l_ip, sizeof(auth->l_ip)); auth->l_port = (uint16_t)atoi(l_port); /* should be safe */ @@ -216,8 +209,7 @@ static void start_auth(const char *cid, const char *l_ip, const char *l_port, co rb_strlcpy(auth->c_ip, c_ip, sizeof(auth->c_ip)); auth->c_port = (uint16_t)atoi(c_port); - snprintf(name, sizeof(name), "%d provider data", auth->cid); - auth->data = rb_dictionary_create(name, rb_uint32cmp); + rb_dictionary_add(auth_clients, RB_UINT_TO_POINTER(auth->cid), auth); RB_DLINK_FOREACH(ptr, auth_providers.head) { diff --git a/authd/provider.h b/authd/provider.h index d443c0bb..f9cb12f7 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -22,17 +22,16 @@ #define __CHARYBDIS_AUTHD_PROVIDER_H__ #include "stdinc.h" +#include "rb_dictionary.h" -/* Arbitrary limit */ -#define MAX_CLIENTS 4096 +#define MAX_PROVIDERS 32 /* This should be enough */ /* Registered providers */ typedef enum { - PROVIDER_NULL = 0x0, /* Dummy value */ - PROVIDER_RDNS = 0x1, - PROVIDER_IDENT = 0x2, - PROVIDER_BLACKLIST = 0x4, + PROVIDER_RDNS, + PROVIDER_IDENT, + PROVIDER_BLACKLIST, } provider_t; struct auth_client @@ -48,10 +47,10 @@ struct auth_client char hostname[HOSTLEN + 1]; /* Used for DNS lookup */ char username[USERLEN + 1]; /* Used for ident lookup */ - unsigned int providers; /* Providers at work, + uint32_t providers; /* Providers at work, * none left when set to 0 */ - struct Dictionary *data; /* Provider-specific data */ + void *data[MAX_PROVIDERS]; /* Provider-specific data slots */ }; typedef bool (*provider_init_t)(void); @@ -75,11 +74,11 @@ struct auth_provider }; extern rb_dlink_list auth_providers; +extern struct Dictionary *auth_clients; + extern struct auth_provider rdns_provider; extern struct auth_provider ident_provider; -extern struct auth_client auth_clients[MAX_CLIENTS]; - void load_provider(struct auth_provider *provider); void unload_provider(struct auth_provider *provider); @@ -98,19 +97,19 @@ void handle_new_connection(int parc, char *parv[]); /* Provider is operating on this auth_client (set this if you have async work to do) */ static inline void set_provider(struct auth_client *auth, provider_t provider) { - auth->providers |= provider; + auth->providers |= (1 << provider); } /* Provider is no longer operating on this auth client (you should use provider_done) */ static inline void unset_provider(struct auth_client *auth, provider_t provider) { - auth->providers &= ~provider; + auth->providers &= ~(1 << provider); } /* Check if provider is operating on this auth client */ static inline bool is_provider(struct auth_client *auth, provider_t provider) { - return auth->providers & provider; + return auth->providers & (1 << provider); } #endif /* __CHARYBDIS_AUTHD_PROVIDER_H__ */ diff --git a/authd/providers/ident.c b/authd/providers/ident.c index d633d172..5a9376cc 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -28,9 +28,6 @@ struct ident_query { - rb_dlink_node node; - - struct auth_client *auth; /* Our client */ time_t timeout; /* Timeout interval */ rb_fde_t *F; /* Our FD */ }; @@ -54,12 +51,10 @@ static EVH timeout_ident_queries_event; static CNCB ident_connected; static PF read_ident_reply; -static void client_fail(struct ident_query *query, ident_message message); -static void client_success(struct ident_query *query); -static void cleanup_query(struct ident_query *query); +static void client_fail(struct auth_client *auth, ident_message message); +static void client_success(struct auth_client *auth); static char * get_valid_ident(char *buf); -static rb_dlink_list queries; static struct ev_entry *timeout_ev; static int ident_timeout = 5; @@ -72,18 +67,14 @@ bool ident_init(void) void ident_destroy(void) { - rb_dlink_node *ptr, *nptr; + struct auth_client *auth; + struct DictionaryIter iter; /* Nuke all ident queries */ - RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) + DICTIONARY_FOREACH(auth, &iter, auth_clients) { - struct ident_query *query = ptr->data; - - notice_client(query->auth, messages[REPORT_FAIL]); - - rb_close(query->F); - rb_free(query); - rb_dlinkDelete(ptr, &queries); + if(auth->data[PROVIDER_IDENT] != NULL) + client_fail(auth, REPORT_FAIL); } } @@ -94,12 +85,12 @@ bool ident_start(struct auth_client *auth) int family; rb_fde_t *F; - query->auth = auth; + auth->data[PROVIDER_IDENT] = query; query->timeout = rb_current_time() + ident_timeout; if((F = rb_socket(family, SOCK_STREAM, 0, "ident")) == NULL) { - client_fail(query, REPORT_FAIL); + client_fail(auth, REPORT_FAIL); return true; /* Not a fatal error */ } @@ -109,7 +100,7 @@ bool ident_start(struct auth_client *auth) if(!rb_inet_ntop_sock((struct sockaddr *)&l_addr, auth->l_ip, sizeof(l_addr)) || !rb_inet_ntop_sock((struct sockaddr *)&c_addr, auth->c_ip, sizeof(c_addr))) { - client_fail(query, REPORT_FAIL); + client_fail(auth, REPORT_FAIL); return true; } @@ -133,52 +124,32 @@ bool ident_start(struct auth_client *auth) GET_SS_LEN(&l_addr), ident_connected, query, ident_timeout); - rb_dlinkAdd(query, &query->node, &queries); - - set_provider(auth, PROVIDER_IDENT); notice_client(auth, messages[REPORT_LOOKUP]); + set_provider(auth, PROVIDER_IDENT); return true; } void ident_cancel(struct auth_client *auth) { - rb_dlink_node *ptr, *nptr; + struct ident_query *query = auth->data[PROVIDER_IDENT]; - RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) - { - struct ident_query *query = ptr->data; - - if(query->auth == auth) - { - client_fail(query, REPORT_FAIL); - - rb_close(query->F); - rb_free(query); - rb_dlinkDelete(ptr, &queries); - - return; - } - } + if(query != NULL) + client_fail(auth, REPORT_FAIL); } /* Timeout outstanding queries */ static void timeout_ident_queries_event(void *notused) { - rb_dlink_node *ptr, *nptr; + struct auth_client *auth; + struct DictionaryIter iter; - RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) + DICTIONARY_FOREACH(auth, &iter, auth_clients) { - struct ident_query *query = ptr->data; + struct ident_query *query = auth->data[PROVIDER_IDENT]; - if(query->timeout < rb_current_time()) - { - client_fail(query, REPORT_FAIL); - - rb_close(query->F); - rb_free(query); - rb_dlinkDelete(ptr, &queries); - } + if(query != NULL && query->timeout < rb_current_time()) + client_fail(auth, REPORT_FAIL); } } @@ -195,8 +166,8 @@ static void timeout_ident_queries_event(void *notused) */ static void ident_connected(rb_fde_t *F, int error, void *data) { - struct ident_query *query = data; - struct auth_client *auth = query->auth; + struct auth_client *auth = data; + struct ident_query *query = auth->data[PROVIDER_IDENT]; char authbuf[32]; int authlen; @@ -204,8 +175,7 @@ static void ident_connected(rb_fde_t *F, int error, void *data) if(error != RB_OK) { /* We had an error during connection :( */ - client_fail(query, REPORT_FAIL); - cleanup_query(query); + client_fail(auth, REPORT_FAIL); return; } @@ -215,18 +185,18 @@ static void ident_connected(rb_fde_t *F, int error, void *data) if(rb_write(query->F, authbuf, authlen) != authlen) { - client_fail(query, REPORT_FAIL); + client_fail(auth, REPORT_FAIL); return; } - read_ident_reply(query->F, query); + read_ident_reply(query->F, auth); } static void read_ident_reply(rb_fde_t *F, void *data) { - struct ident_query *query = data; - struct auth_client *auth = query->auth; + struct auth_client *auth = data; + struct ident_query *query = auth->data[PROVIDER_IDENT]; char *s = NULL; char *t = NULL; int len; @@ -268,51 +238,35 @@ read_ident_reply(rb_fde_t *F, void *data) } if(s == NULL) - client_fail(query, REPORT_FAIL); + client_fail(auth, REPORT_FAIL); else - client_success(query); - - cleanup_query(query); + client_success(auth); } -static void client_fail(struct ident_query *query, ident_message report) +static void client_fail(struct auth_client *auth, ident_message report) { - struct auth_client *auth = query->auth; + struct ident_query *query = auth->data[PROVIDER_IDENT]; - if(auth) - { - rb_strlcpy(auth->username, "*", sizeof(auth->username)); - notice_client(auth, messages[report]); - provider_done(auth, PROVIDER_IDENT); - } + rb_strlcpy(auth->username, "*", sizeof(auth->username)); + + rb_close(query->F); + rb_free(query); + auth->data[PROVIDER_IDENT] = NULL; + + notice_client(auth, messages[report]); + provider_done(auth, PROVIDER_IDENT); } -static void client_success(struct ident_query *query) +static void client_success(struct auth_client *auth) { - struct auth_client *auth = query->auth; + struct ident_query *query = auth->data[PROVIDER_IDENT]; - if(auth) - { - notice_client(auth, messages[REPORT_FOUND]); - provider_done(auth, PROVIDER_IDENT); - } -} + rb_close(query->F); + rb_free(query); + auth->data[PROVIDER_IDENT] = NULL; -static void cleanup_query(struct ident_query *query) -{ - rb_dlink_node *ptr, *nptr; - - RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) - { - struct ident_query *query_l = ptr->data; - - if(query_l == query) - { - rb_close(query->F); - rb_free(query); - rb_dlinkDelete(ptr, &queries); - } - } + notice_client(auth, messages[REPORT_FOUND]); + provider_done(auth, PROVIDER_IDENT); } /* get_valid_ident diff --git a/authd/providers/rdns.c b/authd/providers/rdns.c index 0a3c2e5e..163be796 100644 --- a/authd/providers/rdns.c +++ b/authd/providers/rdns.c @@ -29,7 +29,6 @@ struct user_query { rb_dlink_node node; - struct auth_client *auth; /* Our client */ struct dns_query *query; /* Pending DNS query */ time_t timeout; /* When the request times out */ }; @@ -51,14 +50,13 @@ typedef enum REPORT_TOOLONG, } dns_message; -static void client_fail(struct user_query *query, dns_message message); -static void client_success(struct user_query *query); +static void client_fail(struct auth_client *auth, dns_message message); +static void client_success(struct auth_client *auth); static void get_dns_answer(const char *res, bool status, query_type type, void *data); static struct ev_entry *timeout_ev; static EVH timeout_dns_queries_event; static int rdns_timeout = 30; -static rb_dlink_list queries; /* Stored here for easy timeout */ bool client_dns_init(void) @@ -69,14 +67,13 @@ bool client_dns_init(void) void client_dns_destroy(void) { - rb_dlink_node *ptr, *nptr; - struct user_query *query; + struct auth_client *auth; + struct DictionaryIter iter; - RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) + DICTIONARY_FOREACH(auth, &iter, auth_clients) { - client_fail(ptr->data, REPORT_FAIL); - rb_dlinkDelete(ptr, &queries); - rb_free(ptr); + if(auth->data[PROVIDER_RDNS] != NULL) + client_fail(auth, REPORT_FAIL); } rb_event_delete(timeout_ev); @@ -86,10 +83,11 @@ bool client_dns_start(struct auth_client *auth) { struct user_query *query = rb_malloc(sizeof(struct user_query)); - query->auth = auth; query->timeout = rb_current_time() + rdns_timeout; - query->query = lookup_hostname(auth->c_ip, get_dns_answer, query); + auth->data[PROVIDER_RDNS] = query; + + query->query = lookup_hostname(auth->c_ip, get_dns_answer, auth); notice_client(auth, messages[REPORT_LOOKUP]); set_provider(auth, PROVIDER_RDNS); @@ -98,104 +96,75 @@ bool client_dns_start(struct auth_client *auth) void client_dns_cancel(struct auth_client *auth) { - rb_dlink_node *ptr, *nptr; + struct user_query *query = auth->data[PROVIDER_RDNS]; - RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) - { - struct user_query *query = ptr->data; - - if(query->auth == auth) - { - /* Victim found */ - client_fail(query, REPORT_FAIL); - rb_dlinkDelete(ptr, &queries); - rb_free(query); - return; - } - } + if(query != NULL) + client_fail(auth, REPORT_FAIL); } static void get_dns_answer(const char *res, bool status, query_type type, void *data) { - struct user_query *query = data; - struct auth_client *auth = query->auth; - bool fail = false; - dns_message response; - rb_dlink_node *ptr, *nptr; + struct auth_client *auth = data; + struct user_query *query = auth->data[PROVIDER_RDNS]; - if(res == NULL || status == false) - { - response = REPORT_FAIL; - fail = true; - goto cleanup; - } + if(query == NULL || res == NULL || status == false) + client_fail(auth, REPORT_FAIL); else if(strlen(res) > HOSTLEN) + client_fail(auth, REPORT_TOOLONG); + else { - /* Ah well. */ - response = REPORT_TOOLONG; - fail = true; - goto cleanup; - } - - rb_strlcpy(auth->hostname, res, HOSTLEN + 1); - -cleanup: - /* Clean us up off the pending queries list */ - RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) - { - struct user_query *query_l = ptr->data; - - if(query == query_l) - { - /* Found */ - if(fail) - client_fail(query, response); - else - client_success(query); - - rb_dlinkDelete(ptr, &queries); - rb_free(query); - return; - } + rb_strlcpy(auth->hostname, res, HOSTLEN + 1); + client_success(auth); } } /* Timeout outstanding queries */ static void timeout_dns_queries_event(void *notused) { - rb_dlink_node *ptr, *nptr; + struct auth_client *auth; + struct DictionaryIter iter; - RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head) + DICTIONARY_FOREACH(auth, &iter, auth_clients) { - struct user_query *query = ptr->data; + struct user_query *query = auth->data[PROVIDER_RDNS]; - if(query->auth && query->timeout < rb_current_time()) + if(query != NULL && query->timeout < rb_current_time()) { - client_fail(query, REPORT_FAIL); - rb_dlinkDelete(ptr, &queries); - rb_free(query); + client_fail(auth, REPORT_FAIL); return; } } } -static void client_fail(struct user_query *query, dns_message report) +static void client_fail(struct auth_client *auth, dns_message report) { - struct auth_client *auth = query->auth; + struct user_query *query = auth->data[PROVIDER_RDNS]; + + if(query == NULL) + return; rb_strlcpy(auth->hostname, "*", sizeof(auth->hostname)); + notice_client(auth, messages[report]); cancel_query(query->query); + + rb_free(query); + auth->data[PROVIDER_RDNS] = NULL; + provider_done(auth, PROVIDER_RDNS); } -static void client_success(struct user_query *query) +static void client_success(struct auth_client *auth) { - struct auth_client *auth = query->auth; + struct user_query *query = auth->data[PROVIDER_RDNS]; notice_client(auth, messages[REPORT_FOUND]); cancel_query(query->query); + + rb_free(query); + auth->data[PROVIDER_RDNS] = NULL; + provider_done(auth, PROVIDER_RDNS); } From aba29d5a19d0b3aa8448e35c8b20472c383ef11c Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Wed, 23 Mar 2016 09:03:37 -0500 Subject: [PATCH 32/96] authd/provider: incorporate new changes --- authd/provider.c | 4 ++-- authd/providers/ident.c | 4 ++-- authd/providers/rdns.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index ecbb45c5..8888d28a 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -50,7 +50,7 @@ rb_dlink_list auth_providers; /* Clients waiting */ -struct Dictionary *auth_clients; +rb_dictionary *auth_clients; /* Load a provider */ void load_provider(struct auth_provider *provider) @@ -81,7 +81,7 @@ void init_providers(void) void destroy_providers(void) { rb_dlink_node *ptr; - struct DictionaryIter iter; + rb_dictionary_iter iter; struct auth_client *auth; struct auth_provider *provider; diff --git a/authd/providers/ident.c b/authd/providers/ident.c index 5a9376cc..22ede8c9 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -68,7 +68,7 @@ bool ident_init(void) void ident_destroy(void) { struct auth_client *auth; - struct DictionaryIter iter; + rb_dictionary_iter iter; /* Nuke all ident queries */ DICTIONARY_FOREACH(auth, &iter, auth_clients) @@ -142,7 +142,7 @@ void ident_cancel(struct auth_client *auth) static void timeout_ident_queries_event(void *notused) { struct auth_client *auth; - struct DictionaryIter iter; + rb_dictionary_iter iter; DICTIONARY_FOREACH(auth, &iter, auth_clients) { diff --git a/authd/providers/rdns.c b/authd/providers/rdns.c index 163be796..6d0d7dfe 100644 --- a/authd/providers/rdns.c +++ b/authd/providers/rdns.c @@ -68,7 +68,7 @@ bool client_dns_init(void) void client_dns_destroy(void) { struct auth_client *auth; - struct DictionaryIter iter; + rb_dictionary_iter iter; DICTIONARY_FOREACH(auth, &iter, auth_clients) { @@ -123,7 +123,7 @@ get_dns_answer(const char *res, bool status, query_type type, void *data) static void timeout_dns_queries_event(void *notused) { struct auth_client *auth; - struct DictionaryIter iter; + rb_dictionary_iter iter; DICTIONARY_FOREACH(auth, &iter, auth_clients) { From fa1b3a733ad88266773fe5fe3974f5ffb89ef066 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Wed, 23 Mar 2016 09:11:20 -0500 Subject: [PATCH 33/96] common: don't even attempt to define NULL. stddef.h includes it, ISO C mandates NULL be in it, and if any platforms don't have it, *tough shit*. --- include/common.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/common.h b/include/common.h index 7754007e..676b6b9c 100644 --- a/include/common.h +++ b/include/common.h @@ -25,12 +25,6 @@ #ifndef INCLUDED_common_h #define INCLUDED_common_h - -#ifndef NULL -#define NULL 0 -#endif - - /* Just blindly define our own MIN/MAX macro */ #define IRCD_MAX(a, b) ((a) > (b) ? (a) : (b)) From a52c7a8e693a11cbfd02c94e2ea0676b04d09343 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Wed, 23 Mar 2016 09:15:18 -0500 Subject: [PATCH 34/96] authd/provider: really fix things for new changes. --- authd/provider.c | 2 +- authd/provider.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index 8888d28a..31ef7816 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -86,7 +86,7 @@ void destroy_providers(void) struct auth_provider *provider; /* Cancel outstanding connections */ - DICTIONARY_FOREACH(auth, &iter, auth_clients) + RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) { /* TBD - is this the right thing? */ reject_client(auth, 0, "Authentication system is down... try reconnecting in a few seconds"); diff --git a/authd/provider.h b/authd/provider.h index f9cb12f7..a3326cc5 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -74,7 +74,7 @@ struct auth_provider }; extern rb_dlink_list auth_providers; -extern struct Dictionary *auth_clients; +extern rb_dictionary *auth_clients; extern struct auth_provider rdns_provider; extern struct auth_provider ident_provider; From 757bab823c5b37d1a4dd344a59c10d3a1ceb3885 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Wed, 23 Mar 2016 12:04:02 -0500 Subject: [PATCH 35/96] misc solaris fixes --- librb/src/openssl.c | 7 ++++--- librb/src/ports.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/librb/src/openssl.c b/librb/src/openssl.c index 9898bf80..eea76c6f 100644 --- a/librb/src/openssl.c +++ b/librb/src/openssl.c @@ -359,9 +359,10 @@ rb_init_ssl(void) SSL_CTX_set_session_cache_mode(ssl_server_ctx, SSL_SESS_CACHE_OFF); SSL_CTX_set_cipher_list(ssl_server_ctx, librb_ciphers); - /* Set ECDHE on OpenSSL 1.00+, but make sure it's actually available because redhat are dicks - and bastardise their OpenSSL for stupid reasons... */ - #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && defined(NID_secp384r1) + /* Set ECDHE on OpenSSL 1.00+, but make sure it's actually available + * (it's not by default on Solaris or Red Hat... fuck Red Hat and Oracle) + */ + #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && !defined(OPENSSL_NO_ECDH) EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1); if (key) { SSL_CTX_set_tmp_ecdh(ssl_server_ctx, key); diff --git a/librb/src/ports.c b/librb/src/ports.c index af025718..bc2d85b6 100644 --- a/librb/src/ports.c +++ b/librb/src/ports.c @@ -123,7 +123,7 @@ rb_setselect_ports(rb_fde_t *F, unsigned int type, PF * handler, void *client_da int rb_select_ports(long delay) { - int i, fd; + int i; unsigned int nget = 1; struct timespec poll_time; struct timespec *p = NULL; From ab33d608de2257a8984e86f3813d734becdb3d88 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Wed, 23 Mar 2016 14:29:27 -0500 Subject: [PATCH 36/96] DICTIONARY_FOREACH -> RB_DICTIONARY_FOREACH [ci skip] --- authd/providers/ident.c | 4 ++-- authd/providers/rdns.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/authd/providers/ident.c b/authd/providers/ident.c index 22ede8c9..0ba927c8 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -71,7 +71,7 @@ void ident_destroy(void) rb_dictionary_iter iter; /* Nuke all ident queries */ - DICTIONARY_FOREACH(auth, &iter, auth_clients) + RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) { if(auth->data[PROVIDER_IDENT] != NULL) client_fail(auth, REPORT_FAIL); @@ -144,7 +144,7 @@ static void timeout_ident_queries_event(void *notused) struct auth_client *auth; rb_dictionary_iter iter; - DICTIONARY_FOREACH(auth, &iter, auth_clients) + RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) { struct ident_query *query = auth->data[PROVIDER_IDENT]; diff --git a/authd/providers/rdns.c b/authd/providers/rdns.c index 6d0d7dfe..d1dfbdc6 100644 --- a/authd/providers/rdns.c +++ b/authd/providers/rdns.c @@ -70,7 +70,7 @@ void client_dns_destroy(void) struct auth_client *auth; rb_dictionary_iter iter; - DICTIONARY_FOREACH(auth, &iter, auth_clients) + RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) { if(auth->data[PROVIDER_RDNS] != NULL) client_fail(auth, REPORT_FAIL); @@ -125,7 +125,7 @@ static void timeout_dns_queries_event(void *notused) struct auth_client *auth; rb_dictionary_iter iter; - DICTIONARY_FOREACH(auth, &iter, auth_clients) + RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) { struct user_query *query = auth->data[PROVIDER_RDNS]; From 8ed8e5cae841e650e9528a9d5390327adbca68e7 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Wed, 23 Mar 2016 16:40:31 -0500 Subject: [PATCH 37/96] res: expose rDNS building functions This will be used by the blacklist code to avoid duplication of code. --- authd/res.c | 81 +++++++++++++++++++++++++++++++---------------------- authd/res.h | 1 + 2 files changed, 48 insertions(+), 34 deletions(-) diff --git a/authd/res.c b/authd/res.c index f9db7afd..d68e402a 100644 --- a/authd/res.c +++ b/authd/res.c @@ -465,6 +465,52 @@ static void do_query_name(struct DNSQuery *query, const char *name, struct resli query_name(request); } +/* Build an rDNS style query - if suffix is NULL, use the appropriate .arpa zone */ +void build_rdns(char *buf, size_t size, const struct rb_sockaddr_storage *addr, const char *suffix) +{ + const unsigned char *cp; + + if (GET_SS_FAMILY(addr) == AF_INET) + { + const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr; + cp = (const unsigned char *)&v4->sin_addr.s_addr; + + (void) snprintf(buf, size, "%u.%u.%u.%u.%s", + (unsigned int)(cp[3]), + (unsigned int)(cp[2]), + (unsigned int)(cp[1]), + (unsigned int)(cp[0]), + suffix == NULL ? "in-addr.arpa" : suffix); + } +#ifdef RB_IPV6 + else if (GET_SS_FAMILY(addr) == AF_INET6) + { + const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr; + cp = (const unsigned char *)&v6->sin6_addr.s6_addr; + + (void) snprintf(buf, size, + "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%s", + (unsigned int)(cp[15] & 0xf), (unsigned int)(cp[15] >> 4), + (unsigned int)(cp[14] & 0xf), (unsigned int)(cp[14] >> 4), + (unsigned int)(cp[13] & 0xf), (unsigned int)(cp[13] >> 4), + (unsigned int)(cp[12] & 0xf), (unsigned int)(cp[12] >> 4), + (unsigned int)(cp[11] & 0xf), (unsigned int)(cp[11] >> 4), + (unsigned int)(cp[10] & 0xf), (unsigned int)(cp[10] >> 4), + (unsigned int)(cp[9] & 0xf), (unsigned int)(cp[9] >> 4), + (unsigned int)(cp[8] & 0xf), (unsigned int)(cp[8] >> 4), + (unsigned int)(cp[7] & 0xf), (unsigned int)(cp[7] >> 4), + (unsigned int)(cp[6] & 0xf), (unsigned int)(cp[6] >> 4), + (unsigned int)(cp[5] & 0xf), (unsigned int)(cp[5] >> 4), + (unsigned int)(cp[4] & 0xf), (unsigned int)(cp[4] >> 4), + (unsigned int)(cp[3] & 0xf), (unsigned int)(cp[3] >> 4), + (unsigned int)(cp[2] & 0xf), (unsigned int)(cp[2] >> 4), + (unsigned int)(cp[1] & 0xf), (unsigned int)(cp[1] >> 4), + (unsigned int)(cp[0] & 0xf), (unsigned int)(cp[0] >> 4), + suffix == NULL ? "ip6.arpa" : suffix); + } +#endif +} + /* * do_query_number - Use this to do reverse IP# lookups. */ @@ -480,40 +526,7 @@ static void do_query_number(struct DNSQuery *query, const struct rb_sockaddr_sto request->name = (char *)rb_malloc(IRCD_RES_HOSTLEN + 1); } - if (GET_SS_FAMILY(addr) == AF_INET) - { - const struct sockaddr_in *v4 = (const struct sockaddr_in *)addr; - cp = (const unsigned char *)&v4->sin_addr.s_addr; - - sprintf(request->queryname, "%u.%u.%u.%u.in-addr.arpa", (unsigned int)(cp[3]), - (unsigned int)(cp[2]), (unsigned int)(cp[1]), (unsigned int)(cp[0])); - } -#ifdef RB_IPV6 - else if (GET_SS_FAMILY(addr) == AF_INET6) - { - const struct sockaddr_in6 *v6 = (const struct sockaddr_in6 *)addr; - cp = (const unsigned char *)&v6->sin6_addr.s6_addr; - - (void)sprintf(request->queryname, "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x." - "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa", - (unsigned int)(cp[15] & 0xf), (unsigned int)(cp[15] >> 4), - (unsigned int)(cp[14] & 0xf), (unsigned int)(cp[14] >> 4), - (unsigned int)(cp[13] & 0xf), (unsigned int)(cp[13] >> 4), - (unsigned int)(cp[12] & 0xf), (unsigned int)(cp[12] >> 4), - (unsigned int)(cp[11] & 0xf), (unsigned int)(cp[11] >> 4), - (unsigned int)(cp[10] & 0xf), (unsigned int)(cp[10] >> 4), - (unsigned int)(cp[9] & 0xf), (unsigned int)(cp[9] >> 4), - (unsigned int)(cp[8] & 0xf), (unsigned int)(cp[8] >> 4), - (unsigned int)(cp[7] & 0xf), (unsigned int)(cp[7] >> 4), - (unsigned int)(cp[6] & 0xf), (unsigned int)(cp[6] >> 4), - (unsigned int)(cp[5] & 0xf), (unsigned int)(cp[5] >> 4), - (unsigned int)(cp[4] & 0xf), (unsigned int)(cp[4] >> 4), - (unsigned int)(cp[3] & 0xf), (unsigned int)(cp[3] >> 4), - (unsigned int)(cp[2] & 0xf), (unsigned int)(cp[2] >> 4), - (unsigned int)(cp[1] & 0xf), (unsigned int)(cp[1] >> 4), - (unsigned int)(cp[0] & 0xf), (unsigned int)(cp[0] >> 4)); - } -#endif + build_rdns(request->queryname, IRCD_RES_HOSTLEN + 1, addr, NULL); request->type = T_PTR; query_name(request); diff --git a/authd/res.h b/authd/res.h index 5a177257..1fabe0b2 100644 --- a/authd/res.h +++ b/authd/res.h @@ -32,5 +32,6 @@ extern void init_resolver(void); extern void restart_resolver(void); extern void gethost_byname_type(const char *, struct DNSQuery *, int); extern void gethost_byaddr(const struct rb_sockaddr_storage *, struct DNSQuery *); +extern void build_rdns(char *, size_t, const struct rb_sockaddr_storage *, const char *); #endif From 1d591813c3efe619ce1990ab0aa371fd4dcc99c7 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Wed, 23 Mar 2016 17:44:56 -0500 Subject: [PATCH 38/96] providers/rdns: remove useless struct member --- authd/providers/rdns.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/authd/providers/rdns.c b/authd/providers/rdns.c index d1dfbdc6..013d6d6c 100644 --- a/authd/providers/rdns.c +++ b/authd/providers/rdns.c @@ -27,8 +27,6 @@ struct user_query { - rb_dlink_node node; - struct dns_query *query; /* Pending DNS query */ time_t timeout; /* When the request times out */ }; From 6e4bcf20ff05e2b557ee9bc40ff61328c5e7599c Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Wed, 23 Mar 2016 18:47:02 -0500 Subject: [PATCH 39/96] providers/ident: fix inet_ntop/inet_pton mixup --- authd/providers/ident.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/authd/providers/ident.c b/authd/providers/ident.c index 0ba927c8..a610cfe5 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -97,8 +97,8 @@ bool ident_start(struct auth_client *auth) query->F = F; /* Build sockaddr_storages for rb_connect_tcp below */ - if(!rb_inet_ntop_sock((struct sockaddr *)&l_addr, auth->l_ip, sizeof(l_addr)) || - !rb_inet_ntop_sock((struct sockaddr *)&c_addr, auth->c_ip, sizeof(c_addr))) + if(!rb_inet_pton_sock(auth->l_ip, (struct sockaddr *)&l_addr, sizeof(l_addr)) || + !rb_inet_pton_sock(auth->c_ip, (struct sockaddr)&c_addr, sizeof(c_addr))) { client_fail(auth, REPORT_FAIL); return true; From 9c7498d5598daa92f1726edfbf04cea8aa43ee18 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Wed, 23 Mar 2016 18:56:29 -0500 Subject: [PATCH 40/96] authd/provider: add c_addr/l_addr fields Some providers consume these directly, so it's better to have a "cached" version that's already generated. --- authd/provider.c | 16 ++++++++++++++++ authd/provider.h | 2 ++ 2 files changed, 18 insertions(+) diff --git a/authd/provider.c b/authd/provider.c index 31ef7816..016dfe12 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -205,9 +205,25 @@ static void start_auth(const char *cid, const char *l_ip, const char *l_port, co rb_strlcpy(auth->l_ip, l_ip, sizeof(auth->l_ip)); auth->l_port = (uint16_t)atoi(l_port); /* should be safe */ + (void) rb_inet_pton_sock(l_ip, (struct sockaddr *)&auth->l_addr, sizeof(auth->l_addr)); rb_strlcpy(auth->c_ip, c_ip, sizeof(auth->c_ip)); auth->c_port = (uint16_t)atoi(c_port); + (void) rb_inet_pton_sock(c_ip, (struct sockaddr *)&auth->c_addr, sizeof(auth->c_addr)); + +#ifdef RB_IPV6 + if(GET_SS_FAMILY(&auth->l_addr) == AF_INET6) + ((struct sockaddr_in6 *)&l_addr)->sin6_port = htons(auth->l_port); + else +#endif + ((struct sockaddr_in *)&l_addr)->sin_port = htons(auth->l_port); + +#ifdef RB_IPV6 + if(GET_SS_FAMILY(&auth->c_addr) == AF_INET6) + ((struct sockaddr_in6 *)&c_addr)->sin6_port = htons(auth->c_port); + else +#endif + ((struct sockaddr_in *)&c_addr)->sin_port = htons(auth->c_port); rb_dictionary_add(auth_clients, RB_UINT_TO_POINTER(auth->cid), auth); diff --git a/authd/provider.h b/authd/provider.h index a3326cc5..5fa0962b 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -40,9 +40,11 @@ struct auth_client char l_ip[HOSTIPLEN + 1]; /* Listener IP address */ uint16_t l_port; /* Listener port */ + struct rb_sockaddr_storage l_addr; /* Listener address/port */ char c_ip[HOSTIPLEN + 1]; /* Client IP address */ uint16_t c_port; /* Client port */ + struct rb_sockaddr_storage c_addr; /* Client address/port */ char hostname[HOSTLEN + 1]; /* Used for DNS lookup */ char username[USERLEN + 1]; /* Used for ident lookup */ From 6cd3964de7a2c90f9b9f9bde40ac7edd1179fbdf Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Wed, 23 Mar 2016 18:58:56 -0500 Subject: [PATCH 41/96] ident: use new *_addr fields --- authd/providers/ident.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/authd/providers/ident.c b/authd/providers/ident.c index a610cfe5..8c586bed 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -97,12 +97,8 @@ bool ident_start(struct auth_client *auth) query->F = F; /* Build sockaddr_storages for rb_connect_tcp below */ - if(!rb_inet_pton_sock(auth->l_ip, (struct sockaddr *)&l_addr, sizeof(l_addr)) || - !rb_inet_pton_sock(auth->c_ip, (struct sockaddr)&c_addr, sizeof(c_addr))) - { - client_fail(auth, REPORT_FAIL); - return true; - } + memcpy(&l_addr, auth->l_addr, sizeof(l_addr)); + memcpy(&c_addr, auth->c_addr, sizeof(c_addr)); /* Set the ports correctly */ #ifdef RB_IPV6 From 32f8c78b55f0c8b6a0c361112ebf35e470a58432 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Wed, 23 Mar 2016 19:06:33 -0500 Subject: [PATCH 42/96] stupidity fixes --- authd/provider.c | 12 ++++++------ authd/providers/ident.c | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index 016dfe12..3cd489c2 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -205,25 +205,25 @@ static void start_auth(const char *cid, const char *l_ip, const char *l_port, co rb_strlcpy(auth->l_ip, l_ip, sizeof(auth->l_ip)); auth->l_port = (uint16_t)atoi(l_port); /* should be safe */ - (void) rb_inet_pton_sock(l_ip, (struct sockaddr *)&auth->l_addr, sizeof(auth->l_addr)); + (void) rb_inet_pton_sock(l_ip, (struct sockaddr *)&auth->l_addr); rb_strlcpy(auth->c_ip, c_ip, sizeof(auth->c_ip)); auth->c_port = (uint16_t)atoi(c_port); - (void) rb_inet_pton_sock(c_ip, (struct sockaddr *)&auth->c_addr, sizeof(auth->c_addr)); + (void) rb_inet_pton_sock(c_ip, (struct sockaddr *)&auth->c_addr); #ifdef RB_IPV6 if(GET_SS_FAMILY(&auth->l_addr) == AF_INET6) - ((struct sockaddr_in6 *)&l_addr)->sin6_port = htons(auth->l_port); + ((struct sockaddr_in6 *)&auth->l_addr)->sin6_port = htons(auth->l_port); else #endif - ((struct sockaddr_in *)&l_addr)->sin_port = htons(auth->l_port); + ((struct sockaddr_in *)&auth->l_addr)->sin_port = htons(auth->l_port); #ifdef RB_IPV6 if(GET_SS_FAMILY(&auth->c_addr) == AF_INET6) - ((struct sockaddr_in6 *)&c_addr)->sin6_port = htons(auth->c_port); + ((struct sockaddr_in6 *)&auth->c_addr)->sin6_port = htons(auth->c_port); else #endif - ((struct sockaddr_in *)&c_addr)->sin_port = htons(auth->c_port); + ((struct sockaddr_in *)&auth->c_addr)->sin_port = htons(auth->c_port); rb_dictionary_add(auth_clients, RB_UINT_TO_POINTER(auth->cid), auth); diff --git a/authd/providers/ident.c b/authd/providers/ident.c index 8c586bed..3e77025f 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -97,8 +97,8 @@ bool ident_start(struct auth_client *auth) query->F = F; /* Build sockaddr_storages for rb_connect_tcp below */ - memcpy(&l_addr, auth->l_addr, sizeof(l_addr)); - memcpy(&c_addr, auth->c_addr, sizeof(c_addr)); + memcpy(&l_addr, &auth->l_addr, sizeof(l_addr)); + memcpy(&c_addr, &auth->c_addr, sizeof(c_addr)); /* Set the ports correctly */ #ifdef RB_IPV6 From 410fcc233fd5ae0b8c58a1de845796bfb13cfd31 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Wed, 23 Mar 2016 21:59:48 -0500 Subject: [PATCH 43/96] authd/rdns: rename a function --- authd/providers/rdns.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/authd/providers/rdns.c b/authd/providers/rdns.c index 013d6d6c..ff3768d3 100644 --- a/authd/providers/rdns.c +++ b/authd/providers/rdns.c @@ -50,7 +50,7 @@ typedef enum static void client_fail(struct auth_client *auth, dns_message message); static void client_success(struct auth_client *auth); -static void get_dns_answer(const char *res, bool status, query_type type, void *data); +static void dns_answer_callback(const char *res, bool status, query_type type, void *data); static struct ev_entry *timeout_ev; static EVH timeout_dns_queries_event; @@ -85,7 +85,7 @@ bool client_dns_start(struct auth_client *auth) auth->data[PROVIDER_RDNS] = query; - query->query = lookup_hostname(auth->c_ip, get_dns_answer, auth); + query->query = lookup_hostname(auth->c_ip, dns_answer_callback, auth); notice_client(auth, messages[REPORT_LOOKUP]); set_provider(auth, PROVIDER_RDNS); @@ -101,7 +101,7 @@ void client_dns_cancel(struct auth_client *auth) } static void -get_dns_answer(const char *res, bool status, query_type type, void *data) +dns_answer_callback(const char *res, bool status, query_type type, void *data) { struct auth_client *auth = data; struct user_query *query = auth->data[PROVIDER_RDNS]; From 89d22b9af5597800fa9cb711f42daecfb6800029 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 24 Mar 2016 19:23:49 -0500 Subject: [PATCH 44/96] authd/provider: cleanups --- authd/provider.c | 35 +++++++++++++++++++++++++++++------ authd/provider.h | 12 +++++++----- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index 3cd489c2..d227bed3 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -18,14 +18,14 @@ * POSSIBILITY OF SUCH DAMAGE. */ -/* So the basic design here is to have "authentication providers" that do - * things like query ident and blacklists and even open proxies. +/* The basic design here is to have "authentication providers" that do things + * like query ident and blacklists and even open proxies. * * Providers are registered in the auth_providers linked list. It is planned to * use a bitmap to store provider ID's later. * - * Providers can either return failure immediately, immediate acceptance, or - * do work in the background (calling set_provider to signal this). + * Providers can either return failure immediately, immediate acceptance, or do + * work in the background (calling set_provider to signal this). * * Provider-specific data for each client can be kept in an index of the data * struct member (using the provider's ID). @@ -40,6 +40,9 @@ * should call provider_done. Do NOT call this if you have accepted or rejected * the client. * + * Eventually, stuff like *:line handling will be moved here, but that means we + * have to talk to bandb directly first. + * * --Elizafox, 9 March 2016 */ @@ -185,9 +188,29 @@ void accept_client(struct auth_client *auth, provider_t id) } /* Send a notice to a client */ -void notice_client(struct auth_client *auth, const char *notice) +void notice_client(struct auth_client *auth, const char *fmt, ...) { - rb_helper_write(authd_helper, "N %x :%s", auth->cid, notice); + char buf[BUFSIZE]; + va_list args; + + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + rb_helper_write(authd_helper, "N %x :%s", auth->cid, buf); +} + +/* Send a warning to the IRC daemon for logging, etc. */ +void warn_opers(provider_t id, const char *fmt, ...) +{ + char buf[BUFSIZE]; + va_list args; + + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + rb_helper_write(authd_helper, "W %c :%s", id, buf); } /* Begin authenticating user */ diff --git a/authd/provider.h b/authd/provider.h index 5fa0962b..84d62318 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -56,11 +56,12 @@ struct auth_client }; typedef bool (*provider_init_t)(void); -typedef bool (*provider_perform_t)(struct auth_client *); -typedef void (*provider_complete_t)(struct auth_client *, provider_t provider); -typedef void (*provider_cancel_t)(struct auth_client *); typedef void (*provider_destroy_t)(void); +typedef bool (*provider_start_t)(struct auth_client *); +typedef void (*provider_cancel_t)(struct auth_client *); +typedef void (*provider_complete_t)(struct auth_client *, provider_t provider); + struct auth_provider { rb_dlink_node node; @@ -70,7 +71,7 @@ struct auth_provider provider_init_t init; /* Initalise the provider */ provider_destroy_t destroy; /* Terminate the provider */ - provider_perform_t start; /* Perform authentication */ + provider_start_t start; /* Perform authentication */ provider_cancel_t cancel; /* Authentication cancelled */ provider_complete_t completed; /* Callback for when other performers complete (think dependency chains) */ }; @@ -92,7 +93,8 @@ void provider_done(struct auth_client *auth, provider_t id); void accept_client(struct auth_client *auth, provider_t id); void reject_client(struct auth_client *auth, provider_t id, const char *reason); -void notice_client(struct auth_client *auth, const char *notice); +void notice_client(struct auth_client *auth, const char *fmt, ...); +void warn_opers(provider_t id, const char *fmt, ...); void handle_new_connection(int parc, char *parv[]); From b2ede1aa71ccb604cde0ba38b2951ea72a99db11 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Thu, 24 Mar 2016 19:36:41 -0500 Subject: [PATCH 45/96] actually use warn_opers function --- authd/authd.c | 8 ++++++-- authd/provider.c | 11 ++++++++--- authd/provider.h | 10 +++++++++- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/authd/authd.c b/authd/authd.c index 335f55f5..e1145184 100644 --- a/authd/authd.c +++ b/authd/authd.c @@ -49,8 +49,10 @@ handle_stat(int parc, char *parv[]) authd_stat_handler handler; if(parc < 3) - /* XXX Should log this somehow */ + { + warn_opers(L_CRIT, "BUG: handle_stat received too few parameters (at least 3 expected, got %d)", parc); return; + } if (!(handler = authd_stat_handlers[(unsigned char)parv[2][0]])) return; @@ -64,8 +66,10 @@ handle_reload(int parc, char *parv[]) authd_reload_handler handler; if(parc < 2) - /* XXX Should log this somehow */ + { + warn_opers(L_CRIT, "BUG: handle_reload received too few parameters (at least 2 expected, got %d)", parc); return; + } if (!(handler = authd_reload_handlers[(unsigned char)parv[1][0]])) return; diff --git a/authd/provider.c b/authd/provider.c index d227bed3..f0000b1b 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -59,8 +59,10 @@ rb_dictionary *auth_clients; void load_provider(struct auth_provider *provider) { if(rb_dlink_list_length(&auth_providers) >= MAX_PROVIDERS) - /* XXX should probably warn here */ + { + warn_opers(L_CRIT, "Exceeded maximum level of authd providers (%d max)", MAX_PROVIDERS); return; + } provider->init(); rb_dlinkAdd(provider, &provider->node, &auth_providers); @@ -201,7 +203,7 @@ void notice_client(struct auth_client *auth, const char *fmt, ...) } /* Send a warning to the IRC daemon for logging, etc. */ -void warn_opers(provider_t id, const char *fmt, ...) +void warn_opers(notice_level_t level, const char *fmt, ...) { char buf[BUFSIZE]; va_list args; @@ -210,7 +212,7 @@ void warn_opers(provider_t id, const char *fmt, ...) vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); - rb_helper_write(authd_helper, "W %c :%s", id, buf); + rb_helper_write(authd_helper, "W %c :%s", level, buf); } /* Begin authenticating user */ @@ -272,7 +274,10 @@ static void start_auth(const char *cid, const char *l_ip, const char *l_port, co void handle_new_connection(int parc, char *parv[]) { if(parc < 7) + { + warn_opers(L_CRIT, "BUG: received too few params for new connection (7 expected, got %d)", parc); return; + } start_auth(parv[1], parv[2], parv[3], parv[4], parv[5]); } diff --git a/authd/provider.h b/authd/provider.h index 84d62318..9184e2fc 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -34,6 +34,14 @@ typedef enum PROVIDER_BLACKLIST, } provider_t; +typedef enum +{ + L_DEBUG = 'D', + L_INFO = 'I', + L_WARN = 'W', + L_CRIT ='C', +} notice_level_t; + struct auth_client { uint16_t cid; /* Client ID */ @@ -94,7 +102,7 @@ void accept_client(struct auth_client *auth, provider_t id); void reject_client(struct auth_client *auth, provider_t id, const char *reason); void notice_client(struct auth_client *auth, const char *fmt, ...); -void warn_opers(provider_t id, const char *fmt, ...); +void warn_opers(notice_level_t level, const char *fmt, ...); void handle_new_connection(int parc, char *parv[]); From 14505c84009cf3f0347309a8dd7e58bbee810ed4 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Fri, 25 Mar 2016 19:47:54 -0500 Subject: [PATCH 46/96] rdns: adjust timeout values --- authd/providers/rdns.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/authd/providers/rdns.c b/authd/providers/rdns.c index ff3768d3..96bcea14 100644 --- a/authd/providers/rdns.c +++ b/authd/providers/rdns.c @@ -54,12 +54,12 @@ static void dns_answer_callback(const char *res, bool status, query_type type, v static struct ev_entry *timeout_ev; static EVH timeout_dns_queries_event; -static int rdns_timeout = 30; +static int rdns_timeout = 15; bool client_dns_init(void) { - timeout_ev = rb_event_addish("timeout_dns_queries_event", timeout_dns_queries_event, NULL, 5); + timeout_ev = rb_event_addish("timeout_dns_queries_event", timeout_dns_queries_event, NULL, 1); return (timeout_ev != NULL); } From add80afdcb888e8bcdb9ed006a01f996613840e5 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Fri, 25 Mar 2016 20:07:36 -0500 Subject: [PATCH 47/96] authd/provider: add blacklist provider. This took way longer than it should have. --- authd/Makefile.am | 5 +- authd/provider.h | 1 + authd/providers/blacklist.c | 404 ++++++++++++++++++++++++++++++++++++ 3 files changed, 408 insertions(+), 2 deletions(-) create mode 100644 authd/providers/blacklist.c diff --git a/authd/Makefile.am b/authd/Makefile.am index d17e97d1..235061c4 100644 --- a/authd/Makefile.am +++ b/authd/Makefile.am @@ -11,7 +11,8 @@ authd_SOURCES = \ getaddrinfo.c \ getnameinfo.c \ provider.c \ - providers/rdns.c \ - providers/ident.c + providers/blacklist.c \ + providers/ident.c \ + providers/rdns.c authd_LDADD = ../librb/src/librb.la diff --git a/authd/provider.h b/authd/provider.h index 9184e2fc..01c71cf4 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -89,6 +89,7 @@ extern rb_dictionary *auth_clients; extern struct auth_provider rdns_provider; extern struct auth_provider ident_provider; +extern struct auth_provider blacklist_provider; void load_provider(struct auth_provider *provider); void unload_provider(struct auth_provider *provider); diff --git a/authd/providers/blacklist.c b/authd/providers/blacklist.c new file mode 100644 index 00000000..eaccc33b --- /dev/null +++ b/authd/providers/blacklist.c @@ -0,0 +1,404 @@ +/* + * charybdis: A slightly useful ircd. + * blacklist.c: Manages DNS blacklist entries and lookups + * + * Copyright (C) 2006-2011 charybdis development team + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Originally written for charybdis circa 2006 (by nenolod?). + * Tweaked for authd. Some functions and structs renamed. Public/private + * interfaces have been shifted around. Some code has been cleaned up too. + * -- Elizafox 24 March 2016 + */ + +#include "authd.h" +#include "provider.h" +#include "stdinc.h" +#include "dns.h" + +typedef enum filter_t +{ + FILTER_ALL = 1, + FILTER_LAST = 2, +} filter_t; + +/* Blacklist accepted IP types */ +#define IPTYPE_IPV4 1 +#define IPTYPE_IPV6 2 + +/* A configured DNSBL */ +struct blacklist +{ + char host[IRCD_RES_HOSTLEN + 1]; + char reason[BUFSIZE]; /* Reason template (ircd fills in the blanks) */ + unsigned char iptype; /* IP types supported */ + rb_dlink_list filters; /* Filters for queries */ + + bool delete; /* If true delete when no clients */ + int refcount; /* When 0 and delete is set, remove this blacklist */ + + time_t lastwarning; /* Last warning about garbage replies sent */ +}; + +/* A lookup in progress for a particular DNSBL for a particular client */ +struct blacklist_lookup +{ + struct blacklist *bl; /* Blacklist we're checking */ + struct auth_client *auth; /* Client */ + struct dns_query *query; /* DNS query pointer */ + + rb_dlink_node node; +}; + +/* A blacklist filter */ +struct blacklist_filter +{ + filter_t type; /* Type of filter */ + char filterstr[HOSTIPLEN]; /* The filter itself */ + + rb_dlink_node node; +}; + +/* Blacklist user data attached to auth_client instance */ +struct blacklist_user +{ + rb_dlink_list queries; /* Blacklist queries in flight */ + time_t timeout; /* When this times out */ +}; + +/* public interfaces */ +static bool blacklists_init(void); +static void blacklists_destroy(void); + +static bool blacklists_start(struct auth_client *); +static void blacklists_cancel(struct auth_client *); + +/* private interfaces */ +static void unref_blacklist(struct blacklist *); +static struct blacklist *new_blacklist(char *, char *, bool, bool, rb_dlink_list *); +static struct blacklist *find_blacklist(char *); +static bool blacklist_check_reply(struct blacklist_lookup *, const char *); +static void blacklist_dns_callback(const char *, bool, query_type, void *); +static void initiate_blacklist_dnsquery(struct blacklist *, struct auth_client *); +static void timeout_blacklist_queries_event(void *); + +/* Variables */ +static rb_dlink_list blacklist_list = { NULL, NULL, 0 }; +static struct ev_entry *timeout_ev; +static EVH timeout_blacklists; +static int blacklist_timeout = 15; + +/* private interfaces */ + +static void +unref_blacklist(struct blacklist *bl) +{ + rb_dlink_node *ptr, *nptr; + + bl->refcount--; + if (bl->delete && bl->refcount <= 0) + { + RB_DLINK_FOREACH_SAFE(ptr, nptr, bl->filters.head) + { + rb_dlinkDelete(ptr, &bl->filters); + rb_free(ptr); + } + + rb_dlinkFindDestroy(bl, &blacklist_list); + rb_free(bl); + } +} + +static struct blacklist * +new_blacklist(char *name, char *reason, bool ipv4, bool ipv6, rb_dlink_list *filters) +{ + struct blacklist *bl; + + if (name == NULL || reason == NULL || !(ipv4 || ipv6)) + return NULL; + + if((bl = find_blacklist(name)) == NULL) + { + bl = rb_malloc(sizeof(struct blacklist)); + rb_dlinkAddAlloc(bl, &blacklist_list); + } + else + bl->delete = false; + + rb_strlcpy(bl->host, name, IRCD_RES_HOSTLEN + 1); + rb_strlcpy(bl->reason, reason, BUFSIZE); + if(ipv4) + bl->iptype |= IPTYPE_IPV4; + if(ipv6) + bl->iptype |= IPTYPE_IPV6; + + rb_dlinkMoveList(filters, &bl->filters); + + bl->lastwarning = 0; + + return bl; +} + +static struct blacklist * +find_blacklist(char *name) +{ + rb_dlink_node *ptr; + + RB_DLINK_FOREACH(ptr, blacklist_list.head) + { + struct blacklist *bl = (struct blacklist *)ptr->data; + + if (!strcasecmp(bl->host, name)) + return bl; + } + + return NULL; +} + +static inline bool +blacklist_check_reply(struct blacklist_lookup *bllookup, const char *ipaddr) +{ + struct blacklist *bl = bllookup->bl; + const char *lastoctet; + rb_dlink_node *ptr; + + /* No filters and entry found - thus positive match */ + if (!rb_dlink_list_length(&bl->filters)) + return true; + + /* Below will prolly have to change if IPv6 address replies are sent back */ + if ((lastoctet = strrchr(ipaddr, '.')) == NULL || *(++lastoctet) == '\0') + goto blwarn; + + RB_DLINK_FOREACH(ptr, bl->filters.head) + { + struct blacklist_filter *filter = ptr->data; + const char *cmpstr; + + if (filter->type == FILTER_ALL) + cmpstr = ipaddr; + else if (filter->type == FILTER_LAST) + cmpstr = lastoctet; + else + { + warn_opers(L_CRIT, "BUG: Unknown blacklist filter type on blacklist %s: %d", + bl->host, filter->type); + continue; + } + + if (strcmp(cmpstr, filter->filterstr) == 0) + /* Match! */ + return true; + } + + return false; +blwarn: + if (bl->lastwarning + 3600 < rb_current_time()) + { + warn_opers(L_WARN, "Garbage/undecipherable reply received from blacklist %s (reply %s)", + bl->host, ipaddr); + bl->lastwarning = rb_current_time(); + } + return false; +} + +static void +blacklist_dns_callback(const char *result, bool status, query_type type, void *data) +{ + struct blacklist_lookup *bllookup = (struct blacklist_lookup *)data; + struct blacklist_user *bluser; + struct auth_client *auth; + + if (bllookup == NULL || bllookup->auth == NULL) + return; + + auth = bllookup->auth; + bluser = auth->data[PROVIDER_BLACKLIST]; + if(bluser == NULL) + return; + + if (result != NULL && status && blacklist_check_reply(bllookup, result)) + { + /* Match found, so proceed no further */ + blacklists_cancel(auth); + reject_client(auth, PROVIDER_BLACKLIST, bllookup->bl->reason); + return; + } + + unref_blacklist(bllookup->bl); + rb_dlinkDelete(&bllookup->node, &bluser->queries); + rb_free(bllookup); + + if(!rb_dlink_list_length(&bluser->queries)) + { + /* Done here */ + provider_done(auth, PROVIDER_BLACKLIST); + rb_free(bluser); + auth->data[PROVIDER_BLACKLIST] = NULL; + } +} + +static void +initiate_blacklist_dnsquery(struct blacklist *bl, struct auth_client *auth) +{ + struct blacklist_lookup *bllookup = rb_malloc(sizeof(struct blacklist_lookup)); + struct blacklist_user *bluser = auth->data[PROVIDER_BLACKLIST]; + char buf[IRCD_RES_HOSTLEN + 1]; + int aftype; + + bllookup->bl = bl; + bllookup->auth = auth; + + aftype = GET_SS_FAMILY(&auth->c_addr); + if((aftype == AF_INET && (bl->iptype & IPTYPE_IPV4) == 0) || + (aftype == AF_INET6 && (bl->iptype & IPTYPE_IPV6) == 0)) + /* Incorrect blacklist type for this IP... */ + return; + + build_rdns(buf, sizeof(buf), &auth->c_addr, bl->host); + + bllookup->query = lookup_ip(buf, AF_INET, blacklist_dns_callback, bllookup); + + rb_dlinkAdd(bllookup, &bllookup->node, &bluser->queries); + bl->refcount++; +} + +/* Timeout outstanding queries */ +static void +timeout_blacklist_queries_event(void *notused) +{ + struct auth_client *auth; + rb_dictionary_iter iter; + + RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) + { + struct blacklist_user *bluser = auth->data[PROVIDER_BLACKLIST]; + + if(bluser != NULL && bluser->timeout < rb_current_time()) + { + blacklists_cancel(auth); + provider_done(auth, PROVIDER_BLACKLIST); + } + } +} + +/* public interfaces */ +static bool +blacklists_start(struct auth_client *auth) +{ + struct blacklist_user *bluser; + rb_dlink_node *nptr; + + if(auth->data[PROVIDER_BLACKLIST] != NULL) + return true; + + if(!rb_dlink_list_length(&blacklist_list)) + /* Nothing to do... */ + return true; + + bluser = auth->data[PROVIDER_BLACKLIST] = rb_malloc(sizeof(struct blacklist_user)); + + RB_DLINK_FOREACH(nptr, blacklist_list.head) + { + struct blacklist *bl = (struct blacklist *) nptr->data; + + if (!bl->delete) + initiate_blacklist_dnsquery(bl, auth); + } + + bluser->timeout = rb_current_time() + blacklist_timeout; + + set_provider(auth, PROVIDER_BLACKLIST); + return true; +} + +static void +blacklists_cancel(struct auth_client *auth) +{ + rb_dlink_node *ptr, *nptr; + struct blacklist_user *bluser = auth->data[PROVIDER_BLACKLIST]; + + if(bluser == NULL) + return; + + RB_DLINK_FOREACH_SAFE(ptr, nptr, bluser->queries.head) + { + struct blacklist_lookup *bllookup = ptr->data; + rb_dlinkDelete(&bllookup->node, &bluser->queries); + unref_blacklist(bllookup->bl); + cancel_query(bllookup->query); + rb_free(bllookup); + } + + rb_free(bluser); + auth->data[PROVIDER_BLACKLIST] = NULL; +} + +static bool +blacklists_init(void) +{ + timeout_ev = rb_event_addish("timeout_blacklist_queries_event", timeout_blacklist_queries_event, NULL, 1); + return (timeout_ev != NULL); +} + +static void +blacklists_destroy(void) +{ + rb_dlink_node *ptr, *nptr; + rb_dictionary_iter iter; + struct blacklist *bl; + struct auth_client *auth; + + RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) + { + blacklists_cancel(auth); + } + + RB_DLINK_FOREACH_SAFE(ptr, nptr, blacklist_list.head) + { + bl = ptr->data; + if (bl->refcount > 0) + bl->delete = true; + else + { + rb_free(ptr->data); + rb_dlinkDestroy(ptr, &blacklist_list); + } + } +} + +struct auth_provider blacklist_provider = +{ + .id = PROVIDER_BLACKLIST, + .init = blacklists_init, + .destroy = blacklists_destroy, + .start = blacklists_start, + .cancel = blacklists_cancel, + .completed = NULL, +}; From a7d5aea119599580803bf3e7a515bda730b447dc Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Fri, 25 Mar 2016 20:46:58 -0500 Subject: [PATCH 48/96] provider: make blacklist queries come after ident/rdns. --- authd/provider.c | 11 ++++---- authd/provider.h | 18 ++++++++++-- authd/providers/blacklist.c | 56 ++++++++++++++++++++++++++----------- authd/providers/ident.c | 2 +- authd/providers/rdns.c | 2 +- 5 files changed, 63 insertions(+), 26 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index f0000b1b..e7b07c50 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -116,7 +116,7 @@ void cancel_providers(struct auth_client *auth) { provider = ptr->data; - if(provider->cancel && is_provider(auth, provider->id)) + if(provider->cancel && is_provider_on(auth, provider->id)) /* Cancel if required */ provider->cancel(auth); } @@ -131,7 +131,8 @@ void provider_done(struct auth_client *auth, provider_t id) rb_dlink_node *ptr; struct auth_provider *provider; - unset_provider(auth, id); + set_provider_off(auth, id); + set_provider_done(auth, id); if(!auth->providers) { @@ -144,7 +145,7 @@ void provider_done(struct auth_client *auth, provider_t id) { provider = ptr->data; - if(provider->completed && is_provider(auth, provider->id)) + if(provider->completed && is_provider_on(auth, provider->id)) /* Notify pending clients who asked for it */ provider->completed(auth, id); } @@ -174,7 +175,7 @@ void reject_client(struct auth_client *auth, provider_t id, const char *reason) /* TODO send back ident */ rb_helper_write(authd_helper, "R %x %c :%s", auth->cid, reject, reason); - unset_provider(auth, id); + set_provider_off(auth, id); cancel_providers(auth); } @@ -185,7 +186,7 @@ void accept_client(struct auth_client *auth, provider_t id) rb_helper_write(authd_helper, "A %x %s %s", auth->cid, auth->username, auth->hostname); - unset_provider(auth, id); + set_provider_off(auth, id); cancel_providers(auth); } diff --git a/authd/provider.h b/authd/provider.h index 01c71cf4..ef96ca84 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -59,6 +59,7 @@ struct auth_client uint32_t providers; /* Providers at work, * none left when set to 0 */ + uint32_t providers_done; /* Providers completed */ void *data[MAX_PROVIDERS]; /* Provider-specific data slots */ }; @@ -108,21 +109,32 @@ void warn_opers(notice_level_t level, const char *fmt, ...); void handle_new_connection(int parc, char *parv[]); /* Provider is operating on this auth_client (set this if you have async work to do) */ -static inline void set_provider(struct auth_client *auth, provider_t provider) +static inline void set_provider_on(struct auth_client *auth, provider_t provider) { auth->providers |= (1 << provider); } /* Provider is no longer operating on this auth client (you should use provider_done) */ -static inline void unset_provider(struct auth_client *auth, provider_t provider) +static inline void set_provider_off(struct auth_client *auth, provider_t provider) { auth->providers &= ~(1 << provider); } +/* Set the provider to done (you should use provider_done) */ +static inline void set_provider_done(struct auth_client *auth, provider_t provider) +{ + auth->providers_done |= (1 << provider); +} + /* Check if provider is operating on this auth client */ -static inline bool is_provider(struct auth_client *auth, provider_t provider) +static inline bool is_provider_on(struct auth_client *auth, provider_t provider) { return auth->providers & (1 << provider); } +static inline bool is_provider_done(struct auth_client *auth, provider_t provider) +{ + return auth->providers_done & (1 << provider); +} + #endif /* __CHARYBDIS_AUTHD_PROVIDER_H__ */ diff --git a/authd/providers/blacklist.c b/authd/providers/blacklist.c index eaccc33b..ae52bbdc 100644 --- a/authd/providers/blacklist.c +++ b/authd/providers/blacklist.c @@ -258,7 +258,7 @@ blacklist_dns_callback(const char *result, bool status, query_type type, void *d if(!rb_dlink_list_length(&bluser->queries)) { /* Done here */ - provider_done(auth, PROVIDER_BLACKLIST); + provider_done(auth, PROVIDER_BLACKLIST); rb_free(bluser); auth->data[PROVIDER_BLACKLIST] = NULL; } @@ -308,13 +308,27 @@ timeout_blacklist_queries_event(void *notused) } } +static inline void +lookup_all_blacklists(struct auth_client *auth) +{ + struct blacklist_user *bluser = auth->data[PROVIDER_BLACKLIST]; + rb_dlink_node *ptr; + + RB_DLINK_FOREACH(ptr, blacklist_list.head) + { + struct blacklist *bl = (struct blacklist *)ptr->data; + + if (!bl->delete) + initiate_blacklist_dnsquery(bl, auth); + } + + bluser->timeout = rb_current_time() + blacklist_timeout; +} + /* public interfaces */ static bool blacklists_start(struct auth_client *auth) { - struct blacklist_user *bluser; - rb_dlink_node *nptr; - if(auth->data[PROVIDER_BLACKLIST] != NULL) return true; @@ -322,22 +336,32 @@ blacklists_start(struct auth_client *auth) /* Nothing to do... */ return true; - bluser = auth->data[PROVIDER_BLACKLIST] = rb_malloc(sizeof(struct blacklist_user)); + auth->data[PROVIDER_BLACKLIST] = rb_malloc(sizeof(struct blacklist_user)); - RB_DLINK_FOREACH(nptr, blacklist_list.head) - { - struct blacklist *bl = (struct blacklist *) nptr->data; + if(is_provider_done(auth, PROVIDER_RDNS) && is_provider_done(auth, PROVIDER_IDENT)) + /* This probably can't happen but let's handle this case anyway */ + lookup_all_blacklists(auth); - if (!bl->delete) - initiate_blacklist_dnsquery(bl, auth); - } - - bluser->timeout = rb_current_time() + blacklist_timeout; - - set_provider(auth, PROVIDER_BLACKLIST); + set_provider_on(auth, PROVIDER_BLACKLIST); return true; } +/* This is called every time a provider is completed */ +static void +blacklists_initiate(struct auth_client *auth, provider_t provider) +{ + struct blacklist_user *bluser = auth->data[PROVIDER_BLACKLIST]; + + if(bluser == NULL || is_provider_done(auth, PROVIDER_BLACKLIST) || rb_dlink_list_length(&bluser->queries)) + /* Nothing to do */ + return; + else if(!is_provider_done(auth, PROVIDER_RDNS) && !is_provider_done(auth, PROVIDER_IDENT)) + /* Don't start until we've completed these */ + return; + else + lookup_all_blacklists(auth); +} + static void blacklists_cancel(struct auth_client *auth) { @@ -400,5 +424,5 @@ struct auth_provider blacklist_provider = .destroy = blacklists_destroy, .start = blacklists_start, .cancel = blacklists_cancel, - .completed = NULL, + .completed = blacklists_initiate, }; diff --git a/authd/providers/ident.c b/authd/providers/ident.c index 3e77025f..a19b289e 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -121,7 +121,7 @@ bool ident_start(struct auth_client *auth) query, ident_timeout); notice_client(auth, messages[REPORT_LOOKUP]); - set_provider(auth, PROVIDER_IDENT); + set_provider_on(auth, PROVIDER_IDENT); return true; } diff --git a/authd/providers/rdns.c b/authd/providers/rdns.c index 96bcea14..ddce08fb 100644 --- a/authd/providers/rdns.c +++ b/authd/providers/rdns.c @@ -88,7 +88,7 @@ bool client_dns_start(struct auth_client *auth) query->query = lookup_hostname(auth->c_ip, dns_answer_callback, auth); notice_client(auth, messages[REPORT_LOOKUP]); - set_provider(auth, PROVIDER_RDNS); + set_provider_on(auth, PROVIDER_RDNS); return true; } From 6c88869f223eb49a69518a161d8785eaae08971e Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Fri, 25 Mar 2016 20:55:10 -0500 Subject: [PATCH 49/96] providers/blacklist: change some checks to asserts. These should not really happen in reality... --- authd/providers/blacklist.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/authd/providers/blacklist.c b/authd/providers/blacklist.c index ae52bbdc..22917c03 100644 --- a/authd/providers/blacklist.c +++ b/authd/providers/blacklist.c @@ -346,16 +346,20 @@ blacklists_start(struct auth_client *auth) return true; } -/* This is called every time a provider is completed */ +/* This is called every time a provider is completed as long as we are marked not done */ static void blacklists_initiate(struct auth_client *auth, provider_t provider) { struct blacklist_user *bluser = auth->data[PROVIDER_BLACKLIST]; - if(bluser == NULL || is_provider_done(auth, PROVIDER_BLACKLIST) || rb_dlink_list_length(&bluser->queries)) + lrb_assert(provider != PROVIDER_BLACKLIST); + lrb_assert(!is_provider_done(auth, PROVIDER_BLACKLIST)); + lrb_assert(rb_dlink_list_length(&blacklist_list) > 0); + + if(bluser == NULL || rb_dlink_list_length(&bluser->queries)) /* Nothing to do */ return; - else if(!is_provider_done(auth, PROVIDER_RDNS) && !is_provider_done(auth, PROVIDER_IDENT)) + else if(!(is_provider_done(auth, PROVIDER_RDNS) && is_provider_done(auth, PROVIDER_IDENT))) /* Don't start until we've completed these */ return; else From a21a82b1b6f9e16bd45b177dad569f28da685c2d Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Fri, 25 Mar 2016 21:05:39 -0500 Subject: [PATCH 50/96] Fix dangling line from merge --- authd/authd.c | 1 - 1 file changed, 1 deletion(-) diff --git a/authd/authd.c b/authd/authd.c index b4502a68..8097679b 100644 --- a/authd/authd.c +++ b/authd/authd.c @@ -29,7 +29,6 @@ static void handle_stat(int parc, char *parv[]); rb_helper *authd_helper = NULL; authd_cmd_handler authd_cmd_handlers[256] = { -<<<<<<< HEAD ['C'] = handle_new_connection, ['D'] = resolve_dns, ['R'] = handle_reload, From ee658821e34d7daa7a01ce557c0746e19b43796c Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Fri, 25 Mar 2016 21:05:52 -0500 Subject: [PATCH 51/96] reject_client: send back ident and hostname with rejection. At the moment (possibly not in the future) ircd will want to override our decision whether or not to accept a client; we need to give them enough information back to ensure they can do it properly. --- authd/provider.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/authd/provider.c b/authd/provider.c index e7b07c50..13b9a0a8 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -173,7 +173,7 @@ void reject_client(struct auth_client *auth, provider_t id, const char *reason) } /* TODO send back ident */ - rb_helper_write(authd_helper, "R %x %c :%s", auth->cid, reject, reason); + rb_helper_write(authd_helper, "R %x %c %s %s :%s", auth->cid, reject, auth->username, auth->hostname, reason); set_provider_off(auth, id); cancel_providers(auth); From 3ad21f61073225b93ce32e1af6c0caea9efc10ac Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Fri, 25 Mar 2016 21:08:46 -0500 Subject: [PATCH 52/96] authd/provider: remove obsolete comment [ci skip] --- authd/provider.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/authd/provider.c b/authd/provider.c index 13b9a0a8..4e17793e 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -172,7 +172,10 @@ void reject_client(struct auth_client *auth, provider_t id, const char *reason) break; } - /* TODO send back ident */ + /* We send back username and hostname in case ircd wants to overrule our decision. + * In the future this may not be the case. + * --Elizafox + */ rb_helper_write(authd_helper, "R %x %c %s %s :%s", auth->cid, reject, auth->username, auth->hostname, reason); set_provider_off(auth, id); From 75844b15af33acd0e7877a7ff2229835309bf949 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Fri, 25 Mar 2016 21:09:55 -0500 Subject: [PATCH 53/96] authd: fix undefined behaviour --- authd/authd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/authd/authd.c b/authd/authd.c index 8097679b..836d07a5 100644 --- a/authd/authd.c +++ b/authd/authd.c @@ -68,7 +68,7 @@ handle_reload(int parc, char *parv[]) if(parc < 2) { /* Reload all handlers */ - for(size_t i = 0; i < sizeof(authd_reload_handlers); handler = authd_reload_handlers[i++]) + for(size_t i = 0; i < 256; handler = authd_reload_handlers[i++]) handler(parv[1][0]); return; From db821ee9ba2c11b11316a1fc03002aaa68cd279d Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Fri, 25 Mar 2016 21:29:44 -0500 Subject: [PATCH 54/96] authd: split out notices stuff for backporting to master. --- authd/Makefile.am | 7 +++--- authd/authd.c | 1 + authd/notice.c | 48 +++++++++++++++++++++++++++++++++++++ authd/notice.h | 35 +++++++++++++++++++++++++++ authd/provider.c | 27 +-------------------- authd/provider.h | 11 --------- authd/providers/blacklist.c | 1 + authd/providers/ident.c | 7 +++--- authd/providers/rdns.c | 7 +++--- 9 files changed, 98 insertions(+), 46 deletions(-) create mode 100644 authd/notice.c create mode 100644 authd/notice.h diff --git a/authd/Makefile.am b/authd/Makefile.am index 235061c4..ef2c44a4 100644 --- a/authd/Makefile.am +++ b/authd/Makefile.am @@ -4,13 +4,14 @@ AM_CPPFLAGS = -I../include -I../librb/include authd_SOURCES = \ authd.c \ - res.c \ - reslib.c \ - reslist.c \ dns.c \ getaddrinfo.c \ getnameinfo.c \ + notice.c \ provider.c \ + res.c \ + reslib.c \ + reslist.c \ providers/blacklist.c \ providers/ident.c \ providers/rdns.c diff --git a/authd/authd.c b/authd/authd.c index acd5bc1e..d77d87b1 100644 --- a/authd/authd.c +++ b/authd/authd.c @@ -21,6 +21,7 @@ #include "authd.h" #include "dns.h" #include "provider.h" +#include "notice.h" #define MAXPARA 10 diff --git a/authd/notice.c b/authd/notice.c new file mode 100644 index 00000000..3e1d3f8a --- /dev/null +++ b/authd/notice.c @@ -0,0 +1,48 @@ +/* authd/notice.c - send notices back to the ircd and to clients + * Copyright (c) 2016 Elizabeth Myers + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "authd.h" +#include "notice.h" + +/* Send a notice to a client */ +void notice_client(uint32_t cid, const char *fmt, ...) +{ + char buf[BUFSIZE]; + va_list args; + + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + rb_helper_write(authd_helper, "N %x :%s", cid, buf); +} + +/* Send a warning to the IRC daemon for logging, etc. */ +void warn_opers(notice_level_t level, const char *fmt, ...) +{ + char buf[BUFSIZE]; + va_list args; + + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + rb_helper_write(authd_helper, "W %c :%s", level, buf); +} diff --git a/authd/notice.h b/authd/notice.h new file mode 100644 index 00000000..1e48bccf --- /dev/null +++ b/authd/notice.h @@ -0,0 +1,35 @@ +/* authd/notice.h - send notices back to the ircd and to clients + * Copyright (c) 2016 Elizabeth Myers + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __CHARYBDIS_AUTHD_NOTICE_H__ +#define __CHARYBDIS_AUTHD_NOTICE_H__ + +typedef enum +{ + L_DEBUG = 'D', + L_INFO = 'I', + L_WARN = 'W', + L_CRIT ='C', +} notice_level_t; + +void notice_client(uint32_t cid, const char *fmt, ...); +void warn_opers(notice_level_t level, const char *fmt, ...); + +#endif /* __CHARYBDIS_AUTHD_NOTICE_H__ */ diff --git a/authd/provider.c b/authd/provider.c index 4e17793e..1a6c6517 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -49,6 +49,7 @@ #include "rb_dictionary.h" #include "authd.h" #include "provider.h" +#include "notice.h" rb_dlink_list auth_providers; @@ -193,32 +194,6 @@ void accept_client(struct auth_client *auth, provider_t id) cancel_providers(auth); } -/* Send a notice to a client */ -void notice_client(struct auth_client *auth, const char *fmt, ...) -{ - char buf[BUFSIZE]; - va_list args; - - va_start(args, fmt); - vsnprintf(buf, sizeof(buf), fmt, args); - va_end(args); - - rb_helper_write(authd_helper, "N %x :%s", auth->cid, buf); -} - -/* Send a warning to the IRC daemon for logging, etc. */ -void warn_opers(notice_level_t level, const char *fmt, ...) -{ - char buf[BUFSIZE]; - va_list args; - - va_start(args, fmt); - vsnprintf(buf, sizeof(buf), fmt, args); - va_end(args); - - rb_helper_write(authd_helper, "W %c :%s", level, buf); -} - /* Begin authenticating user */ static void start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_ip, const char *c_port) { diff --git a/authd/provider.h b/authd/provider.h index ef96ca84..8fab21cf 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -34,14 +34,6 @@ typedef enum PROVIDER_BLACKLIST, } provider_t; -typedef enum -{ - L_DEBUG = 'D', - L_INFO = 'I', - L_WARN = 'W', - L_CRIT ='C', -} notice_level_t; - struct auth_client { uint16_t cid; /* Client ID */ @@ -103,9 +95,6 @@ void provider_done(struct auth_client *auth, provider_t id); void accept_client(struct auth_client *auth, provider_t id); void reject_client(struct auth_client *auth, provider_t id, const char *reason); -void notice_client(struct auth_client *auth, const char *fmt, ...); -void warn_opers(notice_level_t level, const char *fmt, ...); - void handle_new_connection(int parc, char *parv[]); /* Provider is operating on this auth_client (set this if you have async work to do) */ diff --git a/authd/providers/blacklist.c b/authd/providers/blacklist.c index 22917c03..df7d3974 100644 --- a/authd/providers/blacklist.c +++ b/authd/providers/blacklist.c @@ -39,6 +39,7 @@ #include "authd.h" #include "provider.h" +#include "notice.h" #include "stdinc.h" #include "dns.h" diff --git a/authd/providers/ident.c b/authd/providers/ident.c index a19b289e..2c561462 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -21,6 +21,7 @@ #include "stdinc.h" #include "match.h" #include "authd.h" +#include "notice.h" #include "provider.h" #include "res.h" @@ -120,7 +121,7 @@ bool ident_start(struct auth_client *auth) GET_SS_LEN(&l_addr), ident_connected, query, ident_timeout); - notice_client(auth, messages[REPORT_LOOKUP]); + notice_client(auth->cid, messages[REPORT_LOOKUP]); set_provider_on(auth, PROVIDER_IDENT); return true; @@ -249,7 +250,7 @@ static void client_fail(struct auth_client *auth, ident_message report) rb_free(query); auth->data[PROVIDER_IDENT] = NULL; - notice_client(auth, messages[report]); + notice_client(auth->cid, messages[report]); provider_done(auth, PROVIDER_IDENT); } @@ -261,7 +262,7 @@ static void client_success(struct auth_client *auth) rb_free(query); auth->data[PROVIDER_IDENT] = NULL; - notice_client(auth, messages[REPORT_FOUND]); + notice_client(auth->cid, messages[REPORT_FOUND]); provider_done(auth, PROVIDER_IDENT); } diff --git a/authd/providers/rdns.c b/authd/providers/rdns.c index ddce08fb..0b203740 100644 --- a/authd/providers/rdns.c +++ b/authd/providers/rdns.c @@ -22,6 +22,7 @@ #include "rb_commio.h" #include "authd.h" #include "provider.h" +#include "notice.h" #include "res.h" #include "dns.h" @@ -87,7 +88,7 @@ bool client_dns_start(struct auth_client *auth) query->query = lookup_hostname(auth->c_ip, dns_answer_callback, auth); - notice_client(auth, messages[REPORT_LOOKUP]); + notice_client(auth->cid, messages[REPORT_LOOKUP]); set_provider_on(auth, PROVIDER_RDNS); return true; } @@ -144,7 +145,7 @@ static void client_fail(struct auth_client *auth, dns_message report) rb_strlcpy(auth->hostname, "*", sizeof(auth->hostname)); - notice_client(auth, messages[report]); + notice_client(auth->cid, messages[report]); cancel_query(query->query); rb_free(query); @@ -157,7 +158,7 @@ static void client_success(struct auth_client *auth) { struct user_query *query = auth->data[PROVIDER_RDNS]; - notice_client(auth, messages[REPORT_FOUND]); + notice_client(auth->cid, messages[REPORT_FOUND]); cancel_query(query->query); rb_free(query); From a51487e0e721591dcedcf2f23cd5d3e567269860 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Fri, 25 Mar 2016 23:04:00 -0500 Subject: [PATCH 55/96] authd/provider: add options handlers for providers This allows providers to create handlers for changing their configuration. --- authd/authd.c | 35 ++++++++++++++++++++++++++++++++++- authd/authd.h | 16 ++++++++++++++-- authd/provider.c | 15 +++++++++++++++ authd/provider.h | 5 ++++- 4 files changed, 67 insertions(+), 4 deletions(-) diff --git a/authd/authd.c b/authd/authd.c index d77d87b1..c6ed0911 100644 --- a/authd/authd.c +++ b/authd/authd.c @@ -27,11 +27,13 @@ static void handle_reload(int parc, char *parv[]); static void handle_stat(int parc, char *parv[]); +static void handle_options(int parc, char *parv[]); rb_helper *authd_helper = NULL; authd_cmd_handler authd_cmd_handlers[256] = { ['C'] = handle_new_connection, ['D'] = resolve_dns, + ['O'] = handle_options, ['R'] = handle_reload, ['S'] = handle_stat, }; @@ -44,6 +46,8 @@ authd_reload_handler authd_reload_handlers[256] = { ['D'] = reload_nameservers, }; +rb_dictionary *authd_option_handlers; + static void handle_stat(int parc, char *parv[]) { @@ -61,6 +65,32 @@ handle_stat(int parc, char *parv[]) handler(parv[1], parv[2][0]); } +static void +handle_options(int parc, char *parv[]) +{ + struct auth_opts_handler *handler; + + if(parc < 4) + { + warn_opers(L_CRIT, "BUG: handle_options received too few parameters (at least 4 expected, got %d)", parc); + return; + } + + if((handler = rb_dictionary_retrieve(authd_option_handlers, parv[1])) == NULL) + { + warn_opers(L_CRIT, "BUG: handle_options got a bad option type %s", parv[1]); + return; + } + + if((parc - 2) < handler->min_parc) + { + warn_opers(L_CRIT, "BUG: handle_options received too few parameters (at least %d expected, got %d)", handler->min_parc, parc); + return; + } + + handler->handler(parv[1], parc - 2, (const char **)(parv + 3)); +} + static void handle_reload(int parc, char *parv[]) { @@ -69,7 +99,7 @@ handle_reload(int parc, char *parv[]) if(parc < 2) { /* Reload all handlers */ - for(size_t i = 0; i < sizeof(authd_reload_handlers); i++) + for(size_t i = 0; i < 256; i++) { if ((handler = authd_reload_handlers[(unsigned char) i]) != NULL) handler(parv[1][0]); @@ -163,6 +193,9 @@ main(int argc, char *argv[]) rb_set_time(); setup_signals(); + + authd_option_handlers = rb_dictionary_create("authd options handlers", strcasecmp); + init_resolver(); init_providers(); rb_init_prng(NULL, RB_PRNG_DEFAULT); diff --git a/authd/authd.h b/authd/authd.h index b44a85d9..07c746ca 100644 --- a/authd/authd.h +++ b/authd/authd.h @@ -21,12 +21,22 @@ #ifndef _AUTHD_H #define _AUTHD_H -#include -#include +#include "stdinc.h" +#include "rb_lib.h" +#include "rb_dictionary.h" #include "setup.h" #include "ircd_defs.h" +typedef void (*provider_opts_handler_t)(const char *, int, const char **); + +struct auth_opts_handler +{ + const char *option; + int min_parc; + provider_opts_handler_t handler; +}; + extern rb_helper *authd_helper; typedef void (*authd_cmd_handler)(int parc, char *parv[]); @@ -37,4 +47,6 @@ extern authd_cmd_handler authd_cmd_handlers[256]; extern authd_stat_handler authd_stat_handlers[256]; extern authd_reload_handler authd_reload_handlers[256]; +extern rb_dictionary *authd_option_handlers; + #endif diff --git a/authd/provider.c b/authd/provider.c index 1a6c6517..dfabac95 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -65,12 +65,27 @@ void load_provider(struct auth_provider *provider) return; } + if(provider->opt_handlers != NULL) + { + struct auth_opts_handler *handler; + + for(handler = provider->opt_handlers; handler->option != NULL; handler++) + rb_dictionary_add(authd_option_handlers, handler->option, handler); + } + provider->init(); rb_dlinkAdd(provider, &provider->node, &auth_providers); } void unload_provider(struct auth_provider *provider) { + if(provider->opt_handlers != NULL) + { + struct auth_opts_handler *handler; + + for(handler = provider->opt_handlers; handler->option != NULL; handler++) + rb_dictionary_delete(authd_option_handlers, handler->option); + } provider->destroy(); rb_dlinkDelete(&provider->node, &auth_providers); } diff --git a/authd/provider.h b/authd/provider.h index 8fab21cf..28deef64 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -22,6 +22,7 @@ #define __CHARYBDIS_AUTHD_PROVIDER_H__ #include "stdinc.h" +#include "authd.h" #include "rb_dictionary.h" #define MAX_PROVIDERS 32 /* This should be enough */ @@ -61,7 +62,7 @@ typedef void (*provider_destroy_t)(void); typedef bool (*provider_start_t)(struct auth_client *); typedef void (*provider_cancel_t)(struct auth_client *); -typedef void (*provider_complete_t)(struct auth_client *, provider_t provider); +typedef void (*provider_complete_t)(struct auth_client *, provider_t); struct auth_provider { @@ -75,6 +76,8 @@ struct auth_provider provider_start_t start; /* Perform authentication */ provider_cancel_t cancel; /* Authentication cancelled */ provider_complete_t completed; /* Callback for when other performers complete (think dependency chains) */ + + struct auth_opts_handler *opt_handlers; }; extern rb_dlink_list auth_providers; From 3f2695ac861d20ab0f18aa4fdca7447cb4c45dfe Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 15:27:57 -0500 Subject: [PATCH 56/96] providers/blacklist: add configuration interface --- authd/providers/blacklist.c | 111 ++++++++++++++++++++++++++++++++---- 1 file changed, 100 insertions(+), 11 deletions(-) diff --git a/authd/providers/blacklist.c b/authd/providers/blacklist.c index df7d3974..07de493d 100644 --- a/authd/providers/blacklist.c +++ b/authd/providers/blacklist.c @@ -81,7 +81,7 @@ struct blacklist_lookup struct blacklist_filter { filter_t type; /* Type of filter */ - char filterstr[HOSTIPLEN]; /* The filter itself */ + char filter[HOSTIPLEN]; /* The filter itself */ rb_dlink_node node; }; @@ -102,8 +102,8 @@ static void blacklists_cancel(struct auth_client *); /* private interfaces */ static void unref_blacklist(struct blacklist *); -static struct blacklist *new_blacklist(char *, char *, bool, bool, rb_dlink_list *); -static struct blacklist *find_blacklist(char *); +static struct blacklist *new_blacklist(const char *, const char *, unsigned char, rb_dlink_list *); +static struct blacklist *find_blacklist(const char *); static bool blacklist_check_reply(struct blacklist_lookup *, const char *); static void blacklist_dns_callback(const char *, bool, query_type, void *); static void initiate_blacklist_dnsquery(struct blacklist *, struct auth_client *); @@ -137,11 +137,11 @@ unref_blacklist(struct blacklist *bl) } static struct blacklist * -new_blacklist(char *name, char *reason, bool ipv4, bool ipv6, rb_dlink_list *filters) +new_blacklist(const char *name, const char *reason, unsigned char iptype, rb_dlink_list *filters) { struct blacklist *bl; - if (name == NULL || reason == NULL || !(ipv4 || ipv6)) + if (name == NULL || reason == NULL || iptype == 0) return NULL; if((bl = find_blacklist(name)) == NULL) @@ -154,10 +154,7 @@ new_blacklist(char *name, char *reason, bool ipv4, bool ipv6, rb_dlink_list *fil rb_strlcpy(bl->host, name, IRCD_RES_HOSTLEN + 1); rb_strlcpy(bl->reason, reason, BUFSIZE); - if(ipv4) - bl->iptype |= IPTYPE_IPV4; - if(ipv6) - bl->iptype |= IPTYPE_IPV6; + bl->iptype = iptype; rb_dlinkMoveList(filters, &bl->filters); @@ -167,7 +164,7 @@ new_blacklist(char *name, char *reason, bool ipv4, bool ipv6, rb_dlink_list *fil } static struct blacklist * -find_blacklist(char *name) +find_blacklist(const char *name) { rb_dlink_node *ptr; @@ -213,7 +210,7 @@ blacklist_check_reply(struct blacklist_lookup *bllookup, const char *ipaddr) continue; } - if (strcmp(cmpstr, filter->filterstr) == 0) + if (strcmp(cmpstr, filter->filter) == 0) /* Match! */ return true; } @@ -422,6 +419,97 @@ blacklists_destroy(void) } } +static void +add_conf_blacklist(const char *key, int parc, const char **parv) +{ + rb_dlink_list filters; + char *tmp, *elemlist = rb_strdup(parv[2]); + unsigned char iptype; + + for(char *elem = rb_strtok_r(elemlist, ",", &tmp); elem; elem = rb_strtok_r(NULL, ",", &tmp)) + { + struct blacklist_filter *filter = rb_malloc(sizeof(struct blacklist_filter)); + int dot_c = 0; + filter_t type = FILTER_LAST; + bool valid = true; + + /* Check blacklist filter type and for validity */ + for(char *c = elem; *c != '\0'; c++) + { + if(*c == '.') + { + if(++dot_c > 3) + { + warn_opers(L_CRIT, "addr_conf_blacklist got a bad filter (too many octets)"); + valid = false; + break; + } + + type = FILTER_ALL; + } + else if(!isdigit(*c)) + { + warn_opers(L_CRIT, "addr_conf_blacklist got a bad filter (invalid character in blacklist filter: %c)", *c); + valid = false; + break; + } + } + + if(valid && dot_c > 0 && dot_c < 3) + { + warn_opers(L_CRIT, "addr_conf_blacklist got a bad filter (insufficient octets)"); + valid = false; + } + + if(!valid) + { + rb_free(filter); + continue; + } + + filter->type = type; + rb_strlcpy(filter->filter, elem, sizeof(filter->filter)); + rb_dlinkAdd(filter, &filter->node, &filters); + } + + rb_free(elemlist); + + iptype = atoi(parv[1]) & 0x3; + if(new_blacklist(parv[0], parv[3], iptype, &filters) == NULL) + { + rb_dlink_node *ptr, *nptr; + + warn_opers(L_CRIT, "addr_conf_blacklist got a malformed blacklist"); + + RB_DLINK_FOREACH_SAFE(ptr, nptr, filters.head) + { + rb_free(ptr->data); + rb_dlinkDelete(ptr, &filters); + } + } +} + +static void +add_conf_blacklist_timeout(const char *key, int parc, const char **parv) +{ + int timeout = atoi(parv[0]); + + if(timeout < 0) + { + warn_opers(L_CRIT, "BUG: timeout < 0 (value: %d)", timeout); + return; + } + + blacklist_timeout = timeout; +} + +struct auth_opts_handler blacklist_options[] = +{ + { "rbl", 4, add_conf_blacklist }, + { "rbl_timeout", 1, add_conf_blacklist_timeout }, + { NULL, 0, NULL }, +}; + struct auth_provider blacklist_provider = { .id = PROVIDER_BLACKLIST, @@ -430,4 +518,5 @@ struct auth_provider blacklist_provider = .start = blacklists_start, .cancel = blacklists_cancel, .completed = blacklists_initiate, + .opt_handlers = blacklist_options, }; From 646e6567c7454a9dd7eb85daeb1fc77006d6ca99 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 15:36:12 -0500 Subject: [PATCH 57/96] providers/rdns: add configuration interface for rDNS timeout --- authd/providers/blacklist.c | 2 +- authd/providers/rdns.c | 121 ++++++++++++++++++++++-------------- 2 files changed, 75 insertions(+), 48 deletions(-) diff --git a/authd/providers/blacklist.c b/authd/providers/blacklist.c index 07de493d..ad7b4a45 100644 --- a/authd/providers/blacklist.c +++ b/authd/providers/blacklist.c @@ -496,7 +496,7 @@ add_conf_blacklist_timeout(const char *key, int parc, const char **parv) if(timeout < 0) { - warn_opers(L_CRIT, "BUG: timeout < 0 (value: %d)", timeout); + warn_opers(L_CRIT, "BUG: blacklist timeout < 0 (value: %d)", timeout); return; } diff --git a/authd/providers/rdns.c b/authd/providers/rdns.c index 0b203740..6e99a6fc 100644 --- a/authd/providers/rdns.c +++ b/authd/providers/rdns.c @@ -57,50 +57,6 @@ static struct ev_entry *timeout_ev; static EVH timeout_dns_queries_event; static int rdns_timeout = 15; - -bool client_dns_init(void) -{ - timeout_ev = rb_event_addish("timeout_dns_queries_event", timeout_dns_queries_event, NULL, 1); - return (timeout_ev != NULL); -} - -void client_dns_destroy(void) -{ - struct auth_client *auth; - rb_dictionary_iter iter; - - RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) - { - if(auth->data[PROVIDER_RDNS] != NULL) - client_fail(auth, REPORT_FAIL); - } - - rb_event_delete(timeout_ev); -} - -bool client_dns_start(struct auth_client *auth) -{ - struct user_query *query = rb_malloc(sizeof(struct user_query)); - - query->timeout = rb_current_time() + rdns_timeout; - - auth->data[PROVIDER_RDNS] = query; - - query->query = lookup_hostname(auth->c_ip, dns_answer_callback, auth); - - notice_client(auth->cid, messages[REPORT_LOOKUP]); - set_provider_on(auth, PROVIDER_RDNS); - return true; -} - -void client_dns_cancel(struct auth_client *auth) -{ - struct user_query *query = auth->data[PROVIDER_RDNS]; - - if(query != NULL) - client_fail(auth, REPORT_FAIL); -} - static void dns_answer_callback(const char *res, bool status, query_type type, void *data) { @@ -119,7 +75,8 @@ dns_answer_callback(const char *res, bool status, query_type type, void *data) } /* Timeout outstanding queries */ -static void timeout_dns_queries_event(void *notused) +static void +timeout_dns_queries_event(void *notused) { struct auth_client *auth; rb_dictionary_iter iter; @@ -136,7 +93,8 @@ static void timeout_dns_queries_event(void *notused) } } -static void client_fail(struct auth_client *auth, dns_message report) +static void +client_fail(struct auth_client *auth, dns_message report) { struct user_query *query = auth->data[PROVIDER_RDNS]; @@ -154,7 +112,8 @@ static void client_fail(struct auth_client *auth, dns_message report) provider_done(auth, PROVIDER_RDNS); } -static void client_success(struct auth_client *auth) +static void +client_success(struct auth_client *auth) { struct user_query *query = auth->data[PROVIDER_RDNS]; @@ -167,6 +126,73 @@ static void client_success(struct auth_client *auth) provider_done(auth, PROVIDER_RDNS); } +static bool +client_dns_init(void) +{ + timeout_ev = rb_event_addish("timeout_dns_queries_event", timeout_dns_queries_event, NULL, 1); + return (timeout_ev != NULL); +} + +static void +client_dns_destroy(void) +{ + struct auth_client *auth; + rb_dictionary_iter iter; + + RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) + { + if(auth->data[PROVIDER_RDNS] != NULL) + client_fail(auth, REPORT_FAIL); + } + + rb_event_delete(timeout_ev); +} + +static bool +client_dns_start(struct auth_client *auth) +{ + struct user_query *query = rb_malloc(sizeof(struct user_query)); + + query->timeout = rb_current_time() + rdns_timeout; + + auth->data[PROVIDER_RDNS] = query; + + query->query = lookup_hostname(auth->c_ip, dns_answer_callback, auth); + + notice_client(auth->cid, messages[REPORT_LOOKUP]); + set_provider_on(auth, PROVIDER_RDNS); + return true; +} + +static void +client_dns_cancel(struct auth_client *auth) +{ + struct user_query *query = auth->data[PROVIDER_RDNS]; + + if(query != NULL) + client_fail(auth, REPORT_FAIL); +} + +static void +add_conf_dns_timeout(const char *key, int parc, const char **parv) +{ + int timeout = atoi(parv[0]); + + if(timeout < 0) + { + warn_opers(L_CRIT, "BUG: DNS timeout < 0 (value: %d)", timeout); + return; + } + + rdns_timeout = timeout; +} + +struct auth_opts_handler rdns_options[] = +{ + { "dns_timeout", 1, add_conf_dns_timeout }, + { NULL, 0, NULL }, +}; + struct auth_provider rdns_provider = { .id = PROVIDER_RDNS, @@ -175,4 +201,5 @@ struct auth_provider rdns_provider = .start = client_dns_start, .cancel = client_dns_cancel, .completed = NULL, + .opt_handlers = rdns_options, }; From 06f3496ab39dde778287d55cdcd6c1c1078bd2b8 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 15:39:55 -0500 Subject: [PATCH 58/96] providers/ident: cleanup things --- authd/providers/ident.c | 174 +++++++++++++++++++++------------------- 1 file changed, 93 insertions(+), 81 deletions(-) diff --git a/authd/providers/ident.c b/authd/providers/ident.c index 2c561462..714102b7 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -18,6 +18,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ +/* Largely adapted from old s_auth.c, but reworked for authd. rDNS code + * moved to its own provider. + * + * --Elizafox 13 March 2016 + */ + #include "stdinc.h" #include "match.h" #include "authd.h" @@ -60,83 +66,9 @@ static struct ev_entry *timeout_ev; static int ident_timeout = 5; -bool ident_init(void) -{ - timeout_ev = rb_event_addish("timeout_ident_queries_event", timeout_ident_queries_event, NULL, 1); - return (timeout_ev != NULL); -} - -void ident_destroy(void) -{ - struct auth_client *auth; - rb_dictionary_iter iter; - - /* Nuke all ident queries */ - RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) - { - if(auth->data[PROVIDER_IDENT] != NULL) - client_fail(auth, REPORT_FAIL); - } -} - -bool ident_start(struct auth_client *auth) -{ - struct ident_query *query = rb_malloc(sizeof(struct ident_query)); - struct rb_sockaddr_storage l_addr, c_addr; - int family; - rb_fde_t *F; - - auth->data[PROVIDER_IDENT] = query; - query->timeout = rb_current_time() + ident_timeout; - - if((F = rb_socket(family, SOCK_STREAM, 0, "ident")) == NULL) - { - client_fail(auth, REPORT_FAIL); - return true; /* Not a fatal error */ - } - - query->F = F; - - /* Build sockaddr_storages for rb_connect_tcp below */ - memcpy(&l_addr, &auth->l_addr, sizeof(l_addr)); - memcpy(&c_addr, &auth->c_addr, sizeof(c_addr)); - - /* Set the ports correctly */ -#ifdef RB_IPV6 - if(GET_SS_FAMILY(&l_addr) == AF_INET6) - ((struct sockaddr_in6 *)&l_addr)->sin6_port = 0; - else -#endif - ((struct sockaddr_in *)&l_addr)->sin_port = 0; - -#ifdef RB_IPV6 - if(GET_SS_FAMILY(&c_addr) == AF_INET6) - ((struct sockaddr_in6 *)&c_addr)->sin6_port = htons(113); - else -#endif - ((struct sockaddr_in *)&c_addr)->sin_port = htons(113); - - rb_connect_tcp(F, (struct sockaddr *)&c_addr, - (struct sockaddr *)&l_addr, - GET_SS_LEN(&l_addr), ident_connected, - query, ident_timeout); - - notice_client(auth->cid, messages[REPORT_LOOKUP]); - set_provider_on(auth, PROVIDER_IDENT); - - return true; -} - -void ident_cancel(struct auth_client *auth) -{ - struct ident_query *query = auth->data[PROVIDER_IDENT]; - - if(query != NULL) - client_fail(auth, REPORT_FAIL); -} - /* Timeout outstanding queries */ -static void timeout_ident_queries_event(void *notused) +static void +timeout_ident_queries_event(void *notused) { struct auth_client *auth; rb_dictionary_iter iter; @@ -161,7 +93,8 @@ static void timeout_ident_queries_event(void *notused) * a write buffer far greater than this message to store it in should * problems arise. -avalon */ -static void ident_connected(rb_fde_t *F, int error, void *data) +static void +ident_connected(rb_fde_t *F, int error, void *data) { struct auth_client *auth = data; struct ident_query *query = auth->data[PROVIDER_IDENT]; @@ -240,7 +173,8 @@ read_ident_reply(rb_fde_t *F, void *data) client_success(auth); } -static void client_fail(struct auth_client *auth, ident_message report) +static void +client_fail(struct auth_client *auth, ident_message report) { struct ident_query *query = auth->data[PROVIDER_IDENT]; @@ -254,7 +188,8 @@ static void client_fail(struct auth_client *auth, ident_message report) provider_done(auth, PROVIDER_IDENT); } -static void client_success(struct auth_client *auth) +static void +client_success(struct auth_client *auth) { struct ident_query *query = auth->data[PROVIDER_IDENT]; @@ -269,8 +204,7 @@ static void client_success(struct auth_client *auth) /* get_valid_ident * parse ident query reply from identd server * - * Torn out of old s_auth.c because there was nothing wrong with it - * --Elizafox + * Taken from old s_auth.c --Elizafox * * Inputs - pointer to ident buf * Outputs - NULL if no valid ident found, otherwise pointer to name @@ -331,6 +265,84 @@ get_valid_ident(char *buf) return (colon3Ptr); } +static bool +ident_init(void) +{ + timeout_ev = rb_event_addish("timeout_ident_queries_event", timeout_ident_queries_event, NULL, 1); + return (timeout_ev != NULL); +} + +static void +ident_destroy(void) +{ + struct auth_client *auth; + rb_dictionary_iter iter; + + /* Nuke all ident queries */ + RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) + { + if(auth->data[PROVIDER_IDENT] != NULL) + client_fail(auth, REPORT_FAIL); + } +} + +static bool ident_start(struct auth_client *auth) +{ + struct ident_query *query = rb_malloc(sizeof(struct ident_query)); + struct rb_sockaddr_storage l_addr, c_addr; + int family; + rb_fde_t *F; + + auth->data[PROVIDER_IDENT] = query; + query->timeout = rb_current_time() + ident_timeout; + + if((F = rb_socket(family, SOCK_STREAM, 0, "ident")) == NULL) + { + client_fail(auth, REPORT_FAIL); + return true; /* Not a fatal error */ + } + + query->F = F; + + /* Build sockaddr_storages for rb_connect_tcp below */ + memcpy(&l_addr, &auth->l_addr, sizeof(l_addr)); + memcpy(&c_addr, &auth->c_addr, sizeof(c_addr)); + + /* Set the ports correctly */ +#ifdef RB_IPV6 + if(GET_SS_FAMILY(&l_addr) == AF_INET6) + ((struct sockaddr_in6 *)&l_addr)->sin6_port = 0; + else +#endif + ((struct sockaddr_in *)&l_addr)->sin_port = 0; + +#ifdef RB_IPV6 + if(GET_SS_FAMILY(&c_addr) == AF_INET6) + ((struct sockaddr_in6 *)&c_addr)->sin6_port = htons(113); + else +#endif + ((struct sockaddr_in *)&c_addr)->sin_port = htons(113); + + rb_connect_tcp(F, (struct sockaddr *)&c_addr, + (struct sockaddr *)&l_addr, + GET_SS_LEN(&l_addr), ident_connected, + query, ident_timeout); + + notice_client(auth->cid, messages[REPORT_LOOKUP]); + set_provider_on(auth, PROVIDER_IDENT); + + return true; +} + +static void +ident_cancel(struct auth_client *auth) +{ + struct ident_query *query = auth->data[PROVIDER_IDENT]; + + if(query != NULL) + client_fail(auth, REPORT_FAIL); +} + struct auth_provider ident_provider = { From a0a218bac88652a27fc57b4973c9a73101dabd7f Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 16:36:14 -0500 Subject: [PATCH 59/96] authd/providers/blacklist: add configuration interface for deletion --- authd/providers/blacklist.c | 57 ++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/authd/providers/blacklist.c b/authd/providers/blacklist.c index ad7b4a45..a99f0c90 100644 --- a/authd/providers/blacklist.c +++ b/authd/providers/blacklist.c @@ -323,6 +323,29 @@ lookup_all_blacklists(struct auth_client *auth) bluser->timeout = rb_current_time() + blacklist_timeout; } +static inline void +delete_blacklist(struct blacklist *bl) +{ + if (bl->refcount > 0) + bl->delete = true; + else + { + rb_dlinkFindDestroy(bl, &blacklist_list); + rb_free(bl); + } +} + +static void +delete_all_blacklists(void) +{ + rb_dlink_node *ptr, *nptr; + + RB_DLINK_FOREACH_SAFE(ptr, nptr, blacklist_list.head) + { + delete_blacklist(ptr->data); + } +} + /* public interfaces */ static bool blacklists_start(struct auth_client *auth) @@ -406,17 +429,8 @@ blacklists_destroy(void) blacklists_cancel(auth); } - RB_DLINK_FOREACH_SAFE(ptr, nptr, blacklist_list.head) - { - bl = ptr->data; - if (bl->refcount > 0) - bl->delete = true; - else - { - rb_free(ptr->data); - rb_dlinkDestroy(ptr, &blacklist_list); - } - } + delete_all_blacklists(); + rb_event_delete(timeout_ev); } static void @@ -489,6 +503,25 @@ add_conf_blacklist(const char *key, int parc, const char **parv) } } +static void +del_conf_blacklist(const char *key, int parc, const char **parv) +{ + struct blacklist *bl = find_blacklist(parv[0]); + if(bl == NULL) + { + warn_opers(L_CRIT, "BUG: tried to remove nonexistent blacklist %s", parv[0]); + return; + } + + delete_blacklist(bl); +} + +static void +del_conf_blacklist_all(const char *key, int parc, const char **parv) +{ + delete_all_blacklists(); +} + static void add_conf_blacklist_timeout(const char *key, int parc, const char **parv) { @@ -506,6 +539,8 @@ add_conf_blacklist_timeout(const char *key, int parc, const char **parv) struct auth_opts_handler blacklist_options[] = { { "rbl", 4, add_conf_blacklist }, + { "rbl_del", 1, del_conf_blacklist }, + { "rbl_del_all", 0, del_conf_blacklist_all }, { "rbl_timeout", 1, add_conf_blacklist_timeout }, { NULL, 0, NULL }, }; From 67acafca57ea211b3bcf5b7f84f982b2b632ee67 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 16:36:50 -0500 Subject: [PATCH 60/96] authd/providers/ident: add configuration interface --- authd/providers/ident.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/authd/providers/ident.c b/authd/providers/ident.c index 714102b7..442a84ca 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -343,6 +343,26 @@ ident_cancel(struct auth_client *auth) client_fail(auth, REPORT_FAIL); } +static void +add_conf_ident_timeout(const char *key, int parc, const char **parv) +{ + int timeout = atoi(parv[0]); + + if(timeout < 0) + { + warn_opers(L_CRIT, "BUG: ident timeout < 0 (value: %d)", timeout); + return; + } + + ident_timeout = timeout; +} + +struct auth_opts_handler ident_options[] = +{ + { "ident_timeout", 1, add_conf_ident_timeout }, + { NULL, 0, NULL }, +}; + struct auth_provider ident_provider = { @@ -352,4 +372,5 @@ struct auth_provider ident_provider = .start = ident_start, .cancel = ident_cancel, .completed = NULL, + .opt_handlers = ident_options, }; From 6ced6a1f1acfa1b04bedef65932d602caf1df63a Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 16:37:04 -0500 Subject: [PATCH 61/96] authd/providers/rdns: minor function renaming cleanup --- authd/providers/rdns.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/authd/providers/rdns.c b/authd/providers/rdns.c index 6e99a6fc..e5e1f6dd 100644 --- a/authd/providers/rdns.c +++ b/authd/providers/rdns.c @@ -127,14 +127,14 @@ client_success(struct auth_client *auth) } static bool -client_dns_init(void) +rdns_init(void) { timeout_ev = rb_event_addish("timeout_dns_queries_event", timeout_dns_queries_event, NULL, 1); return (timeout_ev != NULL); } static void -client_dns_destroy(void) +rdns_destroy(void) { struct auth_client *auth; rb_dictionary_iter iter; @@ -149,7 +149,7 @@ client_dns_destroy(void) } static bool -client_dns_start(struct auth_client *auth) +rdns_start(struct auth_client *auth) { struct user_query *query = rb_malloc(sizeof(struct user_query)); @@ -165,7 +165,7 @@ client_dns_start(struct auth_client *auth) } static void -client_dns_cancel(struct auth_client *auth) +rdns_cancel(struct auth_client *auth) { struct user_query *query = auth->data[PROVIDER_RDNS]; @@ -196,10 +196,10 @@ struct auth_opts_handler rdns_options[] = struct auth_provider rdns_provider = { .id = PROVIDER_RDNS, - .init = client_dns_init, - .destroy = client_dns_destroy, - .start = client_dns_start, - .cancel = client_dns_cancel, + .init = rdns_init, + .destroy = rdns_destroy, + .start = rdns_start, + .cancel = rdns_cancel, .completed = NULL, .opt_handlers = rdns_options, }; From cdf1592915ae34a74df2de13caca43e6927162d6 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 16:53:43 -0500 Subject: [PATCH 62/96] Check these out from authd-framework-2. --- authd/dns.h | 5 ----- authd/provider.h | 19 +------------------ 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/authd/dns.h b/authd/dns.h index 9db7ea97..a21d9858 100644 --- a/authd/dns.h +++ b/authd/dns.h @@ -50,15 +50,10 @@ struct dns_query void *data; }; -<<<<<<< HEAD -extern void format_address(struct rb_sockaddr_storage *addr, char *buffer, size_t length); -extern bool sockcmp(struct rb_sockaddr_storage *addr, struct rb_sockaddr_storage *addr2, int family); -======= extern struct dns_query *lookup_hostname(const char *ip, DNSCB callback, void *data); extern struct dns_query *lookup_ip(const char *host, int aftype, DNSCB callback, void *data); extern void cancel_query(struct dns_query *query); ->>>>>>> authd-framework-2 extern void resolve_dns(int parc, char *parv[]); extern void enumerate_nameservers(const char *rid, const char letter); extern void reload_nameservers(const char letter); diff --git a/authd/provider.h b/authd/provider.h index fc78903c..28deef64 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -39,10 +39,6 @@ struct auth_client { uint16_t cid; /* Client ID */ -<<<<<<< HEAD - struct rb_sockaddr_storage l_addr; /* Listener IP address */ - struct rb_sockaddr_storage c_addr; /* Client IP address */ -======= char l_ip[HOSTIPLEN + 1]; /* Listener IP address */ uint16_t l_port; /* Listener port */ struct rb_sockaddr_storage l_addr; /* Listener address/port */ @@ -50,23 +46,10 @@ struct auth_client char c_ip[HOSTIPLEN + 1]; /* Client IP address */ uint16_t c_port; /* Client port */ struct rb_sockaddr_storage c_addr; /* Client address/port */ ->>>>>>> authd-framework-2 char hostname[HOSTLEN + 1]; /* Used for DNS lookup */ char username[USERLEN + 1]; /* Used for ident lookup */ -<<<<<<< HEAD - unsigned int providers; /* Providers at work, - * none left when set to 0 */ -}; - -typedef bool (*provider_init_t)(void); -typedef bool (*provider_perform_t)(struct auth_client *); -typedef void (*provider_complete_t)(struct auth_client *, provider_t provider); -typedef void (*provider_cancel_t)(struct auth_client *); -typedef void (*provider_destroy_t)(void); - -======= uint32_t providers; /* Providers at work, * none left when set to 0 */ uint32_t providers_done; /* Providers completed */ @@ -81,7 +64,6 @@ typedef bool (*provider_start_t)(struct auth_client *); typedef void (*provider_cancel_t)(struct auth_client *); typedef void (*provider_complete_t)(struct auth_client *, provider_t); ->>>>>>> authd-framework-2 struct auth_provider { rb_dlink_node node; @@ -118,6 +100,7 @@ void reject_client(struct auth_client *auth, provider_t id, const char *reason); void handle_new_connection(int parc, char *parv[]); +/* Provider is operating on this auth_client (set this if you have async work to do) */ static inline void set_provider_on(struct auth_client *auth, provider_t provider) { auth->providers |= (1 << provider); From 47ab6f6e6e2b471eb9c4d605fe25b5c1803ebbb5 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 17:35:48 -0500 Subject: [PATCH 63/96] authd/providers/ident: properly initialise variable --- authd/providers/ident.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/authd/providers/ident.c b/authd/providers/ident.c index 442a84ca..30708e40 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -290,20 +290,20 @@ static bool ident_start(struct auth_client *auth) { struct ident_query *query = rb_malloc(sizeof(struct ident_query)); struct rb_sockaddr_storage l_addr, c_addr; - int family; - rb_fde_t *F; + int family = GET_SS_FAMILY(&auth->c_addr); + + notice_client(auth->cid, messages[REPORT_LOOKUP]); auth->data[PROVIDER_IDENT] = query; query->timeout = rb_current_time() + ident_timeout; - if((F = rb_socket(family, SOCK_STREAM, 0, "ident")) == NULL) + if((query->F = rb_socket(family, SOCK_STREAM, 0, "ident")) == NULL) { + warn_opers(L_DEBUG, "Could not create ident socket: %s", strerror(errno)); client_fail(auth, REPORT_FAIL); return true; /* Not a fatal error */ } - query->F = F; - /* Build sockaddr_storages for rb_connect_tcp below */ memcpy(&l_addr, &auth->l_addr, sizeof(l_addr)); memcpy(&c_addr, &auth->c_addr, sizeof(c_addr)); @@ -323,12 +323,11 @@ static bool ident_start(struct auth_client *auth) #endif ((struct sockaddr_in *)&c_addr)->sin_port = htons(113); - rb_connect_tcp(F, (struct sockaddr *)&c_addr, + rb_connect_tcp(query->F, (struct sockaddr *)&c_addr, (struct sockaddr *)&l_addr, GET_SS_LEN(&l_addr), ident_connected, query, ident_timeout); - notice_client(auth->cid, messages[REPORT_LOOKUP]); set_provider_on(auth, PROVIDER_IDENT); return true; From f875cb848236bfa8956f1cb8fb350937d389781d Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 18:01:14 -0500 Subject: [PATCH 64/96] providers/ident: more aggressive NULL checks --- authd/providers/ident.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/authd/providers/ident.c b/authd/providers/ident.c index 30708e40..082c95aa 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -42,9 +42,9 @@ struct ident_query /* Goinked from old s_auth.c --Elizafox */ static const char *messages[] = { - ":*** Checking Ident", - ":*** Got Ident response", - ":*** No Ident response", + "*** Checking Ident", + "*** Got Ident response", + "*** No Ident response", }; typedef enum @@ -101,6 +101,9 @@ ident_connected(rb_fde_t *F, int error, void *data) char authbuf[32]; int authlen; + if(query == NULL) + return; + /* Check the error */ if(error != RB_OK) { @@ -133,6 +136,9 @@ read_ident_reply(rb_fde_t *F, void *data) int count; char buf[IDENT_BUFSIZE + 1]; /* buffer to read auth reply into */ + if(query == NULL) + return; + len = rb_read(F, buf, IDENT_BUFSIZE); if(len < 0 && rb_ignore_errno(errno)) { @@ -178,9 +184,14 @@ client_fail(struct auth_client *auth, ident_message report) { struct ident_query *query = auth->data[PROVIDER_IDENT]; + if(query == NULL) + return; + rb_strlcpy(auth->username, "*", sizeof(auth->username)); - rb_close(query->F); + if(query->F != NULL) + rb_close(query->F); + rb_free(query); auth->data[PROVIDER_IDENT] = NULL; @@ -193,7 +204,12 @@ client_success(struct auth_client *auth) { struct ident_query *query = auth->data[PROVIDER_IDENT]; - rb_close(query->F); + if(query == NULL) + return; + + if(query->F != NULL) + rb_close(query->F); + rb_free(query); auth->data[PROVIDER_IDENT] = NULL; From 0cff7adb13278fa92b438390e7cb5be871262083 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 18:01:58 -0500 Subject: [PATCH 65/96] authd/provider: some fixes --- authd/provider.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index dfabac95..d048ae7a 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -244,6 +244,8 @@ static void start_auth(const char *cid, const char *l_ip, const char *l_port, co #endif ((struct sockaddr_in *)&auth->c_addr)->sin_port = htons(auth->c_port); + memset(auth->data, 0, sizeof(auth->data)); + rb_dictionary_add(auth_clients, RB_UINT_TO_POINTER(auth->cid), auth); RB_DLINK_FOREACH(ptr, auth_providers.head) @@ -267,9 +269,9 @@ static void start_auth(const char *cid, const char *l_ip, const char *l_port, co /* Callback for the initiation */ void handle_new_connection(int parc, char *parv[]) { - if(parc < 7) + if(parc < 6) { - warn_opers(L_CRIT, "BUG: received too few params for new connection (7 expected, got %d)", parc); + warn_opers(L_CRIT, "BUG: received too few params for new connection (6 expected, got %d)", parc); return; } From d1b70e352451d33a54e0afe966bfe302834756a8 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 18:40:17 -0500 Subject: [PATCH 66/96] providers/ident: fix some nasty crashes --- authd/providers/ident.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/authd/providers/ident.c b/authd/providers/ident.c index 082c95aa..c32d026f 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -68,7 +68,7 @@ static int ident_timeout = 5; /* Timeout outstanding queries */ static void -timeout_ident_queries_event(void *notused) +timeout_ident_queries_event(void *notused __unused) { struct auth_client *auth; rb_dictionary_iter iter; @@ -94,13 +94,18 @@ timeout_ident_queries_event(void *notused) * problems arise. -avalon */ static void -ident_connected(rb_fde_t *F, int error, void *data) +ident_connected(rb_fde_t *F __unused, int error, void *data) { struct auth_client *auth = data; - struct ident_query *query = auth->data[PROVIDER_IDENT]; + struct ident_query *query; char authbuf[32]; int authlen; + if(auth == NULL) + return; + + query = auth->data[PROVIDER_IDENT]; + if(query == NULL) return; @@ -129,20 +134,25 @@ static void read_ident_reply(rb_fde_t *F, void *data) { struct auth_client *auth = data; - struct ident_query *query = auth->data[PROVIDER_IDENT]; + struct ident_query *query; char *s = NULL; char *t = NULL; int len; int count; char buf[IDENT_BUFSIZE + 1]; /* buffer to read auth reply into */ + if(auth == NULL) + return; + + query = auth->data[PROVIDER_IDENT]; + if(query == NULL) return; len = rb_read(F, buf, IDENT_BUFSIZE); if(len < 0 && rb_ignore_errno(errno)) { - rb_setselect(F, RB_SELECT_READ, read_ident_reply, query); + rb_setselect(F, RB_SELECT_READ, read_ident_reply, auth); return; } @@ -342,7 +352,7 @@ static bool ident_start(struct auth_client *auth) rb_connect_tcp(query->F, (struct sockaddr *)&c_addr, (struct sockaddr *)&l_addr, GET_SS_LEN(&l_addr), ident_connected, - query, ident_timeout); + auth, ident_timeout); set_provider_on(auth, PROVIDER_IDENT); @@ -359,7 +369,7 @@ ident_cancel(struct auth_client *auth) } static void -add_conf_ident_timeout(const char *key, int parc, const char **parv) +add_conf_ident_timeout(const char *key __unused, int parc __unused, const char **parv) { int timeout = atoi(parv[0]); From 22946d30d5234787683021cbb89ad457735222d4 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 19:18:54 -0500 Subject: [PATCH 67/96] authd/providers/ident: fix up trailing lf/cr at end of username This bug existed in the original code too, but I have no idea how it didn't manifest. --- authd/providers/ident.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/authd/providers/ident.c b/authd/providers/ident.c index c32d026f..130c0e43 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -45,6 +45,7 @@ static const char *messages[] = "*** Checking Ident", "*** Got Ident response", "*** No Ident response", + "*** Cannot verify ident validity, ignoring ident", }; typedef enum @@ -52,6 +53,7 @@ typedef enum REPORT_LOOKUP, REPORT_FOUND, REPORT_FAIL, + REPORT_INVALID, } ident_message; static EVH timeout_ident_queries_event; @@ -135,11 +137,12 @@ read_ident_reply(rb_fde_t *F, void *data) { struct auth_client *auth = data; struct ident_query *query; + char buf[IDENT_BUFSIZE + 1]; /* buffer to read auth reply into */ + ident_message message = REPORT_FAIL; char *s = NULL; char *t = NULL; - int len; + ssize_t len; int count; - char buf[IDENT_BUFSIZE + 1]; /* buffer to read auth reply into */ if(auth == NULL) return; @@ -158,9 +161,7 @@ read_ident_reply(rb_fde_t *F, void *data) if(len > 0) { - buf[len] = '\0'; - - if((s = get_valid_ident(buf))) + if((s = get_valid_ident(buf)) != NULL) { t = auth->username; @@ -169,10 +170,9 @@ read_ident_reply(rb_fde_t *F, void *data) for (count = USERLEN; *s && count; s++) { - if(*s == '@') - { + if(*s == '@' || *s == '\r' || *s == '\n') break; - } + if(*s != ' ' && *s != ':' && *s != '[') { *t++ = *s; @@ -181,10 +181,14 @@ read_ident_reply(rb_fde_t *F, void *data) } *t = '\0'; } + else + message = REPORT_INVALID; } + warn_opers(L_DEBUG, "Got username: '%s'", auth->username); + if(s == NULL) - client_fail(auth, REPORT_FAIL); + client_fail(auth, message); else client_success(auth); } @@ -252,39 +256,39 @@ get_valid_ident(char *buf) colon1Ptr = strchr(remotePortString, ':'); if(!colon1Ptr) - return 0; + return NULL; *colon1Ptr = '\0'; colon1Ptr++; colon2Ptr = strchr(colon1Ptr, ':'); if(!colon2Ptr) - return 0; + return NULL; *colon2Ptr = '\0'; colon2Ptr++; commaPtr = strchr(remotePortString, ','); if(!commaPtr) - return 0; + return NULL; *commaPtr = '\0'; commaPtr++; remp = atoi(remotePortString); if(!remp) - return 0; + return NULL; locp = atoi(commaPtr); if(!locp) - return 0; + return NULL; /* look for USERID bordered by first pair of colons */ if(!strstr(colon1Ptr, "USERID")) - return 0; + return NULL; colon3Ptr = strchr(colon2Ptr, ':'); if(!colon3Ptr) - return 0; + return NULL; *colon3Ptr = '\0'; colon3Ptr++; From 6950cc255a6575152ff3a4c7aeb8cccdd5a1c28d Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 19:19:52 -0500 Subject: [PATCH 68/96] authd/providers/blacklist: remove dead store. --- authd/providers/blacklist.c | 1 - 1 file changed, 1 deletion(-) diff --git a/authd/providers/blacklist.c b/authd/providers/blacklist.c index a99f0c90..768d6b32 100644 --- a/authd/providers/blacklist.c +++ b/authd/providers/blacklist.c @@ -112,7 +112,6 @@ static void timeout_blacklist_queries_event(void *); /* Variables */ static rb_dlink_list blacklist_list = { NULL, NULL, 0 }; static struct ev_entry *timeout_ev; -static EVH timeout_blacklists; static int blacklist_timeout = 15; /* private interfaces */ From 4ac5b30e77a3df0602bbbc3f6631c1764325c27e Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 19:31:45 -0500 Subject: [PATCH 69/96] authd/providers/ident: remove debugging message --- authd/providers/ident.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/authd/providers/ident.c b/authd/providers/ident.c index 130c0e43..f69a63a9 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -185,8 +185,6 @@ read_ident_reply(rb_fde_t *F, void *data) message = REPORT_INVALID; } - warn_opers(L_DEBUG, "Got username: '%s'", auth->username); - if(s == NULL) client_fail(auth, message); else From f5586c3abb392a7a14c35c8ac2968c179b91182b Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 19:50:09 -0500 Subject: [PATCH 70/96] authd: misc provider fixes --- authd/authd.c | 2 +- authd/provider.c | 1 + authd/providers/blacklist.c | 6 +++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/authd/authd.c b/authd/authd.c index c6ed0911..f2b05190 100644 --- a/authd/authd.c +++ b/authd/authd.c @@ -88,7 +88,7 @@ handle_options(int parc, char *parv[]) return; } - handler->handler(parv[1], parc - 2, (const char **)(parv + 3)); + handler->handler(parv[1], parc - 2, (const char **)&parv[2]); } static void diff --git a/authd/provider.c b/authd/provider.c index d048ae7a..c92fea26 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -96,6 +96,7 @@ void init_providers(void) auth_clients = rb_dictionary_create("pending auth clients", rb_uint32cmp); load_provider(&rdns_provider); load_provider(&ident_provider); + load_provider(&blacklist_provider); } /* Terminate all providers */ diff --git a/authd/providers/blacklist.c b/authd/providers/blacklist.c index 768d6b32..7c59facc 100644 --- a/authd/providers/blacklist.c +++ b/authd/providers/blacklist.c @@ -435,10 +435,13 @@ blacklists_destroy(void) static void add_conf_blacklist(const char *key, int parc, const char **parv) { - rb_dlink_list filters; + rb_dlink_list filters = { NULL, NULL, 0 }; char *tmp, *elemlist = rb_strdup(parv[2]); unsigned char iptype; + if(*elemlist == '*') + goto end; + for(char *elem = rb_strtok_r(elemlist, ",", &tmp); elem; elem = rb_strtok_r(NULL, ",", &tmp)) { struct blacklist_filter *filter = rb_malloc(sizeof(struct blacklist_filter)); @@ -485,6 +488,7 @@ add_conf_blacklist(const char *key, int parc, const char **parv) rb_dlinkAdd(filter, &filter->node, &filters); } +end: rb_free(elemlist); iptype = atoi(parv[1]) & 0x3; From 05fdc0301d415d5422f07d87d912036ea2ad8ec3 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 20:32:35 -0500 Subject: [PATCH 71/96] authd/provider: do not accept clients until all providers have had a chance to run --- authd/provider.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index c92fea26..471e20d7 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -153,8 +153,9 @@ void provider_done(struct auth_client *auth, provider_t id) if(!auth->providers) { - /* No more providers, done */ - accept_client(auth, 0); + if(!auth->providers_starting) + /* Only do this when there are no providers left */ + accept_client(auth, 0); return; } @@ -223,6 +224,15 @@ static void start_auth(const char *cid, const char *l_ip, const char *l_port, co 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); + else + { + warn_opers(L_CRIT, "BUG: duplicate client added via start_auth: %x", auth->cid); + rb_free(auth); + return; + } + rb_strlcpy(auth->l_ip, l_ip, sizeof(auth->l_ip)); auth->l_port = (uint16_t)atoi(l_port); /* should be safe */ (void) rb_inet_pton_sock(l_ip, (struct sockaddr *)&auth->l_addr); @@ -247,12 +257,13 @@ static void start_auth(const char *cid, const char *l_ip, const char *l_port, co memset(auth->data, 0, sizeof(auth->data)); - rb_dictionary_add(auth_clients, RB_UINT_TO_POINTER(auth->cid), auth); - + auth->providers_starting = true; RB_DLINK_FOREACH(ptr, auth_providers.head) { provider = ptr->data; + lrb_assert(provider->start != NULL); + /* Execute providers */ if(!provider->start(auth)) { @@ -261,6 +272,7 @@ static void start_auth(const char *cid, const char *l_ip, const char *l_port, co return; } } + auth->providers_starting = false; /* If no providers are running, accept the client */ if(!auth->providers) From 247b304f1f7d16162bdb14901b305fdfd09b50ad Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 20:33:21 -0500 Subject: [PATCH 72/96] authd/provider: forgot this file... --- authd/provider.h | 1 + 1 file changed, 1 insertion(+) diff --git a/authd/provider.h b/authd/provider.h index 28deef64..348788ec 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -53,6 +53,7 @@ struct auth_client uint32_t providers; /* Providers at work, * none left when set to 0 */ uint32_t providers_done; /* Providers completed */ + bool providers_starting; /* Providers are still warming up */ void *data[MAX_PROVIDERS]; /* Provider-specific data slots */ }; From f681e277eb54e48102dcbb307aa49dc9663d6182 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 20:33:35 -0500 Subject: [PATCH 73/96] authd/providers/ident: perform check for valid auth_client data --- authd/providers/ident.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/authd/providers/ident.c b/authd/providers/ident.c index f69a63a9..e14fac43 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -320,6 +320,9 @@ static bool ident_start(struct auth_client *auth) struct rb_sockaddr_storage l_addr, c_addr; int family = GET_SS_FAMILY(&auth->c_addr); + if(auth->data[PROVIDER_IDENT] != NULL) + return true; + notice_client(auth->cid, messages[REPORT_LOOKUP]); auth->data[PROVIDER_IDENT] = query; From e43e61f7a79f0d9e2b500622ff42e712f2554e3a Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 23:15:28 -0500 Subject: [PATCH 74/96] authd/providers/blacklist: fix use after free After calling provider_done, you must *always* assume your auth instance is freed. --- authd/providers/blacklist.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/authd/providers/blacklist.c b/authd/providers/blacklist.c index 7c59facc..c05cb630 100644 --- a/authd/providers/blacklist.c +++ b/authd/providers/blacklist.c @@ -73,7 +73,7 @@ struct blacklist_lookup struct blacklist *bl; /* Blacklist we're checking */ struct auth_client *auth; /* Client */ struct dns_query *query; /* DNS query pointer */ - + rb_dlink_node node; }; @@ -230,11 +230,13 @@ blacklist_dns_callback(const char *result, bool status, query_type type, void *d { struct blacklist_lookup *bllookup = (struct blacklist_lookup *)data; struct blacklist_user *bluser; + struct blacklist *bl; struct auth_client *auth; if (bllookup == NULL || bllookup->auth == NULL) return; + bl = bllookup->bl; auth = bllookup->auth; bluser = auth->data[PROVIDER_BLACKLIST]; if(bluser == NULL) @@ -244,20 +246,21 @@ blacklist_dns_callback(const char *result, bool status, query_type type, void *d { /* Match found, so proceed no further */ blacklists_cancel(auth); - reject_client(auth, PROVIDER_BLACKLIST, bllookup->bl->reason); + reject_client(auth, PROVIDER_BLACKLIST, bl->reason); return; } - unref_blacklist(bllookup->bl); + unref_blacklist(bl); + cancel_query(bllookup->query); /* Ignore future responses */ rb_dlinkDelete(&bllookup->node, &bluser->queries); rb_free(bllookup); if(!rb_dlink_list_length(&bluser->queries)) { /* Done here */ - provider_done(auth, PROVIDER_BLACKLIST); rb_free(bluser); auth->data[PROVIDER_BLACKLIST] = NULL; + provider_done(auth, PROVIDER_BLACKLIST); } } @@ -398,9 +401,11 @@ blacklists_cancel(struct auth_client *auth) RB_DLINK_FOREACH_SAFE(ptr, nptr, bluser->queries.head) { struct blacklist_lookup *bllookup = ptr->data; - rb_dlinkDelete(&bllookup->node, &bluser->queries); - unref_blacklist(bllookup->bl); + cancel_query(bllookup->query); + unref_blacklist(bllookup->bl); + + rb_dlinkDelete(&bllookup->node, &bluser->queries); rb_free(bllookup); } From 420cfb677ce11aec5aca4fe35411f068ab1174b0 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 23:16:53 -0500 Subject: [PATCH 75/96] authd/provider: add notices in comments to certain functions not to use auth after calling --- authd/provider.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index 471e20d7..6c49bc18 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -142,7 +142,7 @@ void cancel_providers(struct auth_client *auth) rb_free(auth); } -/* Provider is done */ +/* Provider is done - WARNING: do not use auth instance after calling! */ void provider_done(struct auth_client *auth, provider_t id) { rb_dlink_node *ptr; @@ -169,7 +169,7 @@ void provider_done(struct auth_client *auth, provider_t id) } } -/* Reject a client */ +/* Reject a client - WARNING: do not use auth instance after calling! */ void reject_client(struct auth_client *auth, provider_t id, const char *reason) { char reject; @@ -200,7 +200,7 @@ void reject_client(struct auth_client *auth, provider_t id, const char *reason) cancel_providers(auth); } -/* Accept a client, cancel outstanding providers if any */ +/* Accept a client, cancel outstanding providers if any - WARNING: do nto use auth instance after calling! */ void accept_client(struct auth_client *auth, provider_t id) { uint32_t cid = auth->cid; From 0da2a404fab2f8e26164aa26733c570a2244c933 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 23:39:22 -0500 Subject: [PATCH 76/96] authd: try to destroy all providers on the way out. --- authd/authd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/authd/authd.c b/authd/authd.c index f2b05190..1432a545 100644 --- a/authd/authd.c +++ b/authd/authd.c @@ -202,5 +202,7 @@ main(int argc, char *argv[]) rb_helper_loop(authd_helper, 0); + destroy_providers(); + return 0; } From 60374ac975b735fa9245cb107e5e976bfb107a93 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sat, 26 Mar 2016 23:54:21 -0500 Subject: [PATCH 77/96] authd: add abiltiy to cancel connection --- authd/authd.c | 3 ++- authd/dns.c | 2 +- authd/dns.h | 2 +- authd/provider.c | 57 +++++++++++++++++++++++++++++++++++++++--------- authd/provider.h | 16 +++++++++----- 5 files changed, 62 insertions(+), 18 deletions(-) diff --git a/authd/authd.c b/authd/authd.c index 1432a545..6f500a9d 100644 --- a/authd/authd.c +++ b/authd/authd.c @@ -32,7 +32,8 @@ static void handle_options(int parc, char *parv[]); rb_helper *authd_helper = NULL; authd_cmd_handler authd_cmd_handlers[256] = { ['C'] = handle_new_connection, - ['D'] = resolve_dns, + ['D'] = handle_resolve_dns, + ['E'] = handle_cancel_connection, ['O'] = handle_options, ['R'] = handle_reload, ['S'] = handle_stat, diff --git a/authd/dns.c b/authd/dns.c index 45db36a2..19b3efcb 100644 --- a/authd/dns.c +++ b/authd/dns.c @@ -221,7 +221,7 @@ submit_dns_answer(const char *reply, bool status, query_type type, void *data) } void -resolve_dns(int parc, char *parv[]) +handle_resolve_dns(int parc, char *parv[]) { char *id = rb_strdup(parv[1]); char qtype = *parv[2]; diff --git a/authd/dns.h b/authd/dns.h index a21d9858..b4eae8c6 100644 --- a/authd/dns.h +++ b/authd/dns.h @@ -54,7 +54,7 @@ extern struct dns_query *lookup_hostname(const char *ip, DNSCB callback, void *d extern struct dns_query *lookup_ip(const char *host, int aftype, DNSCB callback, void *data); extern void cancel_query(struct dns_query *query); -extern void resolve_dns(int parc, char *parv[]); +extern void handle_resolve_dns(int parc, char *parv[]); extern void enumerate_nameservers(const char *rid, const char letter); extern void reload_nameservers(const char letter); diff --git a/authd/provider.c b/authd/provider.c index 6c49bc18..fcd9490a 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -57,7 +57,8 @@ rb_dlink_list auth_providers; rb_dictionary *auth_clients; /* Load a provider */ -void load_provider(struct auth_provider *provider) +void +load_provider(struct auth_provider *provider) { if(rb_dlink_list_length(&auth_providers) >= MAX_PROVIDERS) { @@ -77,7 +78,8 @@ void load_provider(struct auth_provider *provider) rb_dlinkAdd(provider, &provider->node, &auth_providers); } -void unload_provider(struct auth_provider *provider) +void +unload_provider(struct auth_provider *provider) { if(provider->opt_handlers != NULL) { @@ -91,7 +93,8 @@ void unload_provider(struct auth_provider *provider) } /* Initalise all providers */ -void init_providers(void) +void +init_providers(void) { auth_clients = rb_dictionary_create("pending auth clients", rb_uint32cmp); load_provider(&rdns_provider); @@ -100,7 +103,8 @@ void init_providers(void) } /* Terminate all providers */ -void destroy_providers(void) +void +destroy_providers(void) { rb_dlink_node *ptr; rb_dictionary_iter iter; @@ -124,7 +128,8 @@ void destroy_providers(void) } /* Cancel outstanding providers for a client */ -void cancel_providers(struct auth_client *auth) +void +cancel_providers(struct auth_client *auth) { rb_dlink_node *ptr; struct auth_provider *provider; @@ -143,7 +148,8 @@ void cancel_providers(struct auth_client *auth) } /* Provider is done - WARNING: do not use auth instance after calling! */ -void provider_done(struct auth_client *auth, provider_t id) +void +provider_done(struct auth_client *auth, provider_t id) { rb_dlink_node *ptr; struct auth_provider *provider; @@ -170,7 +176,8 @@ void provider_done(struct auth_client *auth, provider_t id) } /* Reject a client - WARNING: do not use auth instance after calling! */ -void reject_client(struct auth_client *auth, provider_t id, const char *reason) +void +reject_client(struct auth_client *auth, provider_t id, const char *reason) { char reject; @@ -201,7 +208,8 @@ void reject_client(struct auth_client *auth, provider_t id, const char *reason) } /* Accept a client, cancel outstanding providers if any - WARNING: do nto use auth instance after calling! */ -void accept_client(struct auth_client *auth, provider_t id) +void +accept_client(struct auth_client *auth, provider_t id) { uint32_t cid = auth->cid; @@ -212,7 +220,8 @@ void accept_client(struct auth_client *auth, provider_t id) } /* Begin authenticating user */ -static void start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_ip, const char *c_port) +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)); @@ -280,7 +289,8 @@ static void start_auth(const char *cid, const char *l_ip, const char *l_port, co } /* Callback for the initiation */ -void handle_new_connection(int parc, char *parv[]) +void +handle_new_connection(int parc, char *parv[]) { if(parc < 6) { @@ -290,3 +300,30 @@ void handle_new_connection(int parc, char *parv[]) start_auth(parv[1], parv[2], parv[3], parv[4], parv[5]); } + +void +handle_cancel_connection(int parc, char *parv[]) +{ + struct auth_client *auth; + long lcid; + + if(parc < 2) + { + warn_opers(L_CRIT, "BUG: received too few params for new connection (2 expected, got %d)", parc); + return; + } + + if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX) + { + warn_opers(L_CRIT, "BUG: got a request to cancel a connection that can't exist: %lx", lcid); + return; + } + + if((auth = rb_dictionary_retrieve(auth_clients, RB_UINT_TO_POINTER((uint32_t)lcid))) == NULL) + { + warn_opers(L_CRIT, "BUG: tried to cancel nonexistent connection %lx", lcid); + return; + } + + cancel_providers(auth); +} diff --git a/authd/provider.h b/authd/provider.h index 348788ec..a9e99e2c 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -100,32 +100,38 @@ void accept_client(struct auth_client *auth, provider_t id); void reject_client(struct auth_client *auth, provider_t id, const char *reason); void handle_new_connection(int parc, char *parv[]); +void handle_cancel_connection(int parc, char *parv[]); /* Provider is operating on this auth_client (set this if you have async work to do) */ -static inline void set_provider_on(struct auth_client *auth, provider_t provider) +static inline void +set_provider_on(struct auth_client *auth, provider_t provider) { auth->providers |= (1 << provider); } /* Provider is no longer operating on this auth client (you should use provider_done) */ -static inline void set_provider_off(struct auth_client *auth, provider_t provider) +static inline void +set_provider_off(struct auth_client *auth, provider_t provider) { auth->providers &= ~(1 << provider); } /* Set the provider to done (you should use provider_done) */ -static inline void set_provider_done(struct auth_client *auth, provider_t provider) +static inline void +set_provider_done(struct auth_client *auth, provider_t provider) { auth->providers_done |= (1 << provider); } /* Check if provider is operating on this auth client */ -static inline bool is_provider_on(struct auth_client *auth, provider_t provider) +static inline bool +is_provider_on(struct auth_client *auth, provider_t provider) { return auth->providers & (1 << provider); } -static inline bool is_provider_done(struct auth_client *auth, provider_t provider) +static inline bool +is_provider_done(struct auth_client *auth, provider_t provider) { return auth->providers_done & (1 << provider); } From 6535177fef2f782593f2f95bf5d2ca709dd46e2d Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sun, 27 Mar 2016 13:52:52 -0500 Subject: [PATCH 78/96] authd/provider: add data to rejection tag. This is used for information such as what blacklist rejected the client. --- authd/provider.c | 13 ++++++++----- authd/provider.h | 2 +- authd/providers/blacklist.c | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index fcd9490a..941e4059 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -115,7 +115,7 @@ destroy_providers(void) RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) { /* TBD - is this the right thing? */ - reject_client(auth, 0, "Authentication system is down... try reconnecting in a few seconds"); + reject_client(auth, -1, "destroy", "Authentication system is down... try reconnecting in a few seconds"); } RB_DLINK_FOREACH(ptr, auth_providers.head) @@ -161,7 +161,7 @@ provider_done(struct auth_client *auth, provider_t id) { if(!auth->providers_starting) /* Only do this when there are no providers left */ - accept_client(auth, 0); + accept_client(auth, -1); return; } @@ -177,7 +177,7 @@ provider_done(struct auth_client *auth, provider_t id) /* Reject a client - WARNING: do not use auth instance after calling! */ void -reject_client(struct auth_client *auth, provider_t id, const char *reason) +reject_client(struct auth_client *auth, provider_t id, const char *data, const char *reason) { char reject; @@ -197,11 +197,14 @@ reject_client(struct auth_client *auth, provider_t id, const char *reason) break; } + if(data == NULL) + data = "*"; + /* We send back username and hostname in case ircd wants to overrule our decision. * In the future this may not be the case. * --Elizafox */ - rb_helper_write(authd_helper, "R %x %c %s %s :%s", auth->cid, reject, auth->username, auth->hostname, reason); + rb_helper_write(authd_helper, "R %x %c %s %s %s :%s", auth->cid, reject, auth->username, auth->hostname, data, reason); set_provider_off(auth, id); cancel_providers(auth); @@ -285,7 +288,7 @@ start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_ /* If no providers are running, accept the client */ if(!auth->providers) - accept_client(auth, 0); + accept_client(auth, -1); } /* Callback for the initiation */ diff --git a/authd/provider.h b/authd/provider.h index a9e99e2c..3c2773cc 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -97,7 +97,7 @@ void cancel_providers(struct auth_client *auth); void provider_done(struct auth_client *auth, provider_t id); void accept_client(struct auth_client *auth, provider_t id); -void reject_client(struct auth_client *auth, provider_t id, const char *reason); +void reject_client(struct auth_client *auth, provider_t id, const char *data, const char *reason); void handle_new_connection(int parc, char *parv[]); void handle_cancel_connection(int parc, char *parv[]); diff --git a/authd/providers/blacklist.c b/authd/providers/blacklist.c index c05cb630..c738b438 100644 --- a/authd/providers/blacklist.c +++ b/authd/providers/blacklist.c @@ -246,7 +246,7 @@ blacklist_dns_callback(const char *result, bool status, query_type type, void *d { /* Match found, so proceed no further */ blacklists_cancel(auth); - reject_client(auth, PROVIDER_BLACKLIST, bl->reason); + reject_client(auth, PROVIDER_BLACKLIST, bl->host, bl->reason); return; } From eccc44ed7b4fad9c7f581cd642fd50c4a04d5e91 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sun, 27 Mar 2016 14:41:50 -0500 Subject: [PATCH 79/96] authd/providers/blacklist: use uint8_t for iptype This clearly illustrates what it is --- authd/providers/blacklist.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/authd/providers/blacklist.c b/authd/providers/blacklist.c index c738b438..03bc7cab 100644 --- a/authd/providers/blacklist.c +++ b/authd/providers/blacklist.c @@ -58,7 +58,7 @@ struct blacklist { char host[IRCD_RES_HOSTLEN + 1]; char reason[BUFSIZE]; /* Reason template (ircd fills in the blanks) */ - unsigned char iptype; /* IP types supported */ + uint8_t iptype; /* IP types supported */ rb_dlink_list filters; /* Filters for queries */ bool delete; /* If true delete when no clients */ @@ -102,7 +102,7 @@ static void blacklists_cancel(struct auth_client *); /* private interfaces */ static void unref_blacklist(struct blacklist *); -static struct blacklist *new_blacklist(const char *, const char *, unsigned char, rb_dlink_list *); +static struct blacklist *new_blacklist(const char *, const char *, uint8_t, rb_dlink_list *); static struct blacklist *find_blacklist(const char *); static bool blacklist_check_reply(struct blacklist_lookup *, const char *); static void blacklist_dns_callback(const char *, bool, query_type, void *); @@ -136,7 +136,7 @@ unref_blacklist(struct blacklist *bl) } static struct blacklist * -new_blacklist(const char *name, const char *reason, unsigned char iptype, rb_dlink_list *filters) +new_blacklist(const char *name, const char *reason, uint8_t iptype, rb_dlink_list *filters) { struct blacklist *bl; @@ -442,7 +442,7 @@ add_conf_blacklist(const char *key, int parc, const char **parv) { rb_dlink_list filters = { NULL, NULL, 0 }; char *tmp, *elemlist = rb_strdup(parv[2]); - unsigned char iptype; + uint8_t iptype; if(*elemlist == '*') goto end; From 02e141f7a3c7cfff57cccd5f721fb9352b78531d Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sun, 27 Mar 2016 17:04:14 -0500 Subject: [PATCH 80/96] authd: add stats reporting API --- authd/dns.c | 19 ++++++++++++------- authd/notice.c | 40 ++++++++++++++++++++++++++++++++++++++-- authd/notice.h | 3 +++ 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/authd/dns.c b/authd/dns.c index 19b3efcb..487979fe 100644 --- a/authd/dns.c +++ b/authd/dns.c @@ -20,6 +20,7 @@ #include "authd.h" #include "dns.h" +#include "notice.h" #include "res.h" static void handle_lookup_ip_reply(void *data, struct DNSReply *reply); @@ -255,35 +256,39 @@ enumerate_nameservers(const char *rid, const char letter) { char buf[(HOSTIPLEN + 1) * IRCD_MAXNS]; char *c = buf; - int i; + size_t s = 0; + uint32_t i_rid = (uint32_t)strtol(rid, NULL, 16); if (!irc_nscount) { /* Shouldn't happen */ - rb_helper_write(authd_helper, "X %s %c NONAMESERVERS", rid, letter); + stats_error(i_rid, letter, "NONAMESERVERS"); return; } - for(i = 0; i < irc_nscount; i++) + for(int i = 0; i < irc_nscount; i++) { char addr[HOSTIPLEN]; + size_t addrlen; rb_inet_ntop_sock((struct sockaddr *)&irc_nsaddr_list[i], addr, sizeof(addr)); if (!addr[0]) { /* Shouldn't happen */ - rb_helper_write(authd_helper, "X %s %c INVALIDNAMESERVER", rid, letter); + stats_error(i_rid, letter, "INVALIDNAMESERVER"); return; } - (void)snprintf(c, HOSTIPLEN + 1, "%s ", addr); - c += strlen(addr) + 1; + addrlen = strlen(addr) + 1; + (void)snprintf(c, sizeof(buf) - s, "%s ", addr); + c += addrlen; + s += addrlen; } *(--c) = '\0'; - rb_helper_write(authd_helper, "Y %s %c %s", rid, letter, buf); + stats_result(i_rid, letter, "%s", buf); } void diff --git a/authd/notice.c b/authd/notice.c index 3e1d3f8a..76e231c2 100644 --- a/authd/notice.c +++ b/authd/notice.c @@ -22,7 +22,8 @@ #include "notice.h" /* Send a notice to a client */ -void notice_client(uint32_t cid, const char *fmt, ...) +void +notice_client(uint32_t cid, const char *fmt, ...) { char buf[BUFSIZE]; va_list args; @@ -35,7 +36,8 @@ void notice_client(uint32_t cid, const char *fmt, ...) } /* Send a warning to the IRC daemon for logging, etc. */ -void warn_opers(notice_level_t level, const char *fmt, ...) +void +warn_opers(notice_level_t level, const char *fmt, ...) { char buf[BUFSIZE]; va_list args; @@ -46,3 +48,37 @@ void warn_opers(notice_level_t level, const char *fmt, ...) rb_helper_write(authd_helper, "W %c :%s", level, buf); } + +/* Send a stats result */ +void +stats_result(uint32_t cid, char letter, const char *fmt, ...) +{ + char buf[BUFSIZE]; + va_list args; + + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + rb_helper_write(authd_helper, "Y %x %c %s", cid, letter, buf); +} + +/* Send a stats error */ +void +stats_error(uint32_t cid, char letter, const char *fmt, ...) +{ + char buf[BUFSIZE]; + va_list args; + + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + rb_helper_write(authd_helper, "X %x %c %s", cid, letter, buf); +} + +void +stats_done(uint32_t cid, char letter) +{ + rb_helper_write(authd_helper, "Z %x %c", cid, letter); +} diff --git a/authd/notice.h b/authd/notice.h index 1e48bccf..5a4349ab 100644 --- a/authd/notice.h +++ b/authd/notice.h @@ -31,5 +31,8 @@ typedef enum void notice_client(uint32_t cid, const char *fmt, ...); void warn_opers(notice_level_t level, const char *fmt, ...); +void stats_result(uint32_t cid, char letter, const char *fmt, ...); +void stats_error(uint32_t cid, char letter, const char *fmt, ...); +void stats_done(uint32_t cid, char letter); #endif /* __CHARYBDIS_AUTHD_NOTICE_H__ */ From ee7f92714ad53c5bc362447fc98670d873863411 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sun, 27 Mar 2016 17:15:08 -0500 Subject: [PATCH 81/96] authd/provider: add stats handling hooking --- authd/provider.c | 7 +++++++ authd/provider.h | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/authd/provider.c b/authd/provider.c index 941e4059..b512b4a0 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -74,6 +74,9 @@ load_provider(struct auth_provider *provider) rb_dictionary_add(authd_option_handlers, handler->option, handler); } + if(provider->stats_handler.letter != '\0') + authd_stat_handlers[provider->stats_handler.letter] = provider->stats_handler.handler; + provider->init(); rb_dlinkAdd(provider, &provider->node, &auth_providers); } @@ -88,6 +91,10 @@ unload_provider(struct auth_provider *provider) for(handler = provider->opt_handlers; handler->option != NULL; handler++) rb_dictionary_delete(authd_option_handlers, handler->option); } + + if(provider->stats_handler.letter != '\0') + authd_stat_handlers[provider->stats_handler.letter] = NULL; + provider->destroy(); rb_dlinkDelete(&provider->node, &auth_providers); } diff --git a/authd/provider.h b/authd/provider.h index 3c2773cc..c5462c93 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -65,6 +65,12 @@ typedef bool (*provider_start_t)(struct auth_client *); typedef void (*provider_cancel_t)(struct auth_client *); typedef void (*provider_complete_t)(struct auth_client *, provider_t); +struct auth_stats_handler +{ + const char letter; + authd_stat_handler handler; +}; + struct auth_provider { rb_dlink_node node; @@ -78,6 +84,8 @@ struct auth_provider provider_cancel_t cancel; /* Authentication cancelled */ provider_complete_t completed; /* Callback for when other performers complete (think dependency chains) */ + struct auth_stats_handler stats_handler; + struct auth_opts_handler *opt_handlers; }; From 26d491b95fce9be22a72f498907dcaccbcb20b15 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sun, 27 Mar 2016 17:28:26 -0500 Subject: [PATCH 82/96] authd: pass in uint32_t rid's. --- authd/authd.c | 9 ++++++++- authd/authd.h | 2 +- authd/dns.c | 16 +++++++--------- authd/dns.h | 2 +- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/authd/authd.c b/authd/authd.c index 6f500a9d..8aabf267 100644 --- a/authd/authd.c +++ b/authd/authd.c @@ -53,6 +53,7 @@ static void handle_stat(int parc, char *parv[]) { authd_stat_handler handler; + long lrid; if(parc < 3) { @@ -60,10 +61,16 @@ handle_stat(int parc, char *parv[]) return; } + if((lrid = strtol(parv[1], NULL, 16)) > UINT32_MAX) + { + warn_opers(L_CRIT, "BUG: handle_stat got a rid that was too large: %lx", lrid); + return; + } + if (!(handler = authd_stat_handlers[(unsigned char)parv[2][0]])) return; - handler(parv[1], parv[2][0]); + handler((uint32_t)lrid, parv[2][0]); } static void diff --git a/authd/authd.h b/authd/authd.h index 07c746ca..43901dc0 100644 --- a/authd/authd.h +++ b/authd/authd.h @@ -40,7 +40,7 @@ struct auth_opts_handler extern rb_helper *authd_helper; typedef void (*authd_cmd_handler)(int parc, char *parv[]); -typedef void (*authd_stat_handler)(const char *rid, const char letter); +typedef void (*authd_stat_handler)(uint32_t rid, const char letter); typedef void (*authd_reload_handler)(const char letter); extern authd_cmd_handler authd_cmd_handlers[256]; diff --git a/authd/dns.c b/authd/dns.c index 487979fe..7d6d9472 100644 --- a/authd/dns.c +++ b/authd/dns.c @@ -252,17 +252,15 @@ handle_resolve_dns(int parc, char *parv[]) } void -enumerate_nameservers(const char *rid, const char letter) +enumerate_nameservers(uint32_t rid, const char letter) { char buf[(HOSTIPLEN + 1) * IRCD_MAXNS]; - char *c = buf; size_t s = 0; - uint32_t i_rid = (uint32_t)strtol(rid, NULL, 16); if (!irc_nscount) { /* Shouldn't happen */ - stats_error(i_rid, letter, "NONAMESERVERS"); + stats_error(rid, letter, "NONAMESERVERS"); return; } @@ -276,19 +274,19 @@ enumerate_nameservers(const char *rid, const char letter) if (!addr[0]) { /* Shouldn't happen */ - stats_error(i_rid, letter, "INVALIDNAMESERVER"); + stats_error(rid, letter, "INVALIDNAMESERVER"); return; } addrlen = strlen(addr) + 1; - (void)snprintf(c, sizeof(buf) - s, "%s ", addr); - c += addrlen; + (void)snprintf(&buf[s], sizeof(buf) - s, "%s ", addr); s += addrlen; } - *(--c) = '\0'; + if(s > 0) + buf[--s] = '\0'; - stats_result(i_rid, letter, "%s", buf); + stats_result(rid, letter, "%s", buf); } void diff --git a/authd/dns.h b/authd/dns.h index b4eae8c6..7383ab69 100644 --- a/authd/dns.h +++ b/authd/dns.h @@ -55,7 +55,7 @@ extern struct dns_query *lookup_ip(const char *host, int aftype, DNSCB callback, extern void cancel_query(struct dns_query *query); extern void handle_resolve_dns(int parc, char *parv[]); -extern void enumerate_nameservers(const char *rid, const char letter); +extern void enumerate_nameservers(uint32_t rid, const char letter); extern void reload_nameservers(const char letter); #endif From 54fb109d82db131d80e71a30b9d1214fbe53bf54 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Sun, 27 Mar 2016 23:57:06 -0500 Subject: [PATCH 83/96] authd/providers/ident: add conf option for enabling ident --- authd/providers/ident.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/authd/providers/ident.c b/authd/providers/ident.c index e14fac43..935c8bf1 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -66,6 +66,7 @@ static char * get_valid_ident(char *buf); static struct ev_entry *timeout_ev; static int ident_timeout = 5; +static bool ident_enable = true; /* Timeout outstanding queries */ @@ -320,8 +321,11 @@ static bool ident_start(struct auth_client *auth) struct rb_sockaddr_storage l_addr, c_addr; int family = GET_SS_FAMILY(&auth->c_addr); - if(auth->data[PROVIDER_IDENT] != NULL) + if(!ident_enable || auth->data[PROVIDER_IDENT] != NULL) + { + set_provider_done(auth, PROVIDER_IDENT); /* for blacklists */ return true; + } notice_client(auth->cid, messages[REPORT_LOOKUP]); @@ -387,9 +391,18 @@ add_conf_ident_timeout(const char *key __unused, int parc __unused, const char * ident_timeout = timeout; } +static void +set_ident_enabled(const char *key __unused, int parc __unused, const char **parv) +{ + enable_ident = (strcasecmp(parv[0], "true") == 0 || + strcasecmp(parv[0], "1") == 0 || + strcasecmp(parv[0], "enable") == 0); +} + struct auth_opts_handler ident_options[] = { { "ident_timeout", 1, add_conf_ident_timeout }, + { "ident_enabled", 1, set_ident_enabled }, { NULL, 0, NULL }, }; From 8e001551648cff1813059455329fc39fbe61187a Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Mon, 28 Mar 2016 00:03:27 -0500 Subject: [PATCH 84/96] authd/providers/ident: fix typo --- authd/providers/ident.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/authd/providers/ident.c b/authd/providers/ident.c index 935c8bf1..5f7740b5 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -394,7 +394,7 @@ add_conf_ident_timeout(const char *key __unused, int parc __unused, const char * static void set_ident_enabled(const char *key __unused, int parc __unused, const char **parv) { - enable_ident = (strcasecmp(parv[0], "true") == 0 || + ident_enable = (strcasecmp(parv[0], "true") == 0 || strcasecmp(parv[0], "1") == 0 || strcasecmp(parv[0], "enable") == 0); } From a90465f76738b55103dcbc85d7b0233cef0f0349 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Mon, 28 Mar 2016 01:05:19 -0500 Subject: [PATCH 85/96] authd/providers/blacklist: add stats reporting for blacklist info --- authd/providers/blacklist.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/authd/providers/blacklist.c b/authd/providers/blacklist.c index 03bc7cab..922d4b2c 100644 --- a/authd/providers/blacklist.c +++ b/authd/providers/blacklist.c @@ -63,6 +63,7 @@ struct blacklist bool delete; /* If true delete when no clients */ int refcount; /* When 0 and delete is set, remove this blacklist */ + unsigned int hits; time_t lastwarning; /* Last warning about garbage replies sent */ }; @@ -81,7 +82,7 @@ struct blacklist_lookup struct blacklist_filter { filter_t type; /* Type of filter */ - char filter[HOSTIPLEN]; /* The filter itself */ + char filter[HOSTIPLEN]; /* The filter itself */ rb_dlink_node node; }; @@ -245,6 +246,7 @@ blacklist_dns_callback(const char *result, bool status, query_type type, void *d if (result != NULL && status && blacklist_check_reply(bllookup, result)) { /* Match found, so proceed no further */ + bl->hits++; blacklists_cancel(auth); reject_client(auth, PROVIDER_BLACKLIST, bl->host, bl->reason); return; @@ -544,6 +546,24 @@ add_conf_blacklist_timeout(const char *key, int parc, const char **parv) blacklist_timeout = timeout; } +static void +blacklist_stats(uint32_t rid, char letter) +{ + rb_dlink_node *ptr; + + RB_DLINK_FOREACH(ptr, blacklist_list.head) + { + struct blacklist *bl = ptr->data; + + if(bl->delete) + continue; + + stats_result(rid, letter, "%s %hhu %u", bl->host, bl->iptype, bl->hits); + } + + stats_done(rid, letter); +} + struct auth_opts_handler blacklist_options[] = { { "rbl", 4, add_conf_blacklist }, @@ -562,4 +582,5 @@ struct auth_provider blacklist_provider = .cancel = blacklists_cancel, .completed = blacklists_initiate, .opt_handlers = blacklist_options, + .stats_handler = { 'B', blacklist_stats }, }; From bd7c2037bff076f977b0d119a8d75987e273ecd2 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Mon, 28 Mar 2016 01:55:54 -0500 Subject: [PATCH 86/96] authd/providers/rdns: change option name to rdns_timeout --- authd/providers/rdns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/authd/providers/rdns.c b/authd/providers/rdns.c index e5e1f6dd..e4f2430e 100644 --- a/authd/providers/rdns.c +++ b/authd/providers/rdns.c @@ -189,7 +189,7 @@ add_conf_dns_timeout(const char *key, int parc, const char **parv) struct auth_opts_handler rdns_options[] = { - { "dns_timeout", 1, add_conf_dns_timeout }, + { "rdns_timeout", 1, add_conf_dns_timeout }, { NULL, 0, NULL }, }; From d3f6b808677ba8bd3fa48f9bd61b99a2292a8c3e Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Mon, 28 Mar 2016 02:11:16 -0500 Subject: [PATCH 87/96] Replace s_auth/blacklist stuff with authd calls This also does a lot of surgery on the conf system to reconfigure authd. /!\ WARNING! ACHTUNG! ADVERTENCIA! ATTENTION! AVVERTIMENTO! /!\ This code has not been run-time tested yet (though it compiles)! --- include/authd.h | 23 ++ include/blacklist.h | 68 ----- include/client.h | 28 +- include/s_auth.h | 34 --- ircd/Makefile.am | 2 - ircd/authd.c | 334 ++++++++++++++++++++++-- ircd/blacklist.c | 306 ---------------------- ircd/client.c | 21 +- ircd/ircd.c | 4 +- ircd/listener.c | 4 +- ircd/newconf.c | 66 ++--- ircd/s_auth.c | 607 -------------------------------------------- ircd/s_conf.c | 3 +- ircd/s_user.c | 104 +++++--- modules/m_set.c | 1 + modules/m_stats.c | 84 +++--- modules/m_user.c | 2 - 17 files changed, 502 insertions(+), 1189 deletions(-) delete mode 100644 include/blacklist.h delete mode 100644 include/s_auth.h delete mode 100644 ircd/blacklist.c delete mode 100644 ircd/s_auth.c diff --git a/include/authd.h b/include/authd.h index 276d6fa8..03405958 100644 --- a/include/authd.h +++ b/include/authd.h @@ -26,11 +26,34 @@ #ifndef CHARYBDIS_AUTHD_H #define CHARYBDIS_AUTHD_H +#include "stdinc.h" +#include "rb_dictionary.h" +#include "client.h" + +struct blacklist_stats +{ + uint8_t iptype; + unsigned int hits; +}; + extern rb_helper *authd_helper; +extern rb_dictionary *bl_stats; + void init_authd(void); +void configure_authd(void); void restart_authd(void); void rehash_authd(void); void check_authd(void); +void authd_initiate_client(struct Client *); +void authd_decide_client(struct Client *client_p, const char *ident, const char *host, bool accept, char cause, const char *data, const char *reason); +void authd_abort_client(struct Client *); +const char *get_provider_string(char cause); + +void add_blacklist(const char *host, const char *reason, uint8_t iptype, rb_dlink_list *filters); +void del_blacklist(const char *host); +void del_blacklist_all(void); +void set_authd_timeout(const char *key, int timeout); + #endif diff --git a/include/blacklist.h b/include/blacklist.h deleted file mode 100644 index 7c8fc23e..00000000 --- a/include/blacklist.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * charybdis: A slightly useful ircd. - * blacklist.h: Manages DNS blacklist entries and lookups - * - * Copyright (C) 2006 charybdis development team - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef _BLACKLIST_H_ -#define _BLACKLIST_H_ - -#include "stdinc.h" - -#define BLACKLIST_FILTER_ALL 1 -#define BLACKLIST_FILTER_LAST 2 - -/* A configured DNSBL */ -struct Blacklist { - unsigned int status; /* If CONF_ILLEGAL, delete when no clients */ - int refcount; - int ipv4; /* Does this blacklist support IPv4 lookups? */ - int ipv6; /* Does this blacklist support IPv6 lookups? */ - char host[IRCD_RES_HOSTLEN + 1]; - rb_dlink_list filters; /* Filters for queries */ - char reject_reason[BUFSIZE]; - unsigned int hits; - time_t lastwarning; -}; - -/* A lookup in progress for a particular DNSBL for a particular client */ -struct BlacklistClient { - struct Blacklist *blacklist; - struct Client *client_p; - uint16_t dns_id; - rb_dlink_node node; -}; - -/* A blacklist filter */ -struct BlacklistFilter { - int type; /* Type of filter */ - char filterstr[HOSTIPLEN]; /* The filter itself */ - rb_dlink_node node; -}; - -/* public interfaces */ -struct Blacklist *new_blacklist(char *host, char *reject_reason, int ipv4, int ipv6, rb_dlink_list *filters); -void lookup_blacklists(struct Client *client_p); -void abort_blacklist_queries(struct Client *client_p); -void unref_blacklist(struct Blacklist *blptr); -void destroy_blacklists(void); - -extern rb_dlink_list blacklist_list; - -#endif diff --git a/include/client.h b/include/client.h index b9a612bf..ee2c5969 100644 --- a/include/client.h +++ b/include/client.h @@ -63,7 +63,6 @@ struct Client; struct User; struct Server; struct LocalUser; -struct AuthRequest; struct PreClient; struct ListClient; struct scache_entry; @@ -190,6 +189,7 @@ struct LocalUser /* Send and receive linebuf queues .. */ buf_head_t buf_sendq; buf_head_t buf_recvq; + /* * we want to use unsigned int here so the sizes have a better chance of * staying the same on 64 bit machines. The current trend is to use @@ -199,13 +199,15 @@ struct LocalUser * performed on these, it's not safe to allow them to become negative, * which is possible for long running server connections. Unsigned values * generally overflow gracefully. --Bleep + * + * We have modern conveniences. Let's use uint32_t. --Elizafox */ - unsigned int sendM; /* Statistics: protocol messages send */ - unsigned int sendK; /* Statistics: total k-bytes send */ - unsigned int receiveM; /* Statistics: protocol messages received */ - unsigned int receiveK; /* Statistics: total k-bytes received */ - unsigned short sendB; /* counters to count upto 1-k lots of bytes */ - unsigned short receiveB; /* sent and received. */ + uint32_t sendM; /* Statistics: protocol messages send */ + uint32_t sendK; /* Statistics: total k-bytes send */ + uint32_t receiveM; /* Statistics: protocol messages received */ + uint32_t receiveK; /* Statistics: total k-bytes received */ + uint16_t sendB; /* counters to count upto 1-k lots of bytes */ + uint16_t receiveB; /* sent and received. */ struct Listener *listener; /* listener accepted from */ struct ConfItem *att_conf; /* attached conf */ struct server_conf *att_sconf; @@ -251,7 +253,6 @@ struct LocalUser int sent_parsed; /* how many messages we've parsed in this second */ time_t last_knock; /* time of last knock */ unsigned long random_ping; - struct AuthRequest *auth_request; /* target change stuff */ /* targets we're aware of (fnv32(use_id(target_p))): @@ -291,8 +292,12 @@ struct PreClient char spoofuser[USERLEN + 1]; char spoofhost[HOSTLEN + 1]; - rb_dlink_list dnsbl_queries; /* list of struct BlacklistClient * */ - struct Blacklist *dnsbl_listed; /* first dnsbl where it's listed */ + uint32_t authd_cid; /* authd id */ + time_t authd_timeout; /* When to terminate authd query */ + bool authd_accepted; /* did authd accept us? */ + char authd_cause; /* rejection cause */ + char *authd_data; /* reason data */ + char *authd_reason; /* reason we were rejected */ struct rb_sockaddr_storage lip; /* address of our side of the connection */ }; @@ -574,8 +579,6 @@ extern int exit_client(struct Client *, struct Client *, struct Client *, const extern void error_exit_client(struct Client *, int); - - extern void count_local_client_memory(size_t * count, size_t * memory); extern void count_remote_client_memory(size_t * count, size_t * memory); @@ -594,7 +597,6 @@ extern int show_ip(struct Client *source_p, struct Client *target_p); extern int show_ip_conf(struct ConfItem *aconf, struct Client *source_p); extern int show_ip_whowas(struct Whowas *whowas, struct Client *source_p); -extern void initUser(void); extern void free_user(struct User *, struct Client *); extern struct User *make_user(struct Client *); extern struct Server *make_server(struct Client *); diff --git a/include/s_auth.h b/include/s_auth.h deleted file mode 100644 index bbc20b7f..00000000 --- a/include/s_auth.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * ircd-ratbox: A slightly useful ircd. - * s_auth.h: A header for the ident functions. - * - * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2002-2004 ircd-ratbox development team - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef INCLUDED_s_auth_h -#define INCLUDED_s_auth_h - -struct Client; - -extern void start_auth(struct Client *); -extern void init_auth(void); -extern void delete_auth_queries(struct Client *); - -#endif /* INCLUDED_s_auth_h */ diff --git a/ircd/Makefile.am b/ircd/Makefile.am index 20370488..b1f6011d 100644 --- a/ircd/Makefile.am +++ b/ircd/Makefile.am @@ -21,7 +21,6 @@ endif libircd_la_SOURCES = \ authd.c \ bandbi.c \ - blacklist.c \ cache.c \ capability.c \ channel.c \ @@ -53,7 +52,6 @@ libircd_la_SOURCES = \ ratelimit.c \ reject.c \ restart.c \ - s_auth.c \ s_conf.c \ s_newconf.c \ s_serv.c \ diff --git a/ircd/authd.c b/ircd/authd.c index 8b453393..cfbbb52f 100644 --- a/ircd/authd.c +++ b/ircd/authd.c @@ -22,20 +22,23 @@ * USA */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "stdinc.h" +#include "rb_lib.h" +#include "client.h" +#include "ircd_defs.h" +#include "parse.h" +#include "authd.h" +#include "match.h" +#include "logger.h" +#include "s_conf.h" +#include "s_stats.h" +#include "client.h" +#include "packet.h" +#include "hash.h" +#include "send.h" +#include "numeric.h" +#include "msg.h" +#include "dns.h" static int start_authd(void); static void parse_authd_reply(rb_helper * helper); @@ -44,6 +47,11 @@ static void restart_authd_cb(rb_helper * helper); rb_helper *authd_helper; static char *authd_path; +uint32_t cid = 1; +static rb_dictionary *cid_clients; + +rb_dictionary *bl_stats; + static int start_authd(void) { @@ -77,6 +85,12 @@ start_authd(void) authd_path = rb_strdup(fullpath); } + if(cid_clients == NULL) + cid_clients = rb_dictionary_create("authd cid to uid mapping", rb_uint32cmp); + + if(bl_stats == NULL) + bl_stats = rb_dictionary_create("blacklist statistics", strcasecmp); + authd_helper = rb_helper_start("authd", authd_path, parse_authd_reply, restart_authd_cb); if(authd_helper == NULL) @@ -98,6 +112,9 @@ parse_authd_reply(rb_helper * helper) int parc; char dnsBuf[READBUF_SIZE]; char *parv[MAXPARA + 1]; + long lcid; + char *id; + struct Client *client_p; while((len = rb_helper_read(helper, dnsBuf, sizeof(dnsBuf))) > 0) { @@ -105,7 +122,75 @@ parse_authd_reply(rb_helper * helper) switch (*parv[0]) { - case 'E': + case 'A': /* Accepted a client */ + if(parc != 4) + { + iwarn("authd sent a result with wrong number of arguments: got %d", parc); + restart_authd(); + return; + } + + if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX) + { + iwarn("authd sent us back a bad client ID"); + restart_authd(); + return; + } + + /* cid to uid (retrieve and delete) */ + if((id = rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER((uint32_t)lcid))) == NULL) + { + iwarn("authd sent us back an unknown client ID"); + restart_authd(); + return; + } + + if((client_p = find_id(id)) == NULL) + { + /* Client vanished... */ + rb_free(id); + return; + } + + rb_free(id); + + authd_decide_client(client_p, parv[2], parv[3], true, '\0', NULL, NULL); + break; + case 'R': /* Reject client */ + if(parc != 7) + { + iwarn("authd sent us a result with wrong number of arguments: got %d", parc); + restart_authd(); + return; + } + + if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX) + { + iwarn("authd sent us back a bad client ID"); + restart_authd(); + return; + } + + /* cid to uid (retrieve and delete) */ + if((id = rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER((uint32_t)lcid))) == NULL) + { + iwarn("authd sent us back an unknown client ID"); + restart_authd(); + return; + } + + if((client_p = find_id(id)) == NULL) + { + /* Client vanished... */ + rb_free(id); + return; + } + + rb_free(id); + + authd_decide_client(client_p, parv[3], parv[4], false, toupper(*parv[2]), parv[5], parv[6]); + return; + case 'E': /* DNS Result */ if(parc != 5) { ilog(L_MAIN, "authd sent a result with wrong number of arguments: got %d", parc); @@ -114,7 +199,7 @@ parse_authd_reply(rb_helper * helper) } dns_results_callback(parv[1], parv[2], parv[3], parv[4]); break; - case 'W': + case 'W': /* Oper warning */ if(parc != 3) { ilog(L_MAIN, "authd sent a result with wrong number of arguments: got %d", parc); @@ -124,7 +209,7 @@ parse_authd_reply(rb_helper * helper) switch(*parv[2]) { - case 'D': /* debug */ + case 'D': /* Debug */ sendto_realops_snomask(SNO_DEBUG, L_ALL, "authd debug: %s", parv[3]); break; case 'I': /* Info */ @@ -147,9 +232,9 @@ parse_authd_reply(rb_helper * helper) /* NOTREACHED */ break; - case 'X': - case 'Y': - case 'Z': + case 'X': /* Stats error */ + case 'Y': /* Stats reply */ + case 'Z': /* End of stats reply */ if(parc < 3) { ilog(L_MAIN, "authd sent a result with wrong number of arguments: got %d", parc); @@ -190,6 +275,15 @@ init_authd(void) } } +void +configure_authd(void) +{ + /* These will do for now */ + set_authd_timeout("ident_timeout", GlobalSetOptions.ident_timeout); + set_authd_timeout("rdns_timeout", ConfigFileEntry.connect_timeout); + set_authd_timeout("blacklist_timeout", ConfigFileEntry.connect_timeout); +} + static void restart_authd_cb(rb_helper * helper) { @@ -213,6 +307,7 @@ void rehash_authd(void) { rb_helper_write(authd_helper, "R"); + configure_authd(); } void @@ -221,3 +316,202 @@ check_authd(void) if(authd_helper == NULL) restart_authd(); } + +static inline uint32_t +generate_cid(void) +{ + if(++cid == 0) + cid = 1; + + return cid; +} + +/* Basically when this is called we begin handing off the client to authd for + * processing. authd "owns" the client until processing is finished, or we + * timeout from authd. authd will make a decision whether or not to accept the + * client, but it's up to other parts of the code (for now) to decide if we're + * gonna accept the client and ignore authd's suggestion. + * + * --Elizafox + */ +void +authd_initiate_client(struct Client *client_p) +{ + char client_ipaddr[HOSTIPLEN+1]; + char listen_ipaddr[HOSTIPLEN+1]; + uint16_t client_port, listen_port; + uint32_t authd_cid; + + if(client_p->preClient == NULL || client_p->preClient->authd_cid == 0) + return; + + authd_cid = client_p->preClient->authd_cid = generate_cid(); + + /* Collisions are extremely unlikely, so disregard the possibility */ + rb_dictionary_add(cid_clients, RB_UINT_TO_POINTER(authd_cid), rb_strdup(client_p->id)); + + /* Retrieve listener and client IP's */ + rb_inet_ntop_sock((struct sockaddr *)&client_p->preClient->lip, listen_ipaddr, sizeof(listen_ipaddr)); + rb_inet_ntop_sock((struct sockaddr *)&client_p->localClient->ip, client_ipaddr, sizeof(client_ipaddr)); + + /* Retrieve listener and client ports */ +#ifdef RB_IPV6 + if(GET_SS_FAMILY(&client_p->preClient->lip) == AF_INET6) + listen_port = ntohs(((struct sockaddr_in6 *)&client_p->preClient->lip)->sin6_port); + else +#endif + listen_port = ntohs(((struct sockaddr_in *)&client_p->preClient->lip)->sin_port); + +#ifdef RB_IPV6 + if(GET_SS_FAMILY(&client_p->localClient->ip) == AF_INET6) + client_port = ntohs(((struct sockaddr_in6 *)&client_p->localClient->ip)->sin6_port); + else +#endif + client_port = ntohs(((struct sockaddr_in *)&client_p->localClient->ip)->sin_port); + + /* FIXME timeout should be configurable */ + client_p->preClient->authd_timeout = rb_current_time() + 45; + + rb_helper_write(authd_helper, "C %x %s %hu %s %hu", authd_cid, listen_ipaddr, listen_port, client_ipaddr, client_port); +} + +/* When this is called we have a decision on client acceptance. + * + * After this point authd no longer "owns" the client. + */ +void +authd_decide_client(struct Client *client_p, const char *ident, const char *host, bool accept, char cause, const char *data, const char *reason) +{ + if(client_p->preClient == NULL || client_p->preClient->authd_cid == 0) + return; + + if(*ident != '*') + { + rb_strlcpy(client_p->username, ident, sizeof(client_p->username)); + ServerStats.is_abad++; /* s_auth used to do this, stay compatible */ + } + else + ServerStats.is_asuc++; + + if(*host != '*') + rb_strlcpy(client_p->host, host, sizeof(client_p->host)); + + client_p->preClient->authd_accepted = accept; + client_p->preClient->authd_cause = cause; + client_p->preClient->authd_data = (data == NULL ? NULL : rb_strdup(data)); + client_p->preClient->authd_reason = (reason == NULL ? NULL : rb_strdup(reason)); + + rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(client_p->preClient->authd_cid)); + + client_p->preClient->authd_cid = 0; + + /* + * When a client has auth'ed, we want to start reading what it sends + * us. This is what read_packet() does. + * -- adrian + * + * Above comment was originally in s_auth.c, but moved here with below code. + * --Elizafox + */ + rb_dlinkAddTail(client_p, &client_p->node, &global_client_list); + read_packet(client_p->localClient->F, client_p); +} + +void +authd_abort_client(struct Client *client_p) +{ + if(client_p->preClient == NULL) + return; + + if(client_p->preClient->authd_cid == 0) + return; + + rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(client_p->preClient->authd_cid)); + + rb_helper_write(authd_helper, "E %x", client_p->preClient->authd_cid); + client_p->preClient->authd_cid = 0; +} + +/* Turn a cause char (who rejected us) into the name of the provider */ +const char * +get_provider_string(char cause) +{ + switch(cause) + { + case 'B': + return "Blacklist"; + case 'D': + return "rDNS"; + case 'I': + return "Ident"; + default: + return "Unknown"; + } +} + +/* Send a new blacklist to authd */ +void +add_blacklist(const char *host, const char *reason, uint8_t iptype, rb_dlink_list *filters) +{ + rb_dlink_node *ptr; + struct blacklist_stats *stats = rb_malloc(sizeof(struct blacklist_stats)); + char filterbuf[BUFSIZE]; + size_t s = 0; + + /* Build a list of comma-separated values for authd. + * We don't check for validity - do it elsewhere. + */ + RB_DLINK_FOREACH(ptr, filters->head) + { + char *filter = ptr->data; + size_t filterlen = strlen(filter) + 1; + + if(s + filterlen > sizeof(filterbuf)) + break; + + snprintf(&filterbuf[s], sizeof(filterbuf) - s, "%s,", filter); + + s += filterlen; + } + + if(s) + filterbuf[s - 1] = '\0'; + + stats->iptype = iptype; + stats->hits = 0; + rb_dictionary_add(bl_stats, host, stats); + + rb_helper_write(authd_helper, "O rbl %s %hhu %s :%s", host, iptype, filterbuf, reason); +} + +/* Delete a blacklist */ +void +del_blacklist(const char *host) +{ + rb_dictionary_delete(bl_stats, host); + + rb_helper_write(authd_helper, "O rbl_del %s", host); +} + +/* Delete all the blacklists */ +void +del_blacklist_all(void) +{ + struct blacklist_stats *stats; + rb_dictionary_iter iter; + + RB_DICTIONARY_FOREACH(stats, &iter, bl_stats) + { + rb_free(stats); + rb_dictionary_delete(bl_stats, iter.cur->key); + } + + rb_helper_write(authd_helper, "O rbl_del_all"); +} + +/* Adjust an authd timeout value */ +void +set_authd_timeout(const char *key, int timeout) +{ + rb_helper_write(authd_helper, "O %s %d", key, timeout); +} diff --git a/ircd/blacklist.c b/ircd/blacklist.c deleted file mode 100644 index 47438438..00000000 --- a/ircd/blacklist.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * charybdis: A slightly useful ircd. - * blacklist.c: Manages DNS blacklist entries and lookups - * - * Copyright (C) 2006-2011 charybdis development team - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "stdinc.h" -#include "client.h" -#include "dns.h" -#include "numeric.h" -#include "reject.h" -#include "s_conf.h" -#include "s_user.h" -#include "blacklist.h" -#include "send.h" - -rb_dlink_list blacklist_list = { NULL, NULL, 0 }; - -/* private interfaces */ -static struct Blacklist *find_blacklist(char *name) -{ - rb_dlink_node *nptr; - - RB_DLINK_FOREACH(nptr, blacklist_list.head) - { - struct Blacklist *blptr = (struct Blacklist *) nptr->data; - - if (!irccmp(blptr->host, name)) - return blptr; - } - - return NULL; -} - -static inline int blacklist_check_reply(struct BlacklistClient *blcptr, const char *ipaddr) -{ - struct Blacklist *blptr = blcptr->blacklist; - const char *lastoctet; - rb_dlink_node *ptr; - - /* No filters and entry found - thus positive match */ - if (!rb_dlink_list_length(&blptr->filters)) - return 1; - - /* Below will prolly have to change too if the above changes */ - if ((lastoctet = strrchr(ipaddr, '.')) == NULL || *(++lastoctet) == '\0') - goto blwarn; - - RB_DLINK_FOREACH(ptr, blcptr->blacklist->filters.head) - { - struct BlacklistFilter *filter = ptr->data; - const char *cmpstr; - - if (filter->type == BLACKLIST_FILTER_ALL) - cmpstr = ipaddr; - else if (filter->type == BLACKLIST_FILTER_LAST) - cmpstr = lastoctet; - else - { - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "blacklist_check_reply(): Unknown filtertype (BUG!)"); - continue; - } - - if (strcmp(cmpstr, filter->filterstr) == 0) - /* Match! */ - return 1; - } - - return 0; -blwarn: - if (blcptr->blacklist->lastwarning + 3600 < rb_current_time()) - { - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "Garbage reply from blacklist %s", - blcptr->blacklist->host); - blcptr->blacklist->lastwarning = rb_current_time(); - } - return 0; -} - -static void blacklist_dns_callback(const char *result, int status, int aftype, void *vptr) -{ - struct BlacklistClient *blcptr = (struct BlacklistClient *) vptr; - bool listed = false; - - if (blcptr == NULL || blcptr->client_p == NULL) - return; - - if (blcptr->client_p->preClient == NULL) - { - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "blacklist_dns_callback(): blcptr->client_p->preClient (%s) is NULL", get_client_name(blcptr->client_p, HIDE_IP)); - rb_free(blcptr); - return; - } - - if (result != NULL && status) - { - if (blacklist_check_reply(blcptr, result)) - listed = true; - } - - /* they have a blacklist entry for this client */ - if (listed && blcptr->client_p->preClient->dnsbl_listed == NULL) - { - blcptr->client_p->preClient->dnsbl_listed = blcptr->blacklist; - /* reference to blacklist moves from blcptr to client_p->preClient... */ - } - else - unref_blacklist(blcptr->blacklist); - - rb_dlinkDelete(&blcptr->node, &blcptr->client_p->preClient->dnsbl_queries); - - /* yes, it can probably happen... */ - if (rb_dlink_list_length(&blcptr->client_p->preClient->dnsbl_queries) == 0 && blcptr->client_p->flags & FLAGS_SENTUSER && !EmptyString(blcptr->client_p->name)) - register_local_user(blcptr->client_p, blcptr->client_p); - - rb_free(blcptr); -} - -static void initiate_blacklist_dnsquery(struct Blacklist *blptr, struct Client *client_p) -{ - struct BlacklistClient *blcptr = rb_malloc(sizeof(struct BlacklistClient)); - char buf[IRCD_RES_HOSTLEN + 1]; - uint8_t *ip; - - blcptr->blacklist = blptr; - blcptr->client_p = client_p; - - /* IPv4 */ - if ((GET_SS_FAMILY(&client_p->localClient->ip) == AF_INET) && blptr->ipv4) - { - ip = (uint8_t *)&((struct sockaddr_in *)&client_p->localClient->ip)->sin_addr.s_addr; - - /* becomes 2.0.0.127.torbl.ahbl.org or whatever */ - snprintf(buf, sizeof buf, "%d.%d.%d.%d.%s", - (unsigned int) ip[3], - (unsigned int) ip[2], - (unsigned int) ip[1], - (unsigned int) ip[0], - blptr->host); - } -#ifdef RB_IPV6 - /* IPv6 */ - else if ((GET_SS_FAMILY(&client_p->localClient->ip) == AF_INET6) && blptr->ipv6) - { - /* Split up for rDNS lookup - * ex: ip[0] = 0x00, ip[1] = 0x00... ip[16] = 0x01 for localhost - * Giving us: - * 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.foobl.invalid - * or something like that. - */ - ip = (uint8_t *)&((struct sockaddr_in6 *)&client_p->localClient->ip)->sin6_addr.s6_addr; - char *bufptr = buf; - int i; - - /* Going backwards */ - for (i = 15; i >= 0; i--, bufptr += 4) - { - /* Get upper and lower nibbles */ - uint8_t hi = (ip[i] >> 4) & 0x0F; - uint8_t lo = ip[i] & 0x0F; - - /* One part... 4 chars + terminator */ - snprintf(bufptr, 5, "%1x.%1x.", - (unsigned int) lo, /* Remember, backwards */ - (unsigned int) hi); - } - - /* Tack host on */ - strcpy(bufptr, blptr->host); - } -#endif - /* This shouldn't happen... */ - else - return; - - blcptr->dns_id = lookup_hostname(buf, AF_INET, blacklist_dns_callback, blcptr); - - rb_dlinkAdd(blcptr, &blcptr->node, &client_p->preClient->dnsbl_queries); - blptr->refcount++; -} - -/* public interfaces */ -struct Blacklist *new_blacklist(char *name, char *reject_reason, int ipv4, int ipv6, rb_dlink_list *filters) -{ - struct Blacklist *blptr; - - if (name == NULL || reject_reason == NULL) - return NULL; - - blptr = find_blacklist(name); - if (blptr == NULL) - { - blptr = rb_malloc(sizeof(struct Blacklist)); - rb_dlinkAddAlloc(blptr, &blacklist_list); - } - else - blptr->status &= ~CONF_ILLEGAL; - - rb_strlcpy(blptr->host, name, IRCD_RES_HOSTLEN + 1); - rb_strlcpy(blptr->reject_reason, reject_reason, BUFSIZE); - blptr->ipv4 = ipv4; - blptr->ipv6 = ipv6; - - rb_dlinkMoveList(filters, &blptr->filters); - - blptr->lastwarning = 0; - - return blptr; -} - -void unref_blacklist(struct Blacklist *blptr) -{ - rb_dlink_node *ptr, *next_ptr; - - blptr->refcount--; - if (blptr->status & CONF_ILLEGAL && blptr->refcount <= 0) - { - RB_DLINK_FOREACH_SAFE(ptr, next_ptr, blptr->filters.head) - { - rb_dlinkDelete(ptr, &blptr->filters); - rb_free(ptr); - } - - rb_dlinkFindDestroy(blptr, &blacklist_list); - rb_free(blptr); - } -} - -void lookup_blacklists(struct Client *client_p) -{ - rb_dlink_node *nptr; - - RB_DLINK_FOREACH(nptr, blacklist_list.head) - { - struct Blacklist *blptr = (struct Blacklist *) nptr->data; - - if (!(blptr->status & CONF_ILLEGAL)) - initiate_blacklist_dnsquery(blptr, client_p); - } -} - -void abort_blacklist_queries(struct Client *client_p) -{ - rb_dlink_node *ptr, *next_ptr; - struct BlacklistClient *blcptr; - - if (client_p->preClient == NULL) - return; - RB_DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->preClient->dnsbl_queries.head) - { - blcptr = ptr->data; - rb_dlinkDelete(&blcptr->node, &client_p->preClient->dnsbl_queries); - unref_blacklist(blcptr->blacklist); - cancel_lookup(blcptr->dns_id); - rb_free(blcptr); - } -} - -void destroy_blacklists(void) -{ - rb_dlink_node *ptr, *next_ptr; - struct Blacklist *blptr; - - RB_DLINK_FOREACH_SAFE(ptr, next_ptr, blacklist_list.head) - { - blptr = ptr->data; - blptr->hits = 0; /* keep it simple and consistent */ - if (blptr->refcount > 0) - blptr->status |= CONF_ILLEGAL; - else - { - rb_free(ptr->data); - rb_dlinkDestroy(ptr, &blacklist_list); - } - } -} diff --git a/ircd/client.c b/ircd/client.c index 268f61b2..86ca8fcc 100644 --- a/ircd/client.c +++ b/ircd/client.c @@ -32,7 +32,7 @@ #include "ircd.h" #include "numeric.h" #include "packet.h" -#include "s_auth.h" +#include "authd.h" #include "s_conf.h" #include "s_newconf.h" #include "logger.h" @@ -47,7 +47,6 @@ #include "hook.h" #include "msg.h" #include "monitor.h" -#include "blacklist.h" #include "reject.h" #include "scache.h" #include "rb_dictionary.h" @@ -253,17 +252,15 @@ make_client(struct Client *from) void free_pre_client(struct Client *client_p) { - struct Blacklist *blptr; - s_assert(NULL != client_p); if(client_p->preClient == NULL) return; - blptr = client_p->preClient->dnsbl_listed; - if (blptr != NULL) - unref_blacklist(blptr); - s_assert(rb_dlink_list_length(&client_p->preClient->dnsbl_queries) == 0); + s_assert(client_p->preClient->authd_cid == 0); + + rb_free(client_p->preClient->authd_data); + rb_free(client_p->preClient->authd_reason); rb_bh_free(pclient_heap, client_p->preClient); client_p->preClient = NULL; @@ -454,9 +451,8 @@ check_unknowns_list(rb_dlink_list * list) if(IsDead(client_p) || IsClosing(client_p)) continue; - /* still has DNSbls to validate against */ - if(client_p->preClient != NULL && - rb_dlink_list_length(&client_p->preClient->dnsbl_queries) > 0) + /* Still querying with authd */ + if(client_p->preClient != NULL && client_p->preClient->authd_cid != 0) continue; /* @@ -1355,8 +1351,7 @@ static int exit_unknown_client(struct Client *client_p, struct Client *source_p, struct Client *from, const char *comment) { - delete_auth_queries(source_p); - abort_blacklist_queries(source_p); + authd_abort_client(client_p); rb_dlinkDelete(&source_p->localClient->tnode, &unknown_list); if(!IsIOError(source_p)) diff --git a/ircd/ircd.c b/ircd/ircd.c index 8a16ffa4..5c576fc8 100644 --- a/ircd/ircd.c +++ b/ircd/ircd.c @@ -39,7 +39,6 @@ #include "numeric.h" #include "parse.h" #include "restart.h" -#include "s_auth.h" #include "s_conf.h" #include "logger.h" #include "s_serv.h" /* try_connections */ @@ -782,7 +781,6 @@ charybdis_main(int argc, char *argv[]) load_all_modules(1); load_core_modules(1); - init_auth(); /* Initialise the auth code */ init_authd(); /* Start up authd. */ init_dns(); /* Start up DNS query system */ @@ -847,6 +845,8 @@ charybdis_main(int argc, char *argv[]) return 0; /* Why? We want the launcher to exit out. */ } + configure_authd(); + me.from = &me; me.servptr = &me; SetMe(&me); diff --git a/ircd/listener.c b/ircd/listener.c index aeff94e9..6038a2d8 100644 --- a/ircd/listener.c +++ b/ircd/listener.c @@ -34,7 +34,7 @@ #include "s_newconf.h" #include "s_stats.h" #include "send.h" -#include "s_auth.h" +#include "authd.h" #include "reject.h" #include "s_conf.h" #include "hostmask.h" @@ -509,7 +509,7 @@ add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, str ++listener->ref_count; - start_auth(new_client); + authd_initiate_client(new_client); } static const char *toofast = "ERROR :Reconnecting too fast, throttled.\r\n"; diff --git a/ircd/newconf.c b/ircd/newconf.c index 7a726db3..347f0f25 100644 --- a/ircd/newconf.c +++ b/ircd/newconf.c @@ -24,7 +24,6 @@ #include "cache.h" #include "ircd.h" #include "snomask.h" -#include "blacklist.h" #include "sslproc.h" #include "privilege.h" #include "chmode.h" @@ -55,8 +54,7 @@ static struct alias_entry *yy_alias = NULL; static char *yy_blacklist_host = NULL; static char *yy_blacklist_reason = NULL; -static int yy_blacklist_ipv4 = 1; -static int yy_blacklist_ipv6 = 0; +static uint8_t yy_blacklist_iptype = 0; static rb_dlink_list yy_blacklist_filters; static char *yy_privset_extends = NULL; @@ -1841,6 +1839,9 @@ conf_set_channel_autochanmodes(void *data) /* XXX for below */ static void conf_set_blacklist_reason(void *data); +#define IPTYPE_IPV4 1 +#define IPTYPE_IPV6 2 + static void conf_set_blacklist_host(void *data) { @@ -1854,8 +1855,7 @@ conf_set_blacklist_host(void *data) return; } - yy_blacklist_ipv4 = 1; - yy_blacklist_ipv6 = 0; + yy_blacklist_iptype |= IPTYPE_IPV4; yy_blacklist_host = rb_strdup(data); } @@ -1865,25 +1865,24 @@ conf_set_blacklist_type(void *data) conf_parm_t *args = data; /* Don't assume we have either if we got here */ - yy_blacklist_ipv4 = 0; - yy_blacklist_ipv6 = 0; + yy_blacklist_iptype = 0; for (; args; args = args->next) { if (!strcasecmp(args->v.string, "ipv4")) - yy_blacklist_ipv4 = 1; + yy_blacklist_iptype |= IPTYPE_IPV4; else if (!strcasecmp(args->v.string, "ipv6")) - yy_blacklist_ipv6 = 1; + yy_blacklist_iptype |= IPTYPE_IPV6; else conf_report_error("blacklist::type has unknown address family %s", args->v.string); } /* If we have neither, just default to IPv4 */ - if (!yy_blacklist_ipv4 && !yy_blacklist_ipv6) + if (!yy_blacklist_iptype) { conf_report_error("blacklist::type has neither IPv4 nor IPv6 (defaulting to IPv4)"); - yy_blacklist_ipv4 = 1; + yy_blacklist_iptype = IPTYPE_IPV4; } } @@ -1891,13 +1890,13 @@ static void conf_set_blacklist_matches(void *data) { conf_parm_t *args = data; + enum filter_t { FILTER_NONE, FILTER_ALL, FILTER_LAST }; for (; args; args = args->next) { - struct BlacklistFilter *filter; char *str = args->v.string; char *p; - int type = BLACKLIST_FILTER_LAST; + enum filter_t type = FILTER_LAST; if (CF_TYPE(args->type) != CF_QSTRING) { @@ -1922,17 +1921,17 @@ conf_set_blacklist_matches(void *data) { /* Check for validity */ if (*p == '.') - type = BLACKLIST_FILTER_ALL; - else if (!isalnum((unsigned char)*p)) + type = FILTER_ALL; + else if (!isdigit((unsigned char)*p)) { conf_report_error("blacklist::matches has invalid IP match entry %s", str); - type = 0; + type = FILTER_NONE; break; } } - if (type == BLACKLIST_FILTER_ALL) + if (type == FILTER_ALL) { /* Basic IP sanity check */ struct rb_sockaddr_storage tmp; @@ -1943,7 +1942,7 @@ conf_set_blacklist_matches(void *data) continue; } } - else if (type == BLACKLIST_FILTER_LAST) + else if (type == FILTER_LAST) { /* Verify it's the correct length */ if (strlen(str) > 3) @@ -1958,11 +1957,7 @@ conf_set_blacklist_matches(void *data) continue; /* Invalid entry */ } - filter = rb_malloc(sizeof(struct BlacklistFilter)); - filter->type = type; - rb_strlcpy(filter->filterstr, str, sizeof(filter->filterstr)); - - rb_dlinkAdd(filter, &filter->node, &yy_blacklist_filters); + rb_dlinkAddAlloc(rb_strdup(str), &yy_blacklist_filters); } } @@ -1974,7 +1969,7 @@ conf_set_blacklist_reason(void *data) if (yy_blacklist_host && data) { yy_blacklist_reason = rb_strdup(data); - if (yy_blacklist_ipv6) + if (yy_blacklist_iptype & IPTYPE_IPV4) { /* Make sure things fit (64 = alnum count + dots) */ if ((64 + strlen(yy_blacklist_host)) > IRCD_RES_HOSTLEN) @@ -1985,7 +1980,7 @@ conf_set_blacklist_reason(void *data) } } /* Avoid doing redundant check, IPv6 is bigger than IPv4 --Elizabeth */ - if (yy_blacklist_ipv4 && !yy_blacklist_ipv6) + if ((yy_blacklist_iptype & IPTYPE_IPV4) && !(yy_blacklist_iptype & IPTYPE_IPV6)) { /* Make sure things fit (16 = number of nums + dots) */ if ((16 + strlen(yy_blacklist_host)) > IRCD_RES_HOSTLEN) @@ -1996,30 +1991,23 @@ conf_set_blacklist_reason(void *data) } } - new_blacklist(yy_blacklist_host, yy_blacklist_reason, yy_blacklist_ipv4, yy_blacklist_ipv6, - &yy_blacklist_filters); + add_blacklist(yy_blacklist_host, yy_blacklist_reason, yy_blacklist_iptype, &yy_blacklist_filters); } cleanup_bl: - if (data == NULL) + RB_DLINK_FOREACH_SAFE(ptr, nptr, yy_blacklist_filters.head) { - RB_DLINK_FOREACH_SAFE(ptr, nptr, yy_blacklist_filters.head) - { - rb_dlinkDelete(ptr, &yy_blacklist_filters); - rb_free(ptr); - } - } - else - { - yy_blacklist_filters = (rb_dlink_list){ NULL, NULL, 0 }; + rb_free(ptr->data); + rb_dlinkDestroy(ptr, &yy_blacklist_filters); } + yy_blacklist_filters = (rb_dlink_list){ NULL, NULL, 0 }; + rb_free(yy_blacklist_host); rb_free(yy_blacklist_reason); yy_blacklist_host = NULL; yy_blacklist_reason = NULL; - yy_blacklist_ipv4 = 1; - yy_blacklist_ipv6 = 0; + yy_blacklist_iptype = 0; } /* public functions */ diff --git a/ircd/s_auth.c b/ircd/s_auth.c deleted file mode 100644 index c30b9e14..00000000 --- a/ircd/s_auth.c +++ /dev/null @@ -1,607 +0,0 @@ -/* - * ircd-ratbox: A slightly useful ircd. - * s_auth.c: Functions for querying a users ident. - * - * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2002-2005 ircd-ratbox development team - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - */ - -/* - * Changes: - * July 6, 1999 - Rewrote most of the code here. When a client connects - * to the server and passes initial socket validation checks, it - * is owned by this module (auth) which returns it to the rest of the - * server when dns and auth queries are finished. Until the client is - * released, the server does not know it exists and does not process - * any messages from it. - * --Bleep Thomas Helvey - */ -#include "stdinc.h" -#include "defaults.h" -#include "s_auth.h" -#include "s_conf.h" -#include "client.h" -#include "match.h" -#include "ircd.h" -#include "numeric.h" -#include "packet.h" -#include "dns.h" -#include "logger.h" -#include "s_stats.h" -#include "send.h" -#include "hook.h" -#include "blacklist.h" -#include "s_assert.h" - -struct AuthRequest -{ - rb_dlink_node node; - struct Client *client; /* pointer to client struct for request */ - uint16_t dns_id; /* DNS Query */ - unsigned int flags; /* current state of request */ - rb_fde_t *F; /* file descriptor for auth queries */ - time_t timeout; /* time when query expires */ - uint16_t lport; - uint16_t rport; -}; - -/* - * flag values for AuthRequest - * NAMESPACE: AM_xxx - Authentication Module - */ -#define AM_AUTH_CONNECTING (1 << 0) -#define AM_AUTH_PENDING (1 << 1) -#define AM_DNS_PENDING (1 << 2) - -#define SetDNSPending(x) ((x)->flags |= AM_DNS_PENDING) -#define ClearDNSPending(x) ((x)->flags &= ~AM_DNS_PENDING) -#define IsDNSPending(x) ((x)->flags & AM_DNS_PENDING) - -#define SetAuthConnect(x) ((x)->flags |= AM_AUTH_CONNECTING) -#define ClearAuthConnect(x) ((x)->flags &= ~AM_AUTH_CONNECTING) -#define IsAuthConnect(x) ((x)->flags & AM_AUTH_CONNECTING) - -#define SetAuthPending(x) ((x)->flags |= AM_AUTH_PENDING) -#define ClearAuthPending(x) ((x)->flags &= AM_AUTH_PENDING) -#define IsAuthPending(x) ((x)->flags & AM_AUTH_PENDING) - -#define ClearAuth(x) ((x)->flags &= ~(AM_AUTH_PENDING | AM_AUTH_CONNECTING)) -#define IsDoingAuth(x) ((x)->flags & (AM_AUTH_PENDING | AM_AUTH_CONNECTING)) - -/* - * a bit different approach - * this replaces the original sendheader macros - */ - -static const char *HeaderMessages[] = -{ - ":*** Looking up your hostname...", - ":*** Found your hostname", - ":*** Couldn't look up your hostname", - ":*** Checking Ident", - ":*** Got Ident response", - ":*** No Ident response", - ":*** Your hostname is too long, ignoring hostname", - ":*** Your forward and reverse DNS do not match, ignoring hostname", - ":*** Cannot verify hostname validity, ignoring hostname", -}; - -typedef enum -{ - REPORT_DO_DNS, - REPORT_FIN_DNS, - REPORT_FAIL_DNS, - REPORT_DO_ID, - REPORT_FIN_ID, - REPORT_FAIL_ID, - REPORT_HOST_TOOLONG, - REPORT_HOST_MISMATCH, - REPORT_HOST_UNKNOWN -} -ReportType; - -#define sendheader(c, r) sendto_one_notice(c, "%s", HeaderMessages[(r)]) - -static rb_dlink_list auth_poll_list; -static rb_bh *auth_heap; -static EVH timeout_auth_queries_event; - -static PF read_auth_reply; -static CNCB auth_connect_callback; - -/* - * init_auth() - * - * Initialise the auth code - */ -void -init_auth(void) -{ - /* This hook takes a struct Client for its argument */ - memset(&auth_poll_list, 0, sizeof(auth_poll_list)); - rb_event_addish("timeout_auth_queries_event", timeout_auth_queries_event, NULL, 1); - auth_heap = rb_bh_create(sizeof(struct AuthRequest), LCLIENT_HEAP_SIZE, "auth_heap"); -} - -/* - * make_auth_request - allocate a new auth request - */ -static struct AuthRequest * -make_auth_request(struct Client *client) -{ - struct AuthRequest *request = rb_bh_alloc(auth_heap); - client->localClient->auth_request = request; - request->F = NULL; - request->client = client; - request->timeout = rb_current_time() + ConfigFileEntry.connect_timeout; - return request; -} - -/* - * free_auth_request - cleanup auth request allocations - */ -static void -free_auth_request(struct AuthRequest *request) -{ - rb_bh_free(auth_heap, request); -} - -/* - * release_auth_client - release auth client from auth system - * this adds the client into the local client lists so it can be read by - * the main io processing loop - */ -static void -release_auth_client(struct AuthRequest *auth) -{ - struct Client *client = auth->client; - - if(IsDNSPending(auth) || IsDoingAuth(auth)) - return; - - client->localClient->auth_request = NULL; - rb_dlinkDelete(&auth->node, &auth_poll_list); - free_auth_request(auth); - - /* - * When a client has auth'ed, we want to start reading what it sends - * us. This is what read_packet() does. - * -- adrian - */ - rb_dlinkAddTail(client, &client->node, &global_client_list); - read_packet(client->localClient->F, client); -} - -/* - * auth_dns_callback - called when resolver query finishes - * if the query resulted in a successful search, hp will contain - * a non-null pointer, otherwise hp will be null. - * set the client on it's way to a connection completion, regardless - * of success of failure - */ -static void -auth_dns_callback(const char *result, int status, int aftype, void *vptr) -{ - struct AuthRequest *auth = (struct AuthRequest *) vptr; - ClearDNSPending(auth); - - /* XXX: this shouldn't happen, but it does. -nenolod */ - if(auth->client->localClient == NULL) - { - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "auth_dns_callback(): auth->client->localClient (%s) is NULL", get_client_name(auth->client, HIDE_IP)); - - rb_dlinkDelete(&auth->node, &auth_poll_list); - free_auth_request(auth); - - /* and they will silently drop through and all will hopefully be ok... -nenolod */ - return; - } - - if(result != NULL && status) - { - int good = 1; - - if(good && strlen(result) <= HOSTLEN) - { - rb_strlcpy(auth->client->host, result, sizeof(auth->client->host)); - sendheader(auth->client, REPORT_FIN_DNS); - } - else if (strlen(result) > HOSTLEN) - sendheader(auth->client, REPORT_HOST_TOOLONG); - } - else - sendheader(auth->client, REPORT_FAIL_DNS); - - release_auth_client(auth); -} - -/* - * authsenderr - handle auth send errors - */ -static void -auth_error(struct AuthRequest *auth) -{ - ++ServerStats.is_abad; - - rb_close(auth->F); - auth->F = NULL; - - ClearAuth(auth); - sendheader(auth->client, REPORT_FAIL_ID); - - release_auth_client(auth); -} - -/* - * start_auth_query - Flag the client to show that an attempt to - * contact the ident server on - * the client's host. The connect and subsequently the socket are all put - * into 'non-blocking' mode. Should the connect or any later phase of the - * identifing process fail, it is aborted and the user is given a username - * of "unknown". - */ -static int -start_auth_query(struct AuthRequest *auth) -{ - struct rb_sockaddr_storage localaddr, destaddr; - rb_fde_t *F; - int family; - - if(IsAnyDead(auth->client)) - return 0; - - family = GET_SS_FAMILY(&auth->client->localClient->ip); - if((F = rb_socket(family, SOCK_STREAM, 0, "ident")) == NULL) - { - ilog_error("creating auth stream socket"); - ++ServerStats.is_abad; - return 0; - } - - /* - * TBD: this is a pointless arbitrary limit .. we either have a socket or not. -nenolod - */ - if((maxconnections - 10) < rb_get_fd(F)) - { - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "Can't allocate fd for auth on %s", - get_client_name(auth->client, SHOW_IP)); - rb_close(F); - return 0; - } - - sendheader(auth->client, REPORT_DO_ID); - - /* - * get the local address of the client and bind to that to - * make the auth request. This used to be done only for - * ifdef VIRTUAL_HOST, but needs to be done for all clients - * since the ident request must originate from that same address-- - * and machines with multiple IP addresses are common now - */ - localaddr = auth->client->preClient->lip; - - /* XXX mangle_mapped_sockaddr((struct sockaddr *)&localaddr); */ -#ifdef RB_IPV6 - if(GET_SS_FAMILY(&localaddr) == AF_INET6) - { - auth->lport = ntohs(((struct sockaddr_in6 *)&localaddr)->sin6_port); - ((struct sockaddr_in6 *)&localaddr)->sin6_port = 0; - } - else -#endif - { - auth->lport = ntohs(((struct sockaddr_in *)&localaddr)->sin_port); - ((struct sockaddr_in *)&localaddr)->sin_port = 0; - } - - destaddr = auth->client->localClient->ip; -#ifdef RB_IPV6 - if(GET_SS_FAMILY(&localaddr) == AF_INET6) - { - auth->rport = ntohs(((struct sockaddr_in6 *)&destaddr)->sin6_port); - ((struct sockaddr_in6 *)&destaddr)->sin6_port = htons(113); - } - else -#endif - { - auth->rport = ntohs(((struct sockaddr_in *)&destaddr)->sin_port); - ((struct sockaddr_in *)&destaddr)->sin_port = htons(113); - } - - auth->F = F; - SetAuthConnect(auth); - - rb_connect_tcp(F, (struct sockaddr *)&destaddr, - (struct sockaddr *) &localaddr, GET_SS_LEN(&localaddr), - auth_connect_callback, auth, - GlobalSetOptions.ident_timeout); - return 1; /* We suceed here for now */ -} - -/* - * GetValidIdent - parse ident query reply from identd server - * - * Inputs - pointer to ident buf - * Output - NULL if no valid ident found, otherwise pointer to name - * Side effects - - */ -static char * -GetValidIdent(char *buf) -{ - int remp = 0; - int locp = 0; - char *colon1Ptr; - char *colon2Ptr; - char *colon3Ptr; - char *commaPtr; - char *remotePortString; - - /* All this to get rid of a sscanf() fun. */ - remotePortString = buf; - - colon1Ptr = strchr(remotePortString, ':'); - if(!colon1Ptr) - return 0; - - *colon1Ptr = '\0'; - colon1Ptr++; - colon2Ptr = strchr(colon1Ptr, ':'); - if(!colon2Ptr) - return 0; - - *colon2Ptr = '\0'; - colon2Ptr++; - commaPtr = strchr(remotePortString, ','); - - if(!commaPtr) - return 0; - - *commaPtr = '\0'; - commaPtr++; - - remp = atoi(remotePortString); - if(!remp) - return 0; - - locp = atoi(commaPtr); - if(!locp) - return 0; - - /* look for USERID bordered by first pair of colons */ - if(!strstr(colon1Ptr, "USERID")) - return 0; - - colon3Ptr = strchr(colon2Ptr, ':'); - if(!colon3Ptr) - return 0; - - *colon3Ptr = '\0'; - colon3Ptr++; - return (colon3Ptr); -} - -/* - * start_auth - starts auth (identd) and dns queries for a client - */ -void -start_auth(struct Client *client) -{ - struct AuthRequest *auth = 0; - s_assert(0 != client); - if(client == NULL) - return; - - auth = make_auth_request(client); - - sendheader(client, REPORT_DO_DNS); - - /* No DNS cache now, remember? -- adrian */ - auth->dns_id = lookup_ip(client->sockhost, GET_SS_FAMILY(&client->localClient->ip), auth_dns_callback, auth); - - SetDNSPending(auth); - - if(ConfigFileEntry.disable_auth == 0) - start_auth_query(auth); - - rb_dlinkAdd(auth, &auth->node, &auth_poll_list); -} - -/* - * timeout_auth_queries - timeout resolver and identd requests - * allow clients through if requests failed - */ -static void -timeout_auth_queries_event(void *notused) -{ - rb_dlink_node *ptr; - rb_dlink_node *next_ptr; - struct AuthRequest *auth; - - RB_DLINK_FOREACH_SAFE(ptr, next_ptr, auth_poll_list.head) - { - auth = ptr->data; - - if(auth->timeout < rb_current_time()) - { - if(auth->F != NULL) - rb_close(auth->F); - - if(IsDoingAuth(auth)) - { - ClearAuth(auth); - ++ServerStats.is_abad; - sendheader(auth->client, REPORT_FAIL_ID); - auth->client->localClient->auth_request = NULL; - } - if(IsDNSPending(auth)) - { - ClearDNSPending(auth); - cancel_lookup(auth->dns_id); - sendheader(auth->client, REPORT_FAIL_DNS); - } - - auth->client->localClient->lasttime = rb_current_time(); - release_auth_client(auth); - } - } -} - -/* - * auth_connect_callback() - deal with the result of rb_connect_tcp() - * - * If the connection failed, we simply close the auth fd and report - * a failure. If the connection suceeded send the ident server a query - * giving "theirport , ourport". The write is only attempted *once* so - * it is deemed to be a fail if the entire write doesn't write all the - * data given. This shouldnt be a problem since the socket should have - * a write buffer far greater than this message to store it in should - * problems arise. -avalon - */ -static void -auth_connect_callback(rb_fde_t *F, int error, void *data) -{ - struct AuthRequest *auth = data; - char authbuf[32]; - int authlen; - - /* Check the error */ - if(error != RB_OK) - { - /* We had an error during connection :( */ - auth_error(auth); - return; - } - - snprintf(authbuf, sizeof(authbuf), "%u , %u\r\n", - auth->rport, auth->lport); - authlen = strlen(authbuf); - - if(rb_write(auth->F, authbuf, authlen) != authlen) - { - auth_error(auth); - return; - } - ClearAuthConnect(auth); - SetAuthPending(auth); - read_auth_reply(auth->F, auth); -} - - -/* - * read_auth_reply - read the reply (if any) from the ident server - * we connected to. - * We only give it one shot, if the reply isn't good the first time - * fail the authentication entirely. --Bleep - */ -#define AUTH_BUFSIZ 128 - -static void -read_auth_reply(rb_fde_t *F, void *data) -{ - struct AuthRequest *auth = data; - char *s = NULL; - char *t = NULL; - int len; - int count; - char buf[AUTH_BUFSIZ + 1]; /* buffer to read auth reply into */ - - len = rb_read(F, buf, AUTH_BUFSIZ); - - if(len < 0 && rb_ignore_errno(errno)) - { - rb_setselect(F, RB_SELECT_READ, read_auth_reply, auth); - return; - } - - if(len > 0) - { - buf[len] = '\0'; - - if((s = GetValidIdent(buf))) - { - t = auth->client->username; - - while (*s == '~' || *s == '^') - s++; - - for (count = USERLEN; *s && count; s++) - { - if(*s == '@') - { - break; - } - if(!IsSpace(*s) && *s != ':' && *s != '[') - { - *t++ = *s; - count--; - } - } - *t = '\0'; - } - } - - rb_close(auth->F); - auth->F = NULL; - ClearAuth(auth); - - if(s == NULL) - { - ++ServerStats.is_abad; - strcpy(auth->client->username, "unknown"); - sendheader(auth->client, REPORT_FAIL_ID); - } - else - { - sendheader(auth->client, REPORT_FIN_ID); - ++ServerStats.is_asuc; - SetGotId(auth->client); - } - - release_auth_client(auth); -} - - - -/* - * delete_auth_queries() - */ -void -delete_auth_queries(struct Client *target_p) -{ - struct AuthRequest *auth; - - if(target_p == NULL || target_p->localClient == NULL || - target_p->localClient->auth_request == NULL) - return; - - auth = target_p->localClient->auth_request; - target_p->localClient->auth_request = NULL; - - if(IsDNSPending(auth)) - cancel_lookup(auth->dns_id); - - if(auth->F != NULL) - rb_close(auth->F); - - rb_dlinkDelete(&auth->node, &auth_poll_list); - free_auth_request(auth); -} diff --git a/ircd/s_conf.c b/ircd/s_conf.c index 87520538..18db1736 100644 --- a/ircd/s_conf.c +++ b/ircd/s_conf.c @@ -43,7 +43,6 @@ #include "send.h" #include "reject.h" #include "cache.h" -#include "blacklist.h" #include "privilege.h" #include "sslproc.h" #include "bandbi.h" @@ -1526,7 +1525,7 @@ clear_out_old_conf(void) alias_dict = NULL; } - destroy_blacklists(); + del_blacklist_all(); privilegeset_mark_all_illegal(); diff --git a/ircd/s_user.c b/ircd/s_user.c index 86a8c7cd..8c8f6796 100644 --- a/ircd/s_user.c +++ b/ircd/s_user.c @@ -48,7 +48,6 @@ #include "hook.h" #include "monitor.h" #include "snomask.h" -#include "blacklist.h" #include "substitution.h" #include "chmode.h" #include "s_assert.h" @@ -252,8 +251,8 @@ register_local_user(struct Client *client_p, struct Client *source_p) if(source_p->flags & FLAGS_CLICAP) return -1; - /* still has DNSbls to validate against */ - if(rb_dlink_list_length(&source_p->preClient->dnsbl_queries) > 0) + /* Waiting on authd */ + if(source_p->preClient->authd_cid) return -1; client_p->localClient->last = rb_current_time(); @@ -301,7 +300,6 @@ register_local_user(struct Client *client_p, struct Client *source_p) rb_strlcpy(source_p->host, source_p->sockhost, sizeof(source_p->host)); } - aconf = source_p->localClient->att_conf; if(aconf == NULL) @@ -421,45 +419,83 @@ register_local_user(struct Client *client_p, struct Client *source_p) return CLIENT_EXITED; } - /* dnsbl check */ - if (source_p->preClient->dnsbl_listed != NULL) + /* authd rejection check */ + if(source_p->preClient->authd_accepted == false) { - if (IsExemptKline(source_p) || IsConfExemptDNSBL(aconf)) - sendto_one_notice(source_p, ":*** Your IP address %s is listed in %s, but you are exempt", - source_p->sockhost, source_p->preClient->dnsbl_listed->host); - else + struct blacklist_stats *stats; + rb_dlink_list varlist = { NULL, NULL, 0 }; + char *reason; + + substitution_append_var(&varlist, "nick", source_p->name); + substitution_append_var(&varlist, "ip", source_p->sockhost); + substitution_append_var(&varlist, "host", source_p->host); + substitution_append_var(&varlist, "dnsbl-host", source_p->preClient->authd_data); + substitution_append_var(&varlist, "network-name", ServerInfo.network_name); + reason = substitution_parse(source_p->preClient->authd_reason, &varlist); + + switch(source_p->preClient->authd_cause) { - sendto_realops_snomask(SNO_REJ, L_NETWIDE, - "Listed on DNSBL %s: %s (%s@%s) [%s] [%s]", - source_p->preClient->dnsbl_listed->host, - source_p->name, - source_p->username, source_p->host, - IsIPSpoof(source_p) ? "255.255.255.255" : source_p->sockhost, - source_p->info); + case 'B': /* Blacklists */ + if((stats = rb_dictionary_retrieve(bl_stats, source_p->preClient->authd_data)) != NULL) + stats->hits++; + + if(IsExemptKline(source_p) || IsConfExemptDNSBL(aconf)) + { + sendto_one_notice(source_p, ":*** Your IP address %s is listed in %s, but you are exempt", + source_p->sockhost, source_p->preClient->authd_data); + } + else + { + sendto_realops_snomask(SNO_REJ, L_NETWIDE, + "Listed on DNSBL %s: %s (%s@%s) [%s] [%s]", + source_p->preClient->authd_data, + source_p->name, + source_p->username, source_p->host, + IsIPSpoof(source_p) ? "255.255.255.255" : source_p->sockhost, + source_p->info); - rb_dlink_list varlist = { NULL, NULL, 0 }; + ServerStats.is_ref++; - substitution_append_var(&varlist, "nick", source_p->name); - substitution_append_var(&varlist, "ip", source_p->sockhost); - substitution_append_var(&varlist, "host", source_p->host); - substitution_append_var(&varlist, "dnsbl-host", source_p->preClient->dnsbl_listed->host); - substitution_append_var(&varlist, "network-name", ServerInfo.network_name); + sendto_one(source_p, form_str(ERR_YOUREBANNEDCREEP), + me.name, source_p->name, reason); - ServerStats.is_ref++; + sendto_one_notice(source_p, ":*** Your IP address %s is listed in %s", + source_p->sockhost, source_p->preClient->authd_data); + add_reject(source_p, NULL, NULL); + exit_client(client_p, source_p, &me, "*** Banned (DNS blacklist)"); + substitution_free(&varlist); + return CLIENT_EXITED; + } + break; + default: /* Unknown, but handle the case properly */ + if (IsExemptKline(source_p)) + { + sendto_one_notice(source_p, ":*** You were rejected, but you are exempt (reason: %s)", + reason); + } + else + { + sendto_realops_snomask(SNO_REJ, L_NETWIDE, + "Rejected by authentication system (reason %s): %s (%s@%s) [%s] [%s]", + reason, source_p->name, source_p->username, source_p->host, + IsIPSpoof(source_p) ? "255.255.255.255" : source_p->sockhost, + source_p->info); - sendto_one(source_p, form_str(ERR_YOUREBANNEDCREEP), - me.name, source_p->name, - substitution_parse(source_p->preClient->dnsbl_listed->reject_reason, &varlist)); + ServerStats.is_ref++; - substitution_free(&varlist); + sendto_one(source_p, form_str(ERR_YOUREBANNEDCREEP), + me.name, source_p->name, reason); - sendto_one_notice(source_p, ":*** Your IP address %s is listed in %s", - source_p->sockhost, source_p->preClient->dnsbl_listed->host); - source_p->preClient->dnsbl_listed->hits++; - add_reject(source_p, NULL, NULL); - exit_client(client_p, source_p, &me, "*** Banned (DNS blacklist)"); - return CLIENT_EXITED; + sendto_one_notice(source_p, ":*** Rejected by authentication system: %s", + reason); + add_reject(source_p, NULL, NULL); + exit_client(client_p, source_p, &me, "*** Banned (authentication system)"); + substitution_free(&varlist); + return CLIENT_EXITED; + } } + + substitution_free(&varlist); } /* valid user name check */ diff --git a/modules/m_set.c b/modules/m_set.c index e28b7002..2355ab10 100644 --- a/modules/m_set.c +++ b/modules/m_set.c @@ -202,6 +202,7 @@ quote_identtimeout(struct Client *source_p, const char *arg, int newval) "%s has changed IDENTTIMEOUT to %d", get_oper_name(source_p), newval); GlobalSetOptions.ident_timeout = newval; + set_authd_timeout("ident_timeout", newval); } else sendto_one_notice(source_p, ":IDENTTIMEOUT is currently %d", diff --git a/modules/m_stats.c b/modules/m_stats.c index 40082039..afaea433 100644 --- a/modules/m_stats.c +++ b/modules/m_stats.c @@ -37,7 +37,6 @@ #include "s_serv.h" /* hunt_server */ #include "s_stats.h" #include "s_user.h" /* show_opers */ -#include "blacklist.h" /* dnsbl stuff */ #include "parse.h" #include "modules.h" #include "hook.h" @@ -141,51 +140,51 @@ static void stats_capability(struct Client *); */ static struct stats_cmd stats_cmd_table[256] = { /* letter handler/handler_parv parv oper admin */ - ['a'] = { { stats_dns_servers }, false, true, true, }, - ['A'] = { { stats_dns_servers }, false, true, true, }, - ['b'] = { { stats_delay }, false, true, true, }, - ['B'] = { { stats_hash }, false, true, true, }, + ['a'] = { { stats_dns_servers }, false, true, true, }, + ['A'] = { { stats_dns_servers }, false, true, true, }, + ['b'] = { { stats_delay }, false, true, true, }, + ['B'] = { { stats_hash }, false, true, true, }, ['c'] = { { stats_connect }, false, false, false, }, ['C'] = { { stats_capability }, false, true, false, }, - ['d'] = { { stats_tdeny }, false, true, false, }, - ['D'] = { { stats_deny }, false, true, false, }, - ['e'] = { { stats_exempt }, false, true, false, }, - ['E'] = { { stats_events }, false, true, true, }, - ['f'] = { { stats_comm }, false, true, true, }, - ['F'] = { { stats_comm }, false, true, true, }, - ['g'] = { { stats_prop_klines }, false, true, false, }, + ['d'] = { { stats_tdeny }, false, true, false, }, + ['D'] = { { stats_deny }, false, true, false, }, + ['e'] = { { stats_exempt }, false, true, false, }, + ['E'] = { { stats_events }, false, true, true, }, + ['f'] = { { stats_comm }, false, true, true, }, + ['F'] = { { stats_comm }, false, true, true, }, + ['g'] = { { stats_prop_klines }, false, true, false, }, ['h'] = { { stats_hubleaf }, false, false, false, }, ['H'] = { { stats_hubleaf }, false, false, false, }, - ['i'] = { { stats_auth }, false, false, false, }, - ['I'] = { { stats_auth }, false, false, false, }, + ['i'] = { { stats_auth }, false, false, false, }, + ['I'] = { { stats_auth }, false, false, false, }, ['k'] = { { stats_tklines }, false, false, false, }, - ['K'] = { { stats_klines }, false, false, false, }, - ['l'] = { { .handler_parv = stats_ltrace }, true, false, false, }, - ['L'] = { { .handler_parv = stats_ltrace }, true, false, false, }, + ['K'] = { { stats_klines }, false, false, false, }, + ['l'] = { { .handler_parv = stats_ltrace }, true, false, false, }, + ['L'] = { { .handler_parv = stats_ltrace }, true, false, false, }, ['m'] = { { stats_messages }, false, false, false, }, ['M'] = { { stats_messages }, false, false, false, }, - ['n'] = { { stats_dnsbl }, false, false, false, }, - ['o'] = { { stats_oper }, false, false, false, }, + ['n'] = { { stats_dnsbl }, false, false, false, }, + ['o'] = { { stats_oper }, false, false, false, }, ['O'] = { { stats_privset }, false, true, false, }, ['p'] = { { stats_operedup }, false, false, false, }, - ['P'] = { { stats_ports }, false, false, false, }, - ['q'] = { { stats_tresv }, false, true, false, }, - ['Q'] = { { stats_resv }, false, true, false, }, - ['r'] = { { stats_usage }, false, true, false, }, - ['R'] = { { stats_usage }, false, true, false, }, - ['s'] = { { stats_ssld }, false, true, true, }, - ['S'] = { { stats_ssld }, false, true, true, }, - ['t'] = { { stats_tstats }, false, true, false, }, - ['T'] = { { stats_tstats }, false, true, false, }, - ['u'] = { { stats_uptime }, false, false, false, }, - ['U'] = { { stats_shared }, false, true, false, }, + ['P'] = { { stats_ports }, false, false, false, }, + ['q'] = { { stats_tresv }, false, true, false, }, + ['Q'] = { { stats_resv }, false, true, false, }, + ['r'] = { { stats_usage }, false, true, false, }, + ['R'] = { { stats_usage }, false, true, false, }, + ['s'] = { { stats_ssld }, false, true, true, }, + ['S'] = { { stats_ssld }, false, true, true, }, + ['t'] = { { stats_tstats }, false, true, false, }, + ['T'] = { { stats_tstats }, false, true, false, }, + ['u'] = { { stats_uptime }, false, false, false, }, + ['U'] = { { stats_shared }, false, true, false, }, ['v'] = { { stats_servers }, false, false, false, }, ['V'] = { { stats_servers }, false, false, false, }, - ['x'] = { { stats_tgecos }, false, true, false, }, - ['X'] = { { stats_gecos }, false, true, false, }, - ['y'] = { { stats_class }, false, false, false, }, - ['Y'] = { { stats_class }, false, false, false, }, - ['z'] = { { stats_memory }, false, true, false, }, + ['x'] = { { stats_tgecos }, false, true, false, }, + ['X'] = { { stats_gecos }, false, true, false, }, + ['y'] = { { stats_class }, false, false, false, }, + ['Y'] = { { stats_class }, false, false, false, }, + ['z'] = { { stats_memory }, false, true, false, }, ['Z'] = { { stats_ziplinks }, false, true, false, }, ['?'] = { { stats_servlinks }, false, false, false, }, }; @@ -758,19 +757,14 @@ stats_messages(struct Client *source_p) static void stats_dnsbl(struct Client *source_p) { - rb_dlink_node *ptr; - struct Blacklist *blptr; + rb_dictionary_iter iter; + struct blacklist_stats *stats; - RB_DLINK_FOREACH(ptr, blacklist_list.head) + RB_DICTIONARY_FOREACH(stats, &iter, bl_stats) { - blptr = ptr->data; - /* use RPL_STATSDEBUG for now -- jilles */ - sendto_one_numeric(source_p, RPL_STATSDEBUG, "n :%d %s %s (%d)", - blptr->hits, - blptr->host, - blptr->status & CONF_ILLEGAL ? "disabled" : "active", - blptr->refcount); + sendto_one_numeric(source_p, RPL_STATSDEBUG, "n :%d %s", + stats->hits, (const char *)iter.cur->key); } } diff --git a/modules/m_user.c b/modules/m_user.c index cd8c7c13..d0360039 100644 --- a/modules/m_user.c +++ b/modules/m_user.c @@ -33,7 +33,6 @@ #include "msg.h" #include "parse.h" #include "modules.h" -#include "blacklist.h" #include "s_assert.h" static const char user_desc[] = @@ -92,7 +91,6 @@ do_local_user(struct Client *client_p, struct Client *source_p, make_user(source_p); - lookup_blacklists(source_p); source_p->flags |= FLAGS_SENTUSER; rb_strlcpy(source_p->info, realname, sizeof(source_p->info)); From cc4d393152cd39194793d61f811988ce9e7310b6 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Mon, 28 Mar 2016 02:19:34 -0500 Subject: [PATCH 88/96] ircd/authd: implement client noticing --- ircd/authd.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/ircd/authd.c b/ircd/authd.c index cfbbb52f..5d4a7f8f 100644 --- a/ircd/authd.c +++ b/ircd/authd.c @@ -189,7 +189,36 @@ parse_authd_reply(rb_helper * helper) rb_free(id); authd_decide_client(client_p, parv[3], parv[4], false, toupper(*parv[2]), parv[5], parv[6]); - return; + break; + case 'N': /* Notice to client */ + if(parv != 3) + { + iwarn("authd sent us a result with wrong number of arguments: got %d", parc); + restart_authd(); + return; + } + + if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX) + { + iwarn("authd sent us back a bad client ID"); + restart_authd(); + return; + } + + /* cid to uid */ + if((id = rb_dictionary_retrieve(cid_clients, RB_UINT_TO_POINTER((uint32_t)lcid))) == NULL) + { + iwarn("authd sent us back an unknown client ID"); + restart_authd(); + return; + } + + if((client_p = find_id(id)) == NULL) + /* Client vanished... we'll let the timeout code handle it */ + return; + + sendto_one_notice(client_p, ":%s", parv[2]); + break; case 'E': /* DNS Result */ if(parc != 5) { From ef0b13b9601803d8d4c14504c2bbf88e03d6acb6 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Mon, 28 Mar 2016 02:30:54 -0500 Subject: [PATCH 89/96] ircd/authd: timeout dead authd clients --- ircd/authd.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/ircd/authd.c b/ircd/authd.c index 5d4a7f8f..db646363 100644 --- a/ircd/authd.c +++ b/ircd/authd.c @@ -43,12 +43,14 @@ static int start_authd(void); static void parse_authd_reply(rb_helper * helper); static void restart_authd_cb(rb_helper * helper); +static EVH timeout_dead_authd_clients; rb_helper *authd_helper; static char *authd_path; uint32_t cid = 1; static rb_dictionary *cid_clients; +static struct ev_entry *timeout_ev; rb_dictionary *bl_stats; @@ -91,6 +93,9 @@ start_authd(void) if(bl_stats == NULL) bl_stats = rb_dictionary_create("blacklist statistics", strcasecmp); + if(timeout_ev == NULL) + timeout_ev = rb_event_addish("timeout_dead_authd_clients", timeout_dead_authd_clients, NULL, 1); + authd_helper = rb_helper_start("authd", authd_path, parse_authd_reply, restart_authd_cb); if(authd_helper == NULL) @@ -191,7 +196,7 @@ parse_authd_reply(rb_helper * helper) authd_decide_client(client_p, parv[3], parv[4], false, toupper(*parv[2]), parv[5], parv[6]); break; case 'N': /* Notice to client */ - if(parv != 3) + if(parc != 3) { iwarn("authd sent us a result with wrong number of arguments: got %d", parc); restart_authd(); @@ -461,6 +466,33 @@ authd_abort_client(struct Client *client_p) client_p->preClient->authd_cid = 0; } +static void +timeout_dead_authd_clients(void *notused __unused) +{ + rb_dictionary_iter iter; + char *id; + + RB_DICTIONARY_FOREACH(id, &iter, cid_clients) + { + struct Client *client_p; + if((client_p = find_id(id)) == NULL) + { + /* This shouldn't happen... but just in case... */ + rb_helper_write(authd_helper, "E %x", RB_POINTER_TO_UINT(iter.cur->key)); + rb_free(id); + rb_dictionary_delete(cid_clients, iter.cur->key); + continue; + } + + if(client_p->preClient->authd_timeout < rb_current_time()) + { + rb_helper_write(authd_helper, "E %x", client_p->preClient->authd_cid); + rb_free(id); + rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(client_p->preClient->authd_cid)); + } + } +} + /* Turn a cause char (who rejected us) into the name of the provider */ const char * get_provider_string(char cause) From 59d42a9fcb59922d2911936363abf7d096e72af9 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Mon, 28 Mar 2016 02:32:05 -0500 Subject: [PATCH 90/96] ircd/authd: use proper timeout values for clients --- ircd/authd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ircd/authd.c b/ircd/authd.c index db646363..fa7e77f7 100644 --- a/ircd/authd.c +++ b/ircd/authd.c @@ -403,8 +403,8 @@ authd_initiate_client(struct Client *client_p) #endif client_port = ntohs(((struct sockaddr_in *)&client_p->localClient->ip)->sin_port); - /* FIXME timeout should be configurable */ - client_p->preClient->authd_timeout = rb_current_time() + 45; + /* Add a bit of a fudge factor... */ + client_p->preClient->authd_timeout = rb_current_time() + ConfigFileEntry.connect_timeout + 5; rb_helper_write(authd_helper, "C %x %s %hu %s %hu", authd_cid, listen_ipaddr, listen_port, client_ipaddr, client_port); } From ad04380360ad4e3c8faadaea42ccdf6274fe2228 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Mon, 28 Mar 2016 02:42:20 -0500 Subject: [PATCH 91/96] ircd/authd: respect auth_disabled config option --- include/authd.h | 1 + ircd/authd.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/include/authd.h b/include/authd.h index 03405958..71990aa7 100644 --- a/include/authd.h +++ b/include/authd.h @@ -55,5 +55,6 @@ void add_blacklist(const char *host, const char *reason, uint8_t iptype, rb_dlin void del_blacklist(const char *host); void del_blacklist_all(void); void set_authd_timeout(const char *key, int timeout); +void ident_check_enable(bool enabled); #endif diff --git a/ircd/authd.c b/ircd/authd.c index fa7e77f7..d2514deb 100644 --- a/ircd/authd.c +++ b/ircd/authd.c @@ -316,6 +316,7 @@ configure_authd(void) set_authd_timeout("ident_timeout", GlobalSetOptions.ident_timeout); set_authd_timeout("rdns_timeout", ConfigFileEntry.connect_timeout); set_authd_timeout("blacklist_timeout", ConfigFileEntry.connect_timeout); + ident_check_enable(ConfigFileEntry.disable_auth); } static void @@ -576,3 +577,9 @@ set_authd_timeout(const char *key, int timeout) { rb_helper_write(authd_helper, "O %s %d", key, timeout); } + +void +ident_check_enable(bool enabled) +{ + rb_helper_write(authd_helper, "O ident_enabled %d", enabled ? 1 : 0); +} From a9b809c796ca6f3fa174c204ae67979ae1706622 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Mon, 28 Mar 2016 14:58:26 -0500 Subject: [PATCH 92/96] ircd_lexer: use correct variable here. ircd_paths[IRCD_PATH_ETC] is what's wanted, not IRCD_PATH_ETC. --- ircd/ircd_lexer.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ircd/ircd_lexer.l b/ircd/ircd_lexer.l index ccaf2e99..7112cc30 100644 --- a/ircd/ircd_lexer.l +++ b/ircd/ircd_lexer.l @@ -196,7 +196,7 @@ void cinclude(void) /* if its not found in PREFIX, look in IRCD_PATH_ETC */ char fnamebuf[BUFSIZE]; - snprintf(fnamebuf, sizeof(fnamebuf), "%s%c%s", IRCD_PATH_ETC, RB_PATH_SEPARATOR, c); + snprintf(fnamebuf, sizeof(fnamebuf), "%s%c%s", ircd_paths[IRCD_PATH_ETC], RB_PATH_SEPARATOR, c); tmp_fbfile_in = fopen(fnamebuf, "r"); /* wasnt found there either.. error. */ From c6ebd4fdad092d90838a9db1d838dcaca4f734aa Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Mon, 28 Mar 2016 15:15:16 -0500 Subject: [PATCH 93/96] authd: fix fencepost error --- authd/authd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/authd/authd.c b/authd/authd.c index 8aabf267..3846e209 100644 --- a/authd/authd.c +++ b/authd/authd.c @@ -78,9 +78,9 @@ handle_options(int parc, char *parv[]) { struct auth_opts_handler *handler; - if(parc < 4) + if(parc < 3) { - warn_opers(L_CRIT, "BUG: handle_options received too few parameters (at least 4 expected, got %d)", parc); + warn_opers(L_CRIT, "BUG: handle_options received too few parameters (at least 3 expected, got %d)", parc); return; } From 1345a41ddad0778330a4c6e356318fd30ea81c77 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Mon, 28 Mar 2016 16:46:52 -0500 Subject: [PATCH 94/96] authd: misc fixes --- authd/provider.c | 3 +++ authd/providers/ident.c | 14 ++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index b512b4a0..2bcd7c3c 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -274,6 +274,9 @@ start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_ #endif ((struct sockaddr_in *)&auth->c_addr)->sin_port = htons(auth->c_port); + rb_strlcpy(auth->hostname, "*", sizeof(auth->hostname)); + rb_strlcpy(auth->username, "*", sizeof(auth->username)); + memset(auth->data, 0, sizeof(auth->data)); auth->providers_starting = true; diff --git a/authd/providers/ident.c b/authd/providers/ident.c index 5f7740b5..357bc74d 100644 --- a/authd/providers/ident.c +++ b/authd/providers/ident.c @@ -46,6 +46,7 @@ static const char *messages[] = "*** Got Ident response", "*** No Ident response", "*** Cannot verify ident validity, ignoring ident", + "*** Ident disabled, not checking ident", }; typedef enum @@ -54,6 +55,7 @@ typedef enum REPORT_FOUND, REPORT_FAIL, REPORT_INVALID, + REPORT_DISABLED, } ident_message; static EVH timeout_ident_queries_event; @@ -321,11 +323,17 @@ static bool ident_start(struct auth_client *auth) struct rb_sockaddr_storage l_addr, c_addr; int family = GET_SS_FAMILY(&auth->c_addr); - if(!ident_enable || auth->data[PROVIDER_IDENT] != NULL) + if(auth->data[PROVIDER_IDENT] != NULL) { set_provider_done(auth, PROVIDER_IDENT); /* for blacklists */ return true; } + else if(!ident_enable) + { + notice_client(auth->cid, messages[REPORT_DISABLED]); + set_provider_done(auth, PROVIDER_IDENT); + return true; + } notice_client(auth->cid, messages[REPORT_LOOKUP]); @@ -394,9 +402,7 @@ add_conf_ident_timeout(const char *key __unused, int parc __unused, const char * static void set_ident_enabled(const char *key __unused, int parc __unused, const char **parv) { - ident_enable = (strcasecmp(parv[0], "true") == 0 || - strcasecmp(parv[0], "1") == 0 || - strcasecmp(parv[0], "enable") == 0); + ident_enable = (*parv[0] == '1'); } struct auth_opts_handler ident_options[] = From 50808796e016e1162c943a9e2393e57d2aaa7391 Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Mon, 28 Mar 2016 16:47:51 -0500 Subject: [PATCH 95/96] =?UTF-8?q?authd:=20It=20Works,=20Bitches=E2=84=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ircd/authd.c | 82 ++++++++++++++++++-------------------------------- ircd/ircd.c | 4 +-- ircd/newconf.c | 2 +- 3 files changed, 32 insertions(+), 56 deletions(-) diff --git a/ircd/authd.c b/ircd/authd.c index d2514deb..88819b75 100644 --- a/ircd/authd.c +++ b/ircd/authd.c @@ -48,7 +48,7 @@ static EVH timeout_dead_authd_clients; rb_helper *authd_helper; static char *authd_path; -uint32_t cid = 1; +uint32_t cid; static rb_dictionary *cid_clients; static struct ev_entry *timeout_ev; @@ -115,15 +115,15 @@ parse_authd_reply(rb_helper * helper) { ssize_t len; int parc; - char dnsBuf[READBUF_SIZE]; + char authdBuf[READBUF_SIZE]; char *parv[MAXPARA + 1]; long lcid; - char *id; + uint32_t cid; struct Client *client_p; - while((len = rb_helper_read(helper, dnsBuf, sizeof(dnsBuf))) > 0) + while((len = rb_helper_read(helper, authdBuf, sizeof(authdBuf))) > 0) { - parc = rb_string_to_array(dnsBuf, parv, MAXPARA+1); + parc = rb_string_to_array(authdBuf, parv, MAXPARA+1); switch (*parv[0]) { @@ -135,30 +135,23 @@ parse_authd_reply(rb_helper * helper) return; } - if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX) + if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX || lcid < 0) { - iwarn("authd sent us back a bad client ID"); + iwarn("authd sent us back a bad client ID: %ld", lcid); restart_authd(); return; } + cid = (uint32_t)lcid; + /* cid to uid (retrieve and delete) */ - if((id = rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER((uint32_t)lcid))) == NULL) + if((client_p = rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(cid))) == NULL) { - iwarn("authd sent us back an unknown client ID"); + iwarn("authd sent us back an unknown client ID %x", cid); restart_authd(); return; } - if((client_p = find_id(id)) == NULL) - { - /* Client vanished... */ - rb_free(id); - return; - } - - rb_free(id); - authd_decide_client(client_p, parv[2], parv[3], true, '\0', NULL, NULL); break; case 'R': /* Reject client */ @@ -169,30 +162,23 @@ parse_authd_reply(rb_helper * helper) return; } - if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX) + if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX || lcid < 0) { - iwarn("authd sent us back a bad client ID"); + iwarn("authd sent us back a bad client ID %ld", lcid); restart_authd(); return; } + cid = (uint32_t)lcid; + /* cid to uid (retrieve and delete) */ - if((id = rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER((uint32_t)lcid))) == NULL) + if((client_p = rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(cid))) == NULL) { - iwarn("authd sent us back an unknown client ID"); + iwarn("authd sent us back an unknown client ID %x", cid); restart_authd(); return; } - if((client_p = find_id(id)) == NULL) - { - /* Client vanished... */ - rb_free(id); - return; - } - - rb_free(id); - authd_decide_client(client_p, parv[3], parv[4], false, toupper(*parv[2]), parv[5], parv[6]); break; case 'N': /* Notice to client */ @@ -202,26 +188,24 @@ parse_authd_reply(rb_helper * helper) restart_authd(); return; } - - if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX) + + if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX || lcid < 0) { - iwarn("authd sent us back a bad client ID"); + iwarn("authd sent us back a bad client ID %ld", lcid); restart_authd(); return; } + cid = (uint32_t)lcid; + /* cid to uid */ - if((id = rb_dictionary_retrieve(cid_clients, RB_UINT_TO_POINTER((uint32_t)lcid))) == NULL) + if((client_p = rb_dictionary_retrieve(cid_clients, RB_UINT_TO_POINTER(cid))) == NULL) { - iwarn("authd sent us back an unknown client ID"); + iwarn("authd sent us back an unknown client ID %x", cid); restart_authd(); return; } - if((client_p = find_id(id)) == NULL) - /* Client vanished... we'll let the timeout code handle it */ - return; - sendto_one_notice(client_p, ":%s", parv[2]); break; case 'E': /* DNS Result */ @@ -315,8 +299,8 @@ configure_authd(void) /* These will do for now */ set_authd_timeout("ident_timeout", GlobalSetOptions.ident_timeout); set_authd_timeout("rdns_timeout", ConfigFileEntry.connect_timeout); - set_authd_timeout("blacklist_timeout", ConfigFileEntry.connect_timeout); - ident_check_enable(ConfigFileEntry.disable_auth); + set_authd_timeout("rbl_timeout", ConfigFileEntry.connect_timeout); + ident_check_enable(!ConfigFileEntry.disable_auth); } static void @@ -377,13 +361,13 @@ authd_initiate_client(struct Client *client_p) uint16_t client_port, listen_port; uint32_t authd_cid; - if(client_p->preClient == NULL || client_p->preClient->authd_cid == 0) + if(client_p->preClient == NULL || client_p->preClient->authd_cid != 0) return; authd_cid = client_p->preClient->authd_cid = generate_cid(); /* Collisions are extremely unlikely, so disregard the possibility */ - rb_dictionary_add(cid_clients, RB_UINT_TO_POINTER(authd_cid), rb_strdup(client_p->id)); + rb_dictionary_add(cid_clients, RB_UINT_TO_POINTER(authd_cid), client_p); /* Retrieve listener and client IP's */ rb_inet_ntop_sock((struct sockaddr *)&client_p->preClient->lip, listen_ipaddr, sizeof(listen_ipaddr)); @@ -476,14 +460,6 @@ timeout_dead_authd_clients(void *notused __unused) RB_DICTIONARY_FOREACH(id, &iter, cid_clients) { struct Client *client_p; - if((client_p = find_id(id)) == NULL) - { - /* This shouldn't happen... but just in case... */ - rb_helper_write(authd_helper, "E %x", RB_POINTER_TO_UINT(iter.cur->key)); - rb_free(id); - rb_dictionary_delete(cid_clients, iter.cur->key); - continue; - } if(client_p->preClient->authd_timeout < rb_current_time()) { @@ -517,7 +493,7 @@ add_blacklist(const char *host, const char *reason, uint8_t iptype, rb_dlink_lis { rb_dlink_node *ptr; struct blacklist_stats *stats = rb_malloc(sizeof(struct blacklist_stats)); - char filterbuf[BUFSIZE]; + char filterbuf[BUFSIZE] = "*"; size_t s = 0; /* Build a list of comma-separated values for authd. diff --git a/ircd/ircd.c b/ircd/ircd.c index 460b4009..535ce834 100644 --- a/ircd/ircd.c +++ b/ircd/ircd.c @@ -845,8 +845,6 @@ charybdis_main(int argc, char *argv[]) return 0; /* Why? We want the launcher to exit out. */ } - configure_authd(); - me.from = &me; me.servptr = &me; SetMe(&me); @@ -865,6 +863,8 @@ charybdis_main(int argc, char *argv[]) load_help(); open_logfiles(); + configure_authd(); + ilog(L_MAIN, "Server Ready"); /* We want try_connections to be called as soon as possible now! -- adrian */ diff --git a/ircd/newconf.c b/ircd/newconf.c index 347f0f25..454d1ea4 100644 --- a/ircd/newconf.c +++ b/ircd/newconf.c @@ -55,7 +55,7 @@ static struct alias_entry *yy_alias = NULL; static char *yy_blacklist_host = NULL; static char *yy_blacklist_reason = NULL; static uint8_t yy_blacklist_iptype = 0; -static rb_dlink_list yy_blacklist_filters; +static rb_dlink_list yy_blacklist_filters = { NULL, NULL, 0 }; static char *yy_privset_extends = NULL; From 1bebedd6fb6e92f359f5cd23c1410ef834c910cd Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Mon, 28 Mar 2016 16:49:26 -0500 Subject: [PATCH 96/96] authd: remove useless blacklist stats provider for now. Right now we keep track of this in ircd as stats is not ready for asynchronous replies. --- authd/providers/blacklist.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/authd/providers/blacklist.c b/authd/providers/blacklist.c index 922d4b2c..ad720988 100644 --- a/authd/providers/blacklist.c +++ b/authd/providers/blacklist.c @@ -546,6 +546,7 @@ add_conf_blacklist_timeout(const char *key, int parc, const char **parv) blacklist_timeout = timeout; } +#if 0 static void blacklist_stats(uint32_t rid, char letter) { @@ -563,6 +564,7 @@ blacklist_stats(uint32_t rid, char letter) stats_done(rid, letter); } +#endif struct auth_opts_handler blacklist_options[] = { @@ -582,5 +584,5 @@ struct auth_provider blacklist_provider = .cancel = blacklists_cancel, .completed = blacklists_initiate, .opt_handlers = blacklist_options, - .stats_handler = { 'B', blacklist_stats }, + /* .stats_handler = { 'B', blacklist_stats }, */ };