diff options
author | Jonas Gunz <himself@jonasgunz.de> | 2020-05-25 20:09:04 +0200 |
---|---|---|
committer | Jonas Gunz <himself@jonasgunz.de> | 2020-05-25 20:09:04 +0200 |
commit | 4440a86cfa359b8e40a484a2cd46d33db5455d8a (patch) | |
tree | f5c0c59aebf0058ae97e7ef8b5fb8017f459a05a /iauth/mod_lhex.c | |
download | ircd-4440a86cfa359b8e40a484a2cd46d33db5455d8a.tar.gz |
Initial
Diffstat (limited to 'iauth/mod_lhex.c')
-rw-r--r-- | iauth/mod_lhex.c | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/iauth/mod_lhex.c b/iauth/mod_lhex.c new file mode 100644 index 0000000..07e7e88 --- /dev/null +++ b/iauth/mod_lhex.c @@ -0,0 +1,318 @@ +/************************************************************************ + * IRC - Internet Relay Chat, iauth/mod_lhex.c + * Copyright (C) 1998-1999 Christophe Kalt and Andrew Snare + * + * 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef lint +static char rcsid[] = "@(#)$Id mod_lhex.c,v 1.12 1999/02/06 21:43:52 kalt Exp $"; +#endif + +#include "os.h" +#include "a_defines.h" +#define MOD_LHEX_C +#include "a_externs.h" +#undef MOD_LHEX_C + +/****************************** PRIVATE *************************************/ +#define LHEXPORT 9674 + +struct lhex_private +{ + /* stats */ + u_int ok, banned; + u_int tried, clean, timeout; +}; + +/******************************** PUBLIC ************************************/ + +/* + * lhex_init + * + * This procedure is called when a particular module is loaded. + * Returns NULL if everything went fine, + * an error message otherwise. + */ +char * +lhex_init(self) +AnInstance *self; +{ + struct lhex_private *mydata; + +#if defined(INET6) + return "IPv6 unsupported."; +#endif + if(self->opt == NULL) + return "Aie! no option(s): no LHEx server to connect to!"; + if(!inetaton(self->opt,NULL)) + return "Aie! Option wasn't a valid IP address!"; + + /* Allocate the module data */ + mydata = (struct lhex_private *) malloc(sizeof(struct lhex_private)); + bzero((char *) mydata, sizeof(struct lhex_private)); + + self->popt = mystrdup(self->opt); + self->data = mydata; + return NULL; +} + +/* + * lhex_release + * + * This procedure is called when a particular module is unloaded. + */ +void +lhex_release(self) +AnInstance *self; +{ + struct lhex_private *mydata = self->data; + free(mydata); + free(self->popt); +} + +/* + * lhex_stats + * + * This procedure is called regularly to update statistics sent to ircd. + */ +void +lhex_stats(self) +AnInstance *self; +{ + struct lhex_private *mydata = self->data; + + sendto_ircd("S lhex ok %u banned %u", mydata->ok, mydata->banned); + sendto_ircd("S lhex tried %u aborted %u / %u", + mydata->tried, mydata->clean, mydata->timeout); +} + +/* + * lhex_start + * + * This procedure is called to start the LHEx check procedure. + * Returns 0 if everything went fine, + * anything else otherwise (nothing to be done, or failure) + * + * It is responsible for sending error messages where appropriate. + * In case of failure, it's responsible for cleaning up (e.g. lhex_clean + * will NOT be called) + */ +int +lhex_start(cl) +u_int cl; +{ + char *error; + int fd; + struct lhex_private *mydata = cldata[cl].instance->data; + + if (cldata[cl].state & A_DENY) + { + /* no point of doing anything */ + DebugLog((ALOG_DLHEX, 0, + "lhex_start(%d): A_DENY already set ", cl)); + return -1; + } + + DebugLog((ALOG_DLHEX, 0, "lhex_start(%d): Connecting to %s", cl, + cldata[cl].instance->opt)); + mydata->tried += 1; + fd= tcp_connect(cldata[cl].ourip, cldata[cl].instance->opt, + LHEXPORT, &error); + if (fd < 0) + { + DebugLog((ALOG_DLHEX, 0, + "lhex_start(%d): tcp_connect() reported %s", + cl, error)); + return -1; + } + + cldata[cl].wfd = fd; /*so that lhex_work() is called when connected*/ + return 0; +} + +/* + * lhex_work + * + * This procedure is called whenever there's new data in the buffer. + * Returns 0 if everything went fine, and there is more work to be done, + * Returns -1 if the module has finished its work (and cleaned up). + * + * It is responsible for sending error messages where appropriate. + */ +int +lhex_work(cl) +u_int cl; +{ + DebugLog((ALOG_DLHEX, 0, "lhex_work(%d): %d %d buflen=%d", cl, + cldata[cl].rfd, cldata[cl].wfd, cldata[cl].buflen)); + if (cldata[cl].wfd > 0) + { + /* + ** We haven't sent the query yet, the connection was just + ** established. + */ + char query[3+7+6+4+USERLEN+2*HOSTLEN+8+3];/*strlen(atoi(cl))<=8*/ + char *ident = cldata[cl].authuser; + + /* This is part of every request */ + sprintf(query, "id:%u ip:%s", cl, cldata[cl].itsip); + + /* These bits are optional, depending on what's known */ + if (ident) + { + strcat(query, " ident:"); + strcat(query, ident); + } + if (cldata[cl].state & A_GOTH) + { + strcat(query, " host:"); + strcat(query, cldata[cl].host); + } + /* Terminate the request */ + strcat(query, "\r\n"); + + DebugLog((ALOG_DLHEX, 0, "lhex_work(%u): Sending query [%s]", + cl, query)); + if (write(cldata[cl].wfd, query, strlen(query)) < 0) + { + /* most likely the connection failed */ + DebugLog((ALOG_DLHEX, 0, + "lhex_work(%u): write() failed: %s", + cl, strerror(errno))); + close(cldata[cl].wfd); + cldata[cl].rfd = cldata[cl].wfd = 0; + return 1; + } + cldata[cl].rfd = cldata[cl].wfd; + cldata[cl].wfd = 0; + } + else + { + /* data's in from the other end */ + char *ch, *nch; + u_int id; + int retval = 0; + + cldata[cl].inbuffer[cldata[cl].buflen] = '\0'; + nch = cldata[cl].inbuffer; + while((nch < (cldata[cl].inbuffer + cldata[cl].buflen)) && + (ch = index(nch, '\r')) && !retval) + { + char *och = nch; + nch = ch+2; /* Skip the \r\n */ + *ch = '\0'; + DebugLog((ALOG_DLHEX, 0, "lhex_work(%u): Got [%s]", + cl, och)); + + /* Have a go at parsing the return info */ + if(sscanf(och, "%u", &id) != 1) + DebugLog((ALOG_DLHEX, 0, "lhex_work(%u): " + "Malformed data!", cl)); + else + { + struct lhex_private *d=cldata[cl].instance->data; + ch = index(och, ':'); + while(isspace(*(++ch))); + if(!strcmp(ch,"OK")) + { + d->ok++; + DebugLog((ALOG_DLHEX, 0, + "lhex_work(%u): OK", id)); + close(cldata[cl].rfd); + cldata[cl].rfd = 0; + retval = -1; + } + else if(!strcmp(ch,"Not OK")) + { + d->banned++; + DebugLog((ALOG_DLHEX, 0, + "lhex_work(%u): Not OK", id)); + cldata[cl].state |= A_DENY; + /* I really wish we could send the + client a "reason" here :P */ + sendto_ircd("K %d %s %u ", cl, + cldata[cl].itsip, + cldata[cl].itsport); + close(cldata[cl].rfd); + cldata[cl].rfd = 0; + retval = -1; + } + else + { +#if 0 + /* Call this info for the client */ + sendto_ircd("I %d %s %u NOTICE AUTH :%s", + cl, cldata[cl].itsip, + cldata[cl].itsport, ch); +#endif + retval = 0; + } + } + } + return retval; + } + return 0; +} + +/* + * lhex_clean + * + * This procedure is called whenever the module should interrupt its work. + * It is responsible for cleaning up any allocated data, and in particular + * closing file descriptors. + */ +void +lhex_clean(cl) +u_int cl; +{ + struct lhex_private *mydata = cldata[cl].instance->data; + + mydata->clean += 1; + DebugLog((ALOG_DLHEX, 0, "lhex_clean(%d): cleaning up", cl)); + /* + ** only one of rfd and wfd may be set at the same time, + ** in any case, they would be the same fd, so only close() once + */ + if (cldata[cl].rfd) + close(cldata[cl].rfd); + else if (cldata[cl].wfd) + close(cldata[cl].wfd); + cldata[cl].rfd = cldata[cl].wfd = 0; +} + +/* + * lhex_timeout + * + * This procedure is called whenever the timeout set by the module is + * reached. + * + * Returns 0 if things are okay, -1 if check was aborted. + */ +int +lhex_timeout(cl) +u_int cl; +{ + struct lhex_private *mydata = cldata[cl].instance->data; + + mydata->timeout += 1; + DebugLog((ALOG_DLHEX, 0, "lhex_timeout(%d): calling lhex_clean ", cl)); + lhex_clean(cl); + return -1; +} + +aModule Module_lhex = + { "lhex", lhex_init, lhex_release, lhex_stats, + lhex_start, lhex_work, lhex_timeout, lhex_clean }; |