/* * Unreal Internet Relay Chat Daemon, src/s_svs.c * (C) 2000-2001 Carsten V. Munk and the UnrealIRCd 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. */ #include "struct.h" #include "common.h" #include "sys.h" #include "numeric.h" #include "channel.h" #include #ifndef _WIN32 #include #include #else #include #endif #include #ifdef __hpux #include "inet.h" #endif #if defined(PCS) || defined(AIX) || defined(SVR3) #include #endif #include #include "h.h" #include "proto.h" extern ircstats IRCstats; aConfiguration iConf; #define STAR1 OFLAG_SADMIN|OFLAG_ADMIN|OFLAG_NETADMIN|OFLAG_COADMIN #define STAR2 OFLAG_ZLINE|OFLAG_HIDE|OFLAG_WHOIS MODVAR int oper_access[] = { ~(STAR1 | STAR2), '*', OFLAG_LOCAL, 'o', OFLAG_GLOBAL, 'O', OFLAG_REHASH, 'r', OFLAG_DIE, 'D', OFLAG_RESTART, 'R', OFLAG_HELPOP, 'h', OFLAG_GLOBOP, 'g', OFLAG_WALLOP, 'w', OFLAG_LOCOP, 'l', OFLAG_LROUTE, 'c', OFLAG_GROUTE, 'L', OFLAG_LKILL, 'k', OFLAG_GKILL, 'K', OFLAG_KLINE, 'b', OFLAG_UNKLINE, 'B', OFLAG_LNOTICE, 'n', OFLAG_GNOTICE, 'G', OFLAG_ADMIN, 'A', OFLAG_SADMIN, 'a', OFLAG_NETADMIN, 'N', OFLAG_COADMIN, 'C', OFLAG_ZLINE, 'z', OFLAG_WHOIS, 'W', OFLAG_HIDE, 'H', OFLAG_TKL, 't', OFLAG_GZL, 'Z', OFLAG_OVERRIDE, 'v', OFLAG_UMODEQ, 'q', OFLAG_DCCDENY, 'd', OFLAG_ADDLINE, 'X', OFLAG_TSCTL, 'T', 0, 0 }; MODVAR char oflagbuf[128]; char *oflagstr(long oflag) { int *i, flag; char m; char *p = oflagbuf; for (i = &oper_access[6], m = *(i + 1); (flag = *i); i += 2, m = *(i + 1)) { if (oflag & flag) { *p = m; p++; } } *p = '\0'; return oflagbuf; } /* ok, given a mask, our job is to determine * wether or not it's a safe mask to banish... * * userhost= mask to verify * ipstat= TRUE == it's an ip * FALSE == it's a hostname * UNSURE == we need to find out * return value * TRUE == mask is ok * FALSE == mask is not ok * UNSURE == [unused] something went wrong */ int advanced_check(char *userhost, int ipstat) { register int retval = TRUE; char *up = NULL, *p, *thisseg; int numdots = 0, segno = 0, numseg, i = 0; char *ipseg[10 + 2]; char safebuffer[512] = ""; /* buffer strtoken() can mess up to its heart's content...;> */ strlcpy(safebuffer, userhost, sizeof safebuffer); #define userhost safebuffer #define IP_WILDS_OK(x) ((x)<2? 0 : 1) if (ipstat == UNSURE) { ipstat = TRUE; for (; *up; up++) { if (*up == '.') numdots++; if (!isdigit(*up) && !ispunct(*up)) { ipstat = FALSE; continue; } } if (numdots != 3) ipstat = FALSE; if (numdots < 1 || numdots > 9) return (0); } /* fill in the segment set */ { int l = 0; for (segno = 0, i = 0, thisseg = strtoken(&p, userhost, "."); thisseg; thisseg = strtoken(&p, NULL, "."), i++) { l = strlen(thisseg) + 2; ipseg[segno] = calloc(1, l); strncpy(ipseg[segno++], thisseg, l); } } if (segno < 2 && ipstat == TRUE) retval = FALSE; numseg = segno; if (ipstat == TRUE) for (i = 0; i < numseg; i++) { if (!IP_WILDS_OK(i) && (index(ipseg[i], '*') || index(ipseg[i], '?'))) retval = FALSE; /* The person who wrote this function was braindead --Stskeeps */ /* MyFree(ipseg[i]); */ } else { int wildsok = 0; for (i = 0; i < numseg; i++) { /* for hosts, let the mask extent all the way to the second-level domain... */ wildsok = 1; if (i == numseg || (i + 1) == numseg) wildsok = 0; if (wildsok == 0 && (index(ipseg[i], '*') || index(ipseg[i], '?'))) { retval = FALSE; } /* MyFree(ipseg[i]); */ } } return (retval); #undef userhost #undef IP_WILDS_OK } /* Function to return a group of tokens -- codemastr */ void strrangetok(char *in, char *out, char tok, short first, short last) { int i = 0, tokcount = 0, j = 0; first--; last--; while(in[i]) { if (in[i] == tok) { tokcount++; if (tokcount == first) i++; } if (tokcount >= first && (tokcount <= last || last == -1)) { out[j] = in[i]; j++; } i++; } out[j] = 0; } static int recursive_alias = 0; int m_alias(aClient *cptr, aClient *sptr, int parc, char *parv[], char *cmd) { ConfigItem_alias *alias; aClient *acptr; int ret; if (!(alias = Find_alias(cmd))) { sendto_one(sptr, ":%s %d %s %s :Unknown command", me.name, ERR_UNKNOWNCOMMAND, parv[0], cmd); return 0; } /* If it isn't an ALIAS_COMMAND, we require a paramter ... We check ALIAS_COMMAND LATER */ if (alias->type != ALIAS_COMMAND && (parc < 2 || *parv[1] == '\0')) { sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]); return -1; } if (alias->type == ALIAS_SERVICES) { if (SERVICES_NAME && (acptr = find_person(alias->nick, NULL))) { if (alias->spamfilter && (ret = dospamfilter(sptr, parv[1], SPAMF_USERMSG, alias->nick, 0, NULL)) < 0) return ret; sendto_one(acptr, ":%s PRIVMSG %s@%s :%s", parv[0], alias->nick, SERVICES_NAME, parv[1]); } else sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name, parv[0], alias->nick); } else if (alias->type == ALIAS_STATS) { if (STATS_SERVER && (acptr = find_person(alias->nick, NULL))) { if (alias->spamfilter && (ret = dospamfilter(sptr, parv[1], SPAMF_USERMSG, alias->nick, 0, NULL)) < 0) return ret; sendto_one(acptr, ":%s PRIVMSG %s@%s :%s", parv[0], alias->nick, STATS_SERVER, parv[1]); } else sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name, parv[0], alias->nick); } else if (alias->type == ALIAS_NORMAL) { if ((acptr = find_person(alias->nick, NULL))) { if (alias->spamfilter && (ret = dospamfilter(sptr, parv[1], SPAMF_USERMSG, alias->nick, 0, NULL)) < 0) return ret; if (MyClient(acptr)) sendto_one(acptr, ":%s!%s@%s PRIVMSG %s :%s", parv[0], sptr->user->username, GetHost(sptr), alias->nick, parv[1]); else sendto_one(acptr, ":%s PRIVMSG %s :%s", parv[0], alias->nick, parv[1]); } else sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], alias->nick); } else if (alias->type == ALIAS_CHANNEL) { aChannel *chptr; if ((chptr = find_channel(alias->nick, NULL))) { if (!can_send(sptr, chptr, parv[1], 0)) { if (alias->spamfilter && (ret = dospamfilter(sptr, parv[1], SPAMF_CHANMSG, chptr->chname, 0, NULL)) < 0) return ret; sendto_channelprefix_butone(sptr, sptr, chptr, PREFIX_ALL, ":%s PRIVMSG %s :%s", parv[0], chptr->chname, parv[1]); return 0; } } sendto_one(sptr, err_str(ERR_CANNOTDOCOMMAND), me.name, parv[0], cmd, "You may not use this command at this time"); } else if (alias->type == ALIAS_COMMAND) { ConfigItem_alias_format *format; char *ptr = ""; if (!(parc < 2 || *parv[1] == '\0')) ptr = parv[1]; for (format = alias->format; format; format = (ConfigItem_alias_format *)format->next) { if (regexec(&format->expr, ptr, 0, NULL, 0) == 0) { /* Parse the parameters */ int i = 0, j = 0, k = 1; char output[1024], current[1024]; char nums[4]; bzero(current, sizeof current); bzero(output, sizeof output); while(format->parameters[i] && j < 500) { k = 0; if (format->parameters[i] == '%') { i++; if (format->parameters[i] == '%') output[j++] = '%'; else if (isdigit(format->parameters[i])) { for(; isdigit(format->parameters[i]) && k < 2; i++, k++) { nums[k] = format->parameters[i]; } nums[k] = 0; i--; if (format->parameters[i+1] == '-') { strrangetok(ptr, current, ' ', atoi(nums),0); i++; } else strrangetok(ptr, current, ' ', atoi(nums), atoi(nums)); if (!current) continue; if (j + strlen(current)+1 >= 500) break; strlcat(output, current, sizeof output); j += strlen(current); } else if (format->parameters[i] == 'n' || format->parameters[i] == 'N') { strlcat(output, parv[0], sizeof output); j += strlen(parv[0]); } else { output[j++] = '%'; output[j++] = format->parameters[i]; } i++; continue; } output[j++] = format->parameters[i++]; } output[j] = 0; /* Now check to make sure we have something to send */ if (strlen(output) == 0) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, sptr->name, cmd); return -1; } if (format->type == ALIAS_SERVICES) { if (SERVICES_NAME && (acptr = find_person(format->nick, NULL))) { if (alias->spamfilter && (ret = dospamfilter(sptr, output, SPAMF_USERMSG, format->nick, 0, NULL)) < 0) return ret; sendto_one(acptr, ":%s PRIVMSG %s@%s :%s", parv[0], format->nick, SERVICES_NAME, output); } else sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name, parv[0], format->nick); } else if (format->type == ALIAS_STATS) { if (STATS_SERVER && (acptr = find_person(format->nick, NULL))) { if (alias->spamfilter && (ret = dospamfilter(sptr, output, SPAMF_USERMSG, format->nick, 0, NULL)) < 0) return ret; sendto_one(acptr, ":%s PRIVMSG %s@%s :%s", parv[0], format->nick, STATS_SERVER, output); } else sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name, parv[0], format->nick); } else if (format->type == ALIAS_NORMAL) { if ((acptr = find_person(format->nick, NULL))) { if (alias->spamfilter && (ret = dospamfilter(sptr, output, SPAMF_USERMSG, format->nick, 0, NULL)) < 0) return ret; if (MyClient(acptr)) sendto_one(acptr, ":%s!%s@%s PRIVMSG %s :%s", parv[0], sptr->user->username, IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost, format->nick, output); else sendto_one(acptr, ":%s PRIVMSG %s :%s", parv[0], format->nick, output); } else sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], format->nick); } else if (format->type == ALIAS_CHANNEL) { aChannel *chptr; if ((chptr = find_channel(format->nick, NULL))) { if (!can_send(sptr, chptr, output, 0)) { if (alias->spamfilter && (ret = dospamfilter(sptr, output, SPAMF_CHANMSG, chptr->chname, 0, NULL)) < 0) return ret; sendto_channelprefix_butone(sptr, sptr, chptr, PREFIX_ALL, ":%s PRIVMSG %s :%s", parv[0], chptr->chname, parv[1]); return 0; } } sendto_one(sptr, err_str(ERR_CANNOTDOCOMMAND), me.name, parv[0], cmd, "You may not use this command at this time"); } else if (format->type == ALIAS_REAL) { int ret; char mybuf[500]; snprintf(mybuf, sizeof(mybuf), "%s %s", format->nick, output); if (recursive_alias) { sendto_one(sptr, err_str(ERR_CANNOTDOCOMMAND), me.name, parv[0], cmd, "You may not use this command at this time -- recursion"); return -1; } recursive_alias = 1; ret = parse(sptr, mybuf, mybuf+strlen(mybuf)); recursive_alias = 0; return ret; } break; } } return 0; } return 0; }