From 92a11018ec6d46d6c3cda510c5a59afd29e0148c Mon Sep 17 00:00:00 2001 From: Michael Poole Date: Sun, 5 Jul 2009 03:00:52 +0000 Subject: [PATCH] Fix SF bug #2694761 (iauth class assignment did not work correctly). git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/branches/u2_10_12_branch@1914 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- ChangeLog | 15 ++++++++++++ ircd/s_auth.c | 63 ++++++++++++++++++++++++++++++++++++++++++------ tools/iauth-test | 2 ++ 3 files changed, 72 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 67592a9..a865be6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2009-07-04 Michael Poole + + * ircd/s_auth.c (find_conf_client): New function. + (preregister_user): Use it to avoid assigning a second conf class + on client connection. + (auth_ping_timeout): Send the "T" message only if we do not kill + the client (and thus send a "D" message). + (auth_find_classs_conf): Do not allow IAuth to select a disabled + class. Unlink new conf items from GlobalConfList. + (iauth_cmd_done_client): Handle failures from attach_conf(). + (iauth_parse): Behave decently when a client is killed by the + message handler. + + * tools/iauth-test (%handlers): Add entries to help test this. + 2009-07-04 Michael Poole * include/channel.h (RevealDelayedJoinIfNeeded): Declare. diff --git a/ircd/s_auth.c b/ircd/s_auth.c index 6ea8361..b578c43 100644 --- a/ircd/s_auth.c +++ b/ircd/s_auth.c @@ -461,6 +461,26 @@ auth_verify_hostname(const char *host, int maxlen) return 1; /* it's a valid hostname */ } +/** Check whether a client already has a CONF_CLIENT configuration + * item. + * + * @return A pointer to the client's first CONF_CLIENT, or NULL if + * there are none. + */ +static struct ConfItem *find_conf_client(struct Client *cptr) +{ + struct SLink *list; + + for (list = cli_confs(cptr); list != NULL; list = list->next) { + struct ConfItem *aconf; + aconf = list->value.aconf; + if (aconf->status & CONF_CLIENT) + return aconf; + } + + return NULL; +} + /** Assign a client to a connection class. * @param[in] cptr Client to assign to a class. * @return Zero if client is kept, CPTR_KILLED if rejected. @@ -473,6 +493,10 @@ static int preregister_user(struct Client *cptr) ircd_strncpy(cli_user(cptr)->host, cli_sockhost(cptr), HOSTLEN); ircd_strncpy(cli_user(cptr)->realhost, cli_sockhost(cptr), HOSTLEN); + if (find_conf_client(cptr)) { + return 0; + } + switch (conf_check_client(cptr)) { case ACR_OK: @@ -766,11 +790,11 @@ int auth_ping_timeout(struct Client *cptr) /* Check for iauth timeout. */ if (FlagHas(&auth->flags, AR_IAUTH_PENDING)) { - sendto_iauth(cptr, "T"); if (IAuthHas(iauth, IAUTH_REQUIRED)) { sendheader(cptr, REPORT_FAIL_IAUTH); return exit_client_msg(cptr, cptr, &me, "Authorization Timeout"); } + sendto_iauth(cptr, "T"); FlagClr(&auth->flags, AR_IAUTH_PENDING); return check_auth_finished(auth); } @@ -1805,7 +1829,7 @@ static struct ConfItem *auth_find_class_conf(const char *class_name) /* Make sure the configuration class is valid. */ class = find_class(class_name); - if (!class) + if (!class || !class->valid) return NULL; /* Look for an existing ConfItem for the class. */ @@ -1822,6 +1846,13 @@ static struct ConfItem *auth_find_class_conf(const char *class_name) ConClass(class)); return NULL; } + /* make_conf() "helpfully" links the conf into GlobalConfList, + * which we do not want, so undo that. (Ugh.) + */ + if (aconf == GlobalConfList) { + GlobalConfList = aconf->next; + } + /* Back to business as usual. */ aconf->conn_class = class; aconf->next = aconf_list; aconf_list = aconf; @@ -1835,7 +1866,7 @@ static struct ConfItem *auth_find_class_conf(const char *class_name) * @param[in] cli Client referenced by command. * @param[in] parc Number of parameters. * @param[in] params Optional class name for client. - * @return One. + * @return Negative (CPTR_KILLED) if the connection is refused, one otherwise. */ static int iauth_cmd_done_client(struct IAuth *iauth, struct Client *cli, int parc, char **params) @@ -1851,9 +1882,24 @@ static int iauth_cmd_done_client(struct IAuth *iauth, struct Client *cli, struct ConfItem *aconf; aconf = auth_find_class_conf(params[0]); - if (aconf) - attach_conf(cli, aconf); - else + if (aconf) { + enum AuthorizationCheckResult acr; + + acr = attach_conf(cli, aconf); + switch (acr) { + case ACR_OK: + /* There should maybe be some way to set FLAG_DOID here.. */ + break; + case ACR_TOO_MANY_IN_CLASS: + ++ServerStats->is_ref; + return exit_client(cli, cli, &me, + "Sorry, your connection class is full - try " + "again later or try another server"); + default: + log_write(LS_IAUTH, L_ERROR, 0, "IAuth: Unexpected AuthorizationCheckResult %d from attach_conf()", acr); + break; + } + } else sendto_opmask_butone_ratelimited(NULL, SNO_AUTH, &warn_time, "iauth tried to use undefined class [%s]", params[0]); @@ -1867,7 +1913,8 @@ static int iauth_cmd_done_client(struct IAuth *iauth, struct Client *cli, * @param[in] cli Client referenced by command. * @param[in] parc Number of parameters. * @param[in] params Account name and optional class name for client. - * @return Non-zero if \a cli authorization should be checked for completion. + * @return Negative if the connection is refused, otherwise non-zero + * if \a cli authorization should be checked for completion. */ static int iauth_cmd_done_account(struct IAuth *iauth, struct Client *cli, int parc, char **params) @@ -2048,7 +2095,7 @@ static void iauth_parse(struct IAuth *iauth, char *message) /* Report mismatch to iauth. */ sendto_iauth(cli, "E Mismatch :[%s] != [%s]", params[1], ircd_ntoa(&cli_ip(cli))); - else if (handler(iauth, cli, parc - 3, params + 3)) + else if (handler(iauth, cli, parc - 3, params + 3) > 0) /* Handler indicated a possible state change. */ check_auth_finished(auth); } diff --git a/tools/iauth-test b/tools/iauth-test index 78e80ab..c3dd1f2 100755 --- a/tools/iauth-test +++ b/tools/iauth-test @@ -155,6 +155,8 @@ my %handlers = ( '127.0.0.2' => { C_reply => 'R account-1' }, '127.0.0.3' => { C_reply => 'k' }, '127.0.0.4' => { C_reply => 'K' }, + '127.0.0.5' => { C_reply => 'D Specials' }, + '127.0.0.6' => { C_reply => 'R account-1 Specials' }, '127.0.0.15' => { }, '127.0.0.16' => { H_reply => 'D' }, '127.0.0.17' => { H_reply => 'R account-2' }, -- 2.20.1