From: Gabriel B. <sh...@us...> - 2005-09-04 05:25:09
|
Update of /cvsroot/solidircd/solidircd-stable/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25136/src Added Files: klines.c m_gline.c Log Message: new files. --- NEW FILE: m_gline.c --- /************************************************************************ * Solid Internet Relay Chat Daemon, src/m_gline.c * Copyright (C) 2004 Juan Baez * * 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. */ /* $Id: m_gline.c,v 1.1 2005/09/04 05:25:00 sheik Exp $ */ #include "struct.h" #include "common.h" #include "sys.h" #include "numeric.h" #include "userban.h" #include "h.h" #if defined( HAVE_STRING_H ) #include <string.h> #else #include <strings.h> #endif extern char *smalldate(time_t); /* defined in s_misc.c */ extern int isnumber(char *); extern char *cluster(char *hostname); int m_gline(aClient *cptr, aClient *sptr, int parc, char *parv[]) { struct userBan *ban, *oban; char buffer[1024]; char *user, *host; char *reason; char *current_date; aClient *acptr; char tempuser[USERLEN + 2]; char temphost[HOSTLEN + 1]; int temporary_gline_time = 0; /* -Dianora */ time_t temporary_gline_time_seconds = 0; int time_specified = 0; char *argv; int i; char fbuf[512]; if (!IsAnOper(sptr) && !IsServer(sptr)) { sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } if (parc < 2) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "GLINE"); return 0; } argv = parv[1]; if ((temporary_gline_time = isnumber(argv)) >= 0) { if (parc < 3) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "GLINE"); return 0; } if (temporary_gline_time > 1080000) temporary_gline_time = 1080000; temporary_gline_time_seconds = (time_t) temporary_gline_time; argv = parv[2]; parc--; time_specified = 1; } else { temporary_gline_time = 0; } if(strchr(argv, ' ')) { sendto_one(sptr, ":%s NOTICE %s :Poorly formatted hostname " "(contains spaces). Be sure you are using the form: " "/quote GLINE [time] <user@host/nick> :<reason>", me.name, parv[0]); return 0; } if ((host = strchr(argv, '@')) || *argv == '*') { if (host) { user = argv; *(host++) = '\0'; } else { user = "*"; host = argv; } if (!*host) host = "*"; strncpyzt(tempuser, user, USERLEN + 2); strncpyzt(temphost, host, HOSTLEN); user = tempuser; host = temphost; } else { if (!(acptr = find_chasing(sptr, argv, NULL))) return 0; if (!acptr->user) return 0; if (IsServer(acptr)) { sendto_one(sptr, ":%s NOTICE %s :Can't GLINE a server, use @'s " "where appropriate", me.name, parv[0]); return 0; } tempuser[0] = '*'; if (*acptr->user->username == '~') strcpy(tempuser + 1, (char *) acptr->user->username + 1); else strcpy(tempuser + 1, acptr->user->username); user = tempuser; host = cluster(acptr->user->host); } if (time_specified) argv = parv[3]; else argv = parv[2]; /* FIXME: Shouldnt we use our hown DEFAULT_GLINE_TIME? - Tux`*/ #ifdef DEFAULT_KLINE_TIME if (time_specified <= 0) { temporary_gline_time = 30; temporary_gline_time_seconds = (time_t) temporary_gline_time *(time_t) 60; } #endif if (parc > 2) { if (*argv) reason = argv; else reason = "No reason"; } else reason = "No reason"; if (!match(user, "akjhfkahfasfjd") && !match(host, "ldksjfl.kss...kdjfd.jfklsjf")) { sendto_one(sptr, ":%s NOTICE %s :Can't G-Line *@*", me.name, parv[0]); return 0; } if (temporary_gline_time == 0 && strchr(reason, ':')) { sendto_one(sptr, ":%s NOTICE %s :Invalid character ':' in comment", me.name, parv[0]); return 0; } if (temporary_gline_time == 0 && strchr(reason, '#')) { sendto_one(sptr,":%s NOTICE %s :Invalid character '#' in comment", me.name, parv[0]); return 0; } ban = make_hostbased_ban(user, host); if(!ban) { sendto_one(sptr, ":%s NOTICE %s :Malformed ban %s@%s", me.name, parv[0], user, host); return 0; } if ((oban = find_userban_exact(ban, 0))) { if (oban->flags & UBAN_GLINE) { if (MyClient(sptr)) { sendto_one(sptr, ":%s NOTICE %s :[%s@%s] already %s for %s", me.name, parv[0], user, host, NETWORK_GLINNED_NAME, oban->reason ? oban->reason : "<No Reason>"); } else { /* The G-Line does not exist, and sptr is not our client. * However, we should still send it... - Tux` */ host = get_userban_host(ban, fbuf, 512); sendto_serv_butone(sptr, ":%s GLINE %d %s@%s :%s", parv[0], temporary_gline_time_seconds, user, host, reason); } userban_free(ban); return 0; } } current_date = smalldate((time_t) 0); ban->flags |= temporary_gline_time ? (UBAN_GLINE|UBAN_TEMPORARY) : (UBAN_GLINE); if (IsServer(sptr)) ircsprintf(buffer, "%s", reason); ircsprintf(buffer, "%s (%s)", reason, current_date); ban->reason = (char *) MyMalloc(strlen(buffer) + 1); strcpy(ban->reason, buffer); ban->timeset = timeofday; ban->duration = temporary_gline_time_seconds; if(user_match_ban(sptr, ban)) { sendto_one(sptr, ":%s NOTICE %s :You attempted to add a gline [%s@%s] " "which would affect yourself. Aborted.", me.name, parv[0], user, host); userban_free(ban); return 0; } add_hostbased_userban(ban); /* Check local users against it */ for (i = 0; i <= highest_fd; i++) { if (!(acptr = local[i]) || IsMe(acptr) || IsLog(acptr)) continue; if (IsPerson(acptr) && user_match_ban(acptr, ban)) { sendto_ops(NETWORK_GLINE_NAME" active for %s", get_client_name(acptr, FALSE)); sendto_serv_butone(sptr, ":%s GLOBOPS :%s active for %s", NETWORK_GLINE_NAME, me.name, get_client_name(acptr, FALSE)); ircsprintf(fbuf, NETWORK_GLINNED_NAME": %s", reason); exit_client(acptr, acptr, &me, fbuf); i--; } } host = get_userban_host(ban, fbuf, 512); if(temporary_gline_time) { sendto_realops("%s added a temporary %d sec(s) "NETWORK_GLINE_NAME" for [%s@%s] [%s]", parv[0], temporary_gline_time, user, host, reason); sendto_serv_butone(sptr, ":%s GLINE %d %s@%s :%s", parv[0], temporary_gline_time_seconds, user, host, reason); return 0; } sendto_realops("%s added a permanent gline for [%s@%s] [%s]", parv[0], user, host, reason); sendto_serv_butone(sptr, ":%s GLINE %d %s@%s :%s", parv[0], temporary_gline_time_seconds, user, host, reason); return 0; } int m_ungline(aClient *cptr, aClient *sptr, int parc, char *parv[]) { struct userBan *ban; char *user, *host; if (!IsAnOper(sptr)) { sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } if(parc<2) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0],"UNGLINE"); return 0; } if ((host = strchr(parv[1], '@')) || *parv[1] == '*') { if (host) { user = parv[1]; *(host++) = '\0'; } else { user = "*"; host = parv[1]; } } else { sendto_one(sptr, ":%s NOTICE %s :Invalid parameters",me.name, parv[0]); return 0; } if ((user[0] == '*') && (user[1] == '\0') && (host[0] == '*') && (host[1] == '\0')) { sendto_one(sptr, ":%s NOTICE %s :Cannot ungline everyone",me.name, parv[0]); return 0; } ban = make_hostbased_ban(user, host); if(ban) { struct userBan *oban; ban->flags |= (UBAN_GLINE|UBAN_TEMPORARY); if((oban = find_userban_exact(ban, UBAN_GLINE))) { char tmp[512]; host = get_userban_host(oban, tmp, 512); remove_userban(oban); userban_free(oban); userban_free(ban); if (MyClient(sptr)) sendto_one(sptr, ":%s NOTICE %s :G-line for [%s@%s] is removed", me.name, parv[0], user, host); sendto_ops("%s has removed the G-line for: [%s@%s] (%d matches)", parv[0], user, host, 1); sendto_serv_butone(cptr, ":%s UNGLINE %s@%s", sptr->name, user, host); return 0; } userban_free(ban); } if (MyClient(sptr)) sendto_one(sptr, ":%s NOTICE %s :No g-line for %s@%s was found", me.name, parv[0], user, host); return 0; } --- NEW FILE: klines.c --- /* * klines.c - Kline interface and storage * Copyright (C) 2005 Trevor Talbot and * the DALnet coding 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 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. */ /* $Id: klines.c,v 1.1 2005/09/04 05:25:00 sheik Exp $ */ /* * This is a simple K-Line journal implementation. When a K-Line with a * duration greater than KLINE_MIN_STORE_TIME is added, it is written to the * journal file (.klines): * + expireTS usermask hostmask reason * * When a K-Line is manually removed, it also results in a journal entry: * - usermask hostmask * * This allows K-Lines to be saved across restarts and rehashes. * * To keep the journal from getting larger than it needs to be, it is * periodically compacted: all active K-Lines are dumped into a new file, which * then replaces the active journal. This is done on startup as well as every * KLINE_STORE_COMPACT_THRESH journal entries. */ #include "struct.h" #include "common.h" #include "sys.h" #include "h.h" #include <fcntl.h> #include "userban.h" #include "numeric.h" static int journal = -1; static char journalfilename[512]; static int journalcount; void klinestore_add(struct userBan *); void klinestore_remove(struct userBan *); /* ircd.c */ extern int forked; /* s_misc.c */ extern char *smalldate(time_t); /* * m_kline * Add a local user@host ban. * * parv[0] = sender * parv[1] = duration (optional) * parv[2] = nick or user@host mask * parv[3] = reason (optional) */ int m_kline(aClient *cptr, aClient *sptr, int parc, char *parv[]) { char rbuf[512]; char *target; char *user; char *host; char *reason = "<no reason>"; int tkminutes = DEFAULT_KLINE_TIME; int tkseconds; long lval; struct userBan *ban; struct userBan *existing; if (!OPCanKline(sptr)) { sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } if (parc < 2) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "KLINE"); return 0; } lval = strtol(parv[1], &target, 10); if (*target != 0) { target = parv[1]; if (parc > 2) reason = parv[2]; } else { /* valid expiration time */ tkminutes = lval; if (parc < 3) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "KLINE"); return 0; } target = parv[2]; if (parc > 3) reason = parv[3]; } /* negative times, or times greater than a year, are permanent */ if (tkminutes < 0 || tkminutes > (365 * 24 * 60)) tkminutes = 0; tkseconds = tkminutes * 60; if ((host = strchr(target, '@'))) { *host++ = 0; user = target; } else { user = "*"; host = target; } if (!match(user, "akjhfkahfasfjd") && !match(host, "ldksjfl.kss...kdjfd.jfklsjf")) { sendto_one(sptr, ":%s NOTICE %s :KLINE: %s@%s mask is too wide", me.name, parv[0], user, host); return 0; } /* * XXX: nick target support to be re-added */ if (!(ban = make_hostbased_ban(user, host))) { sendto_one(sptr, ":%s NOTICE %s :KLINE: invalid ban mask %s@%s", me.name, parv[0], user, host); return 0; } ban->flags |= UBAN_LOCAL; /* only looks for duplicate klines, not akills */ if ((existing = find_userban_exact(ban, UBAN_LOCAL))) { sendto_one(sptr, ":%s NOTICE %s :KLINE: %s@%s is already %s: %s", me.name, parv[0], user, host, LOCAL_BANNED_NAME, existing->reason ? existing->reason : "<no reason>"); userban_free(ban); return 0; } if (user_match_ban(sptr, ban)) { sendto_one(sptr, ":%s NOTICE %s :KLINE: %s@%s matches you, rejected", me.name, parv[0], user, host); userban_free(ban); return 0; } ircsnprintf(rbuf, sizeof(rbuf), "%s (%s)", reason, smalldate(0)); ban->reason = MyMalloc(strlen(rbuf) + 1); strcpy(ban->reason, rbuf); if (tkseconds) { ban->flags |= UBAN_TEMPORARY; ban->timeset = NOW; ban->duration = tkseconds; } add_hostbased_userban(ban); if (!tkminutes || tkminutes >= KLINE_MIN_STORE_TIME) klinestore_add(ban); userban_sweep(ban); host = get_userban_host(ban, rbuf, sizeof(rbuf)); if (tkminutes) sendto_realops("%s added temporary %d min. "LOCAL_BAN_NAME" for" " [%s@%s] [%s]", parv[0], tkminutes, user, host, reason); else sendto_realops("%s added "LOCAL_BAN_NAME" for [%s@%s] [%s]", parv[0], user, host, reason); return 0; } /* * m_unkline * Remove a local user@host ban. * * parv[0] = sender * parv[1] = user@host mask */ int m_unkline(aClient *cptr, aClient *sptr, int parc, char *parv[]) { char hbuf[512]; char *user; char *host; struct userBan *ban; struct userBan *existing; if (!OPCanUnKline(sptr)) { sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } if (parc < 2) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "UNKLINE"); return 0; } if ((host = strchr(parv[1], '@'))) { *host++ = 0; user = parv[1]; } else { user = "*"; host = parv[1]; } if (!(ban = make_hostbased_ban(user, host))) { sendto_one(sptr, ":%s NOTICE %s :UNKLINE: No such ban %s@%s", me.name, parv[0], user, host); return 0; } ban->flags |= UBAN_LOCAL; existing = find_userban_exact(ban, UBAN_LOCAL); host = get_userban_host(ban, hbuf, sizeof(hbuf)); userban_free(ban); if (!existing) { sendto_one(sptr, ":%s NOTICE %s :UNKINE: No such ban %s@%s", me.name, parv[0], user, host); return 0; } if (existing->flags & UBAN_CONF) { sendto_one(sptr, ":%s NOTICE %s :UNKLINE: %s@%s is specified in the" " configuration file and cannot be removed online", me.name, parv[0], user, host); return 0; } remove_userban(existing); klinestore_remove(existing); userban_free(existing); sendto_ops("%s has removed the K-Line for: [%s@%s]", parv[0], user, host); return 0; } static void ks_error(char *msg) { if (!forked) puts(msg); else sendto_ops("%s", msg); } /* * Writes a K-Line to the appropriate file. */ void ks_write(int f, char type, struct userBan *ub) { char outbuf[1024]; char cidr[4] = ""; time_t expiretime = 0; char *user = "*"; char *reason = ""; char *host = ub->h; int len; /* userban.c */ unsigned int netmask_to_cidr(unsigned int); if (ub->flags & UBAN_TEMPORARY) expiretime = ub->timeset + ub->duration; if (ub->u) user = ub->u; if (ub->reason) reason = ub->reason; if (ub->flags & (UBAN_CIDR4|UBAN_CIDR4BIG)) { host = inetntoa((char *)&ub->cidr4ip); ircsprintf(cidr, "/%d", netmask_to_cidr(ntohl(ub->cidr4mask))); } if (type == '+') len = ircsprintf(outbuf, "%c %d %s %s%s %s\n", type, (int)expiretime, user, host, cidr, reason); else len = ircsprintf(outbuf, "%c %s %s%s\n", type, user, host, cidr); write(f, outbuf, len); } /* * Parses a K-Line entry from a storage journal line. * Returns 0 on invalid input, 1 otherwise. */ static int ks_read(char *s) { char type; time_t duration = 0; char *user; char *host; char *reason = ""; struct userBan *ban; struct userBan *existing; type = *s++; /* bad type */ if (type != '+' && type != '-') return 0; /* malformed */ if (*s++ != ' ') return 0; if (type == '+') { duration = strtol(s, &s, 0); if (duration) { /* already expired */ if (NOW >= duration) return 1; duration -= NOW; } /* malformed */ if (*s++ != ' ') return 0; } /* usermask */ user = s; while (*s && *s != ' ') s++; /* malformed */ if (*s != ' ') return 0; /* mark end of user mask */ *s++ = 0; /* hostmask */ host = s; while (*s && *s != ' ') s++; if (type == '+') { /* malformed */ if (*s != ' ') return 0; /* mark end of host mask */ *s++ = 0; /* reason is the only thing left */ reason = s; } ban = make_hostbased_ban(user, host); if (!ban) return 0; ban->flags |= UBAN_LOCAL; if (type == '+') { if (duration) { ban->flags |= UBAN_TEMPORARY; ban->timeset = NOW; ban->duration = duration; } if (*reason) DupString(ban->reason, reason); add_hostbased_userban(ban); } else { existing = find_userban_exact(ban, UBAN_LOCAL|UBAN_CONF); userban_free(ban); /* add may have been skipped due to being expired, so not an error */ if (!existing) return 1; remove_userban(existing); userban_free(existing); } return 1; } /* * Compact K-Line store: dump active klines to a new file and remove the * current journal. * Returns 1 on success, 0 on failure. */ int klinestore_compact(void) { char buf1[512]; int newfile; /* userban.c */ extern void ks_dumpklines(int); if (forked) sendto_ops_lev(DEBUG_LEV, "Compacting K-Line store..."); journalcount = 0; /* open a compaction file to dump all active klines to */ ircsnprintf(buf1, sizeof(buf1), "%s/.klines_c", dpath); newfile = open(buf1, O_WRONLY|O_CREAT|O_TRUNC, 0700); if (newfile < 0) { ircsnprintf(buf1, sizeof(buf1), "ERROR: Unable to create K-Line" " compaction file .klines_c: %s", strerror(errno)); ks_error(buf1); return 0; } /* do the dump */ ks_dumpklines(newfile); close(newfile); /* close active storage file, rename compaction file, and reopen */ if (journal >= 0) { close(journal); journal = -1; } if (rename(buf1, journalfilename) < 0) { ircsnprintf(buf1, sizeof(buf1), "ERROR: Unable to rename K-Line" " compaction file .klines_c to .klines: %s", strerror(errno)); ks_error(buf1); return 0; } journal = open(journalfilename, O_WRONLY|O_APPEND, 0700); if (journal < 0) { ircsnprintf(buf1, sizeof(buf1), "ERROR: Unable to reopen K-Line" " storage file .klines: %s", strerror(errno)); ks_error(buf1); return 0; } return 1; } /* * Add a K-Line to the active store. */ void klinestore_add(struct userBan *ban) { if (journal >= 0) ks_write(journal, '+', ban); if (++journalcount > KLINE_STORE_COMPACT_THRESH) klinestore_compact(); } /* * Remove a K-Line from the active store. */ void klinestore_remove(struct userBan *ban) { if (journal >= 0) ks_write(journal, '-', ban); if (++journalcount > KLINE_STORE_COMPACT_THRESH) klinestore_compact(); } /* * Initialize K-Line storage. Pass 1 when klines don't need to be reloaded. * Returns 0 on failure, 1 otherwise. */ int klinestore_init(int noreload) { char buf1[1024]; FILE *jf; ircsnprintf(journalfilename, sizeof(journalfilename), "%s/.klines", dpath); if (journal >= 0) { if (noreload) return 1; close(journal); journal = -1; } /* "a+" to create if it doesn't exist */ jf = fopen(journalfilename, "a+"); if (!jf) { ircsnprintf(buf1, sizeof(buf1), "ERROR: Unable to open K-Line storage" " file .klines: %s", strerror(errno)); ks_error(buf1); return 0; } rewind(jf); /* replay journal */ while (fgets(buf1, sizeof(buf1), jf)) { char *s = strchr(buf1, '\n'); /* no newline, consider it malformed and stop here */ if (!s) break; *s = 0; if (!ks_read(buf1)) break; } fclose(jf); /* this will reopen the journal for appending */ return klinestore_compact(); } |