diff -ru --new-file irc2.10.3p3/common/bsd.c irc2.10.3p3+sd7/common/bsd.c --- irc2.10.3p3/common/bsd.c Sun Mar 4 21:21:56 2001 +++ irc2.10.3p3+sd7/common/bsd.c Mon Feb 3 14:31:07 2003 @@ -105,7 +105,11 @@ #ifndef NOWRITEALARM (void)alarm(WRITEWAITDELAY); #endif +#ifdef USE_SSL + retval = safe_write(cptr, str, len); +#else retval = send(cptr->fd, str, len, 0); +#endif /* ** Convert WOULDBLOCK to a return of "0 bytes moved". This ** should occur only if socket was non-blocking. Note, that diff -ru --new-file irc2.10.3p3/common/class_def.h irc2.10.3p3+sd7/common/class_def.h --- irc2.10.3p3/common/class_def.h Tue Sep 23 23:47:53 1997 +++ irc2.10.3p3+sd7/common/class_def.h Mon Feb 3 14:31:07 2003 @@ -28,6 +28,9 @@ int maxHGlobal; int maxUHGlobal; int links; +#ifdef USE_SSL + int ssl; +#endif struct Class *next; } aClass; @@ -40,6 +43,9 @@ #define MaxUHLocal(x) ((x)->maxUHLocal) #define MaxHGlobal(x) ((x)->maxHGlobal) #define MaxUHGlobal(x) ((x)->maxUHGlobal) +#ifdef USE_SSL +#define UseSSL(x) ((x)->ssl) +#endif #define Links(x) ((x)->links) #define IncSendq(x) MaxSendq(x) = (int)((float)MaxSendq(x) * 1.1) diff -ru --new-file irc2.10.3p3/common/common_def.h irc2.10.3p3+sd7/common/common_def.h --- irc2.10.3p3/common/common_def.h Fri Feb 5 01:26:35 1999 +++ irc2.10.3p3+sd7/common/common_def.h Mon Feb 3 14:31:07 2003 @@ -54,6 +54,7 @@ #define PUNCT 8 #define DIGIT 16 #define SPACE 32 +#define VALID 64 #define isalpha(c) (char_atribs[(u_char)(c)]&ALPHA) #define isspace(c) (char_atribs[(u_char)(c)]&SPACE) @@ -74,6 +75,9 @@ #define isgraph(c) ((char_atribs[(u_char)(c)]&PRINT) && \ ((u_char)(c) != (u_char)0x20)) #define ispunct(c) (!(char_atribs[(u_char)(c)]&(CNTRL|ALPHA|DIGIT))) +#ifdef RESTRICT_USERNAMES +#define isvaliduser(c) (char_atribs[(u_char)(c)]&VALID) +#endif #ifdef DEBUGMODE # define Debug(x) debug x diff -ru --new-file irc2.10.3p3/common/match.c irc2.10.3p3+sd7/common/match.c --- irc2.10.3p3/common/match.c Thu Jul 5 00:44:40 2001 +++ irc2.10.3p3+sd7/common/match.c Mon Feb 3 14:31:07 2003 @@ -110,34 +110,37 @@ /* 16-23 */ CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, /* 24-31 */ CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, /* space */ PRINT|SPACE, -/* !"#$%&'( */ PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, -/* )*+,-./ */ PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, -/* 0123 */ PRINT|DIGIT, PRINT|DIGIT, PRINT|DIGIT, PRINT|DIGIT, -/* 4567 */ PRINT|DIGIT, PRINT|DIGIT, PRINT|DIGIT, PRINT|DIGIT, -/* 89:; */ PRINT|DIGIT, PRINT|DIGIT, PRINT, PRINT, -/* <=>? */ PRINT, PRINT, PRINT, PRINT, -/* @ */ PRINT, -/* ABC */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* DEF */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* GHI */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* JKL */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* MNO */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* PQR */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* STU */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* VWX */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* YZ[ */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* \]^ */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* _` */ PRINT, PRINT, -/* abc */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* def */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* ghi */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* jkl */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* mno */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* pqr */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* stu */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* vwx */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* yz{ */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, -/* \}~ */ PRINT|ALPHA, PRINT|ALPHA, PRINT|ALPHA, +/* !"#$ */ PRINT, PRINT, PRINT, PRINT, +/* %&'( */ PRINT, PRINT, PRINT, PRINT, +/* )*+ */ PRINT, PRINT, PRINT, +/* ,-. */ PRINT, PRINT|VALID, PRINT|VALID, +/* /01 */ PRINT, PRINT|DIGIT|VALID, PRINT|DIGIT|VALID, +/* 234 */ PRINT|DIGIT|VALID, PRINT|DIGIT|VALID, PRINT|DIGIT|VALID, +/* 567 */ PRINT|DIGIT|VALID, PRINT|DIGIT|VALID, PRINT|DIGIT|VALID, +/* 89: */ PRINT|DIGIT|VALID, PRINT|DIGIT|VALID, PRINT, +/* ;<= */ PRINT, PRINT, PRINT, +/* >?@ */ PRINT, PRINT, PRINT, +/* ABC */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* DEF */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* GHI */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* JKL */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* MNO */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* PQR */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* STU */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* VWX */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* YZ[ */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* \]^ */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA, +/* _` */ PRINT|VALID,PRINT, +/* abc */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* def */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* ghi */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* jkl */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* mno */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* pqr */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* stu */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* vwx */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* yz{ */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, +/* \}~ */ PRINT|ALPHA|VALID, PRINT|ALPHA|VALID, PRINT|ALPHA, /* del */ 0, /* 80-8f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90-9f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff -ru --new-file irc2.10.3p3/common/msg_def.h irc2.10.3p3+sd7/common/msg_def.h --- irc2.10.3p3/common/msg_def.h Fri Jan 23 15:28:07 1998 +++ irc2.10.3p3+sd7/common/msg_def.h Mon Feb 3 14:31:07 2003 @@ -32,6 +32,12 @@ #define MSG_QUIT "QUIT" /* QUIT */ #define MSG_SQUIT "SQUIT" /* SQUI */ #define MSG_KILL "KILL" /* KILL */ +#if defined(OPER_KLINE) || defined(LOCOP_KLINE) +#define MSG_KLINE "KLINE" /* KLIN */ +#endif +#if defined(OPER_TKLINE) || defined(LOCOP_TKLINE) +#define MSG_TKLINE "TKLINE" /* TKLI */ +#endif #define MSG_INFO "INFO" /* INFO */ #define MSG_LINKS "LINKS" /* LINK */ #define MSG_SUMMON "SUMMON" /* SUMM */ @@ -48,15 +54,19 @@ #define MSG_WALLOPS "WALLOPS" /* WALL */ #define MSG_TIME "TIME" /* TIME */ #define MSG_NAMES "NAMES" /* NAME */ +#define MSG_SNAMES "SNAMES" /* SNAMES */ #define MSG_ADMIN "ADMIN" /* ADMI */ #define MSG_TRACE "TRACE" /* TRAC */ #define MSG_NOTICE "NOTICE" /* NOTI */ #define MSG_JOIN "JOIN" /* JOIN */ +#define MSG_SJOIN "SJOIN" /* SJOIN */ +#define MSG_SCLEAN "SCLEAN" /* SCLEAN */ #define MSG_NJOIN "NJOIN" /* NJOIN */ #define MSG_PART "PART" /* PART */ #define MSG_LUSERS "LUSERS" /* LUSE */ #define MSG_MOTD "MOTD" /* MOTD */ #define MSG_MODE "MODE" /* MODE */ +#define MSG_SMODE "SMODE" /* SMODE */ #define MSG_UMODE "UMODE" /* UMOD */ #define MSG_KICK "KICK" /* KICK */ #define MSG_RECONECT "RECONNECT" /* RECONNECT -> RECO */ @@ -73,5 +83,10 @@ #define MSG_DIE "DIE" #define MSG_HASH "HAZH" /* HASH */ #define MSG_DNS "DNS" /* DNS -> DNSS */ - -#define MAXPARA 15 +#ifdef SERVER_MAP +#define MSG_MAP "MAP" +#endif +#ifdef OPER_SET +#define MSG_SET "SET" /* SET */ +#endif +#define MAXPARA 15 diff -ru --new-file irc2.10.3p3/common/numeric_def.h irc2.10.3p3+sd7/common/numeric_def.h --- irc2.10.3p3/common/numeric_def.h Sat Feb 10 21:11:05 2001 +++ irc2.10.3p3+sd7/common/numeric_def.h Mon Feb 3 14:31:07 2003 @@ -123,8 +123,18 @@ #define RPL_YOURHOST 002 #define RPL_CREATED 003 #define RPL_MYINFO 004 +#ifdef SEND_ISUPPORT +#define RPL_ISUPPORT 005 +#define RPL_BOUNCE 10 +#else #define RPL_BOUNCE 005 - +#endif +#ifdef SERVER_MAP +#define RPL_MAP 15 /* Undernet extension */ +#define RPL_MAPMORE 16 /* Undernet extension */ +#define RPL_MAPEND 17 /* Undernet extension */ +#define RPL_MAPSTART 18 /* +hemp */ +#endif /* * Errors are in the range from 400-599 currently and are grouped by what * commands they come from. @@ -232,6 +242,7 @@ #define RPL_NOTOPIC 331 #define RPL_TOPIC 332 +#define RPL_TOPICWHOTIME 333 #define RPL_INVITING 341 #define RPL_SUMMONING 342 @@ -299,7 +310,7 @@ #define RPL_STATSQLINE 217 #define RPL_STATSYLINE 218 #define RPL_ENDOFSTATS 219 - +#define RPL_STATSPLINE 220 #define RPL_UMODEIS 221 #define RPL_SERVICEINFO 231 @@ -335,3 +346,5 @@ #define RPL_TRACEEND 262 #define RPL_TRYAGAIN 263 +#define RPL_LOCALUSERS 265 +#define RPL_GLOBALUSERS 266 diff -ru --new-file irc2.10.3p3/common/os.h irc2.10.3p3+sd7/common/os.h --- irc2.10.3p3/common/os.h Thu Feb 3 19:57:00 2000 +++ irc2.10.3p3+sd7/common/os.h Mon Feb 3 14:31:07 2003 @@ -1,3 +1,5 @@ +#ifndef OS_H +#define OS_H /************************************************************************ * IRC - Internet Relay Chat, include/os.h * Copyright (C) 1997 Alain Nissen @@ -25,6 +27,13 @@ or need to be redefined for various reasons. */ +#include /* SSL stuff */ +#include +#include +#include +#include +#include + #include "setup.h" #if defined(linux) @@ -137,6 +146,9 @@ /* Linux 2.1.xx supports poll(), header files are not upto date yet */ # define POLLRDNORM 0x0040 # endif +#ifndef POLLWRNORM +#define POLLWRNORM 0x0100 +#endif #endif #if HAVE_STROPTS_H @@ -759,3 +771,4 @@ # define WHOSTENTP(x) (x) # define IRCDCONF_DELIMITER ':' #endif +#endif diff -ru --new-file irc2.10.3p3/common/parse.c irc2.10.3p3+sd7/common/parse.c --- irc2.10.3p3/common/parse.c Tue May 16 20:53:13 2000 +++ irc2.10.3p3+sd7/common/parse.c Mon Feb 3 14:31:07 2003 @@ -42,7 +42,32 @@ { MSG_NJOIN, m_njoin, MAXPARA, MSG_LAG|MSG_REG|MSG_NOU, 0, 0, 0L}, #endif { MSG_JOIN, m_join, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, +#ifndef CLIENT_COMPILE +# ifdef SOPER_SJOIN +# ifdef LOCOP_SJOIN + { MSG_SJOIN, m_sjoin, MAXPARA, MSG_REG|MSG_OP|MSG_LOP, 0, 0, 0L}, +# else + { MSG_SJOIN, m_sjoin, MAXPARA, MSG_REG|MSG_OP, 0, 0, 0L}, +# endif +# endif +# ifdef SOPER_SCLEAN +# ifdef LOCOP_SCLEAN + { MSG_SCLEAN, m_sclean, MAXPARA, MSG_REG|MSG_OP|MSG_LOP, 0, 0, 0L}, +# else + { MSG_SCLEAN, m_sclean, MAXPARA, MSG_REG|MSG_OP, 0, 0, 0L}, +# endif +# endif +#endif { MSG_MODE, m_mode, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, +#ifndef CLIENT_COMPILE +# ifdef SOPER_SMODE +# ifdef LOCOP_SMODE + { MSG_SMODE, m_smode, MAXPARA, MSG_REG|MSG_OP|MSG_LOP, 0, 0, 0L}, +# else + { MSG_SMODE, m_smode, MAXPARA, MSG_REG|MSG_OP, 0, 0, 0L}, +# endif +# endif +#endif { MSG_NICK, m_nick, MAXPARA, MSG_LAG, 0, 0, 0L}, { MSG_PART, m_part, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, { MSG_QUIT, m_quit, MAXPARA, MSG_LAG, 0, 0, 0L}, @@ -64,6 +89,12 @@ { MSG_KILL, m_kill, MAXPARA, MSG_LAG|MSG_REG|MSG_NOU, 0, 0, 0L}, #endif #ifndef CLIENT_COMPILE +#if defined(OPER_KLINE) || defined(LOCOP_KLINE) + { MSG_KLINE, m_kline, MAXPARA, MSG_LAG|MSG_REG|MSG_OP|MSG_LOP, 0,0, 0L}, +#endif +#if defined(OPER_TKLINE) || defined(LOCOP_TKLINE) + { MSG_TKLINE, m_tkline, MAXPARA, MSG_LAG|MSG_REG|MSG_OP|MSG_LOP, 0,0, 0L}, +#endif { MSG_USER, m_user, MAXPARA, MSG_LAG|MSG_NOU, 0, 0, 0L}, { MSG_AWAY, m_away, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, { MSG_UMODE, m_umode, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, @@ -74,6 +105,13 @@ { MSG_WHOWAS, m_whowas, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, { MSG_LIST, m_list, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, { MSG_NAMES, m_names, MAXPARA, MSG_LAG|MSG_REGU, 0, 0, 0L}, +# ifdef SOPER_SNAMES +# ifdef LOCOP_SNAMES + { MSG_SNAMES, m_snames, MAXPARA, MSG_REG|MSG_OP|MSG_LOP, 0, 0, 0L}, +# else + { MSG_SNAMES, m_snames, MAXPARA, MSG_REG|MSG_OP, 0, 0, 0L}, +# endif +# endif { MSG_USERHOST,m_userhost, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, { MSG_PASS, m_pass, MAXPARA, MSG_LAG|MSG_NOU, 0, 0, 0L}, { MSG_LUSERS, m_lusers, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, @@ -121,6 +159,12 @@ # endif , 0, 0, 0L}, #endif +#ifdef SERVER_MAP + { MSG_MAP, m_map, MAXPARA, MSG_LAG|MSG_REG, 0, 0, 0L}, +#endif +#ifdef OPER_SET + { MSG_SET, m_set, MAXPARA, MSG_LAG|MSG_REGU|MSG_OP|MSG_LOP , 0, 0, 0L}, +#endif #endif /* !CLIENT_COMPILE */ { (char *) 0, (int (*)()) 0, 0, 0, 0, 0, 0L} }; @@ -172,6 +216,71 @@ return acptr; } +aClient *find_matching_client(mask,cptr) +char *mask; +Reg aClient *cptr; +{ + aClient *acptr = cptr; + Reg char *ch; + int wild = 0; + + /* try to find exact match */ + acptr = find_client(mask,NULL); + if (!acptr) + { + aServer *asptr; + int wild = 0, dot = 0; + /* check if we should check against wilds */ + for (ch = mask; *ch; ch++) + { + if (*ch == '*' || *ch == '?') + { + wild = 1; + break; + } + if (*ch == '.') + { + dot = 1; + break; + } + } + + if (!wild && !dot) + { + return cptr; + } + (void) collapse(mask); + + /* try to match some servername against mask */ + for (asptr = svrtop; asptr; asptr = asptr->nexts) + { + if (!match(asptr->bcptr->name,mask) || + !match(mask,asptr->bcptr->name)) + { + acptr = asptr->bcptr; + break; + } + } + + /* no match, try services */ + if (!acptr) + { + aService *sp; + for (sp = svctop;sp;sp = sp->nexts) + { + if (!match(sp->bcptr->name,mask) || + !match(mask,sp->bcptr->name)) + { + acptr = sp->bcptr; + break; + } + } + } + + } + + return acptr ? acptr : cptr; +} #else /* CLIENT_COMPILE */ aClient *find_client(name, cptr) @@ -189,7 +298,7 @@ return cptr; } #endif /* CLIENT_COMPILE */ - +#ifndef CLIENT_COMPILE /* ** Find a user@host (server or user). ** @@ -208,20 +317,39 @@ *count = 0; if (user) - for (c2ptr = client; c2ptr; c2ptr = c2ptr->next) - { - if (!MyClient(c2ptr)) /* implies mine and a user */ - continue; - if ((!host || !match(host, c2ptr->user->host)) && - mycmp(user, c2ptr->user->username) == 0) - { - (*count)++; - res = c2ptr; - } - } + { + if (host) + { + anUser *auptr; + for (auptr = hash_find_hostname(host,NULL); auptr; auptr = auptr->hnext) + { + if (MyConnect(auptr->bcptr) && !mycmp(user,auptr->username)) + { + (*count)++; + res = auptr->bcptr; + } + } + } + else + { + int i; + for (i = 0; i <= highest_fd; i++) + { + if (!(c2ptr = local[i]) || !IsRegisteredUser(c2ptr)) + { + continue; + } + if (!mycmp(user,c2ptr->user->username)) + { + (*count)++; + res = c2ptr; + } + } + } + } return res; } - +#endif /* !CLIENT_COMPILE */ /* ** Find server by name. ** @@ -555,7 +683,11 @@ mptr->bytes += i; #ifndef CLIENT_COMPILE if ((mptr->flags & MSG_LAG) && - !(IsServer(cptr) || IsService(cptr))) + !(IsServer(cptr) || IsService(cptr) +#ifdef CAN_FLOOD + || CanFlood(cptr)) +#endif + ) { /* Flood control partly migrated into penalty */ if (bootopt & BOOT_PROT) cptr->since += (1 + i / 100); @@ -667,14 +799,13 @@ ** Add penalty score for sucessfully parsed command if issued by ** a LOCAL user client. */ - if ((ret > 0) && IsRegisteredUser(cptr) && (bootopt & BOOT_PROT)) + if ((ret > 0) && IsRegisteredUser(cptr) && (bootopt & BOOT_PROT) +#ifdef CAN_FLOOD + && !CanFlood(cptr) +#endif + ) { cptr->since += ret; -/* only to lurk - sendto_one(cptr, - ":%s NOTICE %s :*** Penalty INCR [%s] +%d", - me.name, cptr->name, ch, ret); -*/ } #endif return (ret != FLUSH_BUFFER) ? 2 : FLUSH_BUFFER; @@ -765,7 +896,12 @@ if (index(sender, '.') /* <- buggy, it could be a service! */ && !index(sender, '@')) /* better.. */ { - sendto_flag(SCH_LOCAL, "Squitting unknown %s brought by %s.", +#ifdef LOCAL_REJECTIONS_ONLY + sendto_flag(SCH_NOTICE, +#else + sendto_flag(SCH_LOCAL, +#endif + "Squitting unknown %s brought by %s.", sender, get_client_name(cptr, FALSE)); sendto_one(cptr, ":%s SQUIT %s :(Unknown from %s)", me.name, sender, get_client_name(cptr, FALSE)); @@ -780,7 +916,12 @@ * if we get here and sender is a service, we should probably issue * a kill in this case! -krys */ - sendto_flag(SCH_LOCAL, "Dropping unknown %s brought by %s.", +#ifdef LOCAL_REJECTIONS_ONLY + sendto_flag(SCH_NOTICE, +#else + sendto_flag(SCH_LOCAL, +#endif + "Dropping unknown %s brought by %s.", sender, get_client_name(cptr, FALSE)); } #endif diff -ru --new-file irc2.10.3p3/common/parse_ext.h irc2.10.3p3+sd7/common/parse_ext.h --- irc2.10.3p3/common/parse_ext.h Wed Sep 3 20:45:17 1997 +++ irc2.10.3p3+sd7/common/parse_ext.h Mon Feb 3 14:31:07 2003 @@ -44,6 +44,7 @@ EXTERN aClient *find_mask __P((char *name, aClient *cptr)); EXTERN aServer *find_tokserver __P((int token, aClient *cptr, aClient *c2ptr)); EXTERN aClient *find_name __P((char *name, aClient *cptr)); +EXTERN aClient *find_matching_client __P((char *mask, aClient *cptr)); #else /* CLIENT_COMPILE */ EXTERN aClient *find_client __P((char *name, aClient *cptr)); EXTERN aClient *find_server __P((char *name, aClient *cptr)); diff -ru --new-file irc2.10.3p3/common/send.c irc2.10.3p3+sd7/common/send.c --- irc2.10.3p3/common/send.c Fri Oct 19 00:43:05 2001 +++ irc2.10.3p3+sd7/common/send.c Mon Feb 3 14:31:07 2003 @@ -1391,6 +1391,13 @@ { SCH_SERVICE, "&SERVICES", NULL }, { SCH_DEBUG, "&DEBUG", NULL }, { SCH_AUTH, "&AUTH", NULL }, +#ifdef SMODE_CHAN + { SCH_SMODE, "&SMODE", NULL }, +#endif + +#ifdef CLIENTS_CHANNEL + { SCH_CLIENTS, "&CLIENTS", NULL }, +#endif }; @@ -1515,6 +1522,12 @@ ** And the rest... just count, I got 154 --Beeth */ char linebuf[1500]; +#ifdef LOG_IP + char *rip,*lip; +#ifndef INET6 + char tip[18]; +#endif +#endif /* LOG_IP */ /* ** This is a potential buffer overflow. ** I mean, when you manage to keep ircd @@ -1522,6 +1535,9 @@ */ char buf[12]; int logfile; +#ifdef LOG_IP + u_short rport,lport; +#endif /* LOG_IP */ logfile = msg ? connlog : userlog; @@ -1543,15 +1559,63 @@ (int) (duration % 60)); } +#ifdef LOG_IP + /*- + * New connection log format after looooong discussion: + * [ident@remoteip#remoteport,localip#localport] + * --Yegg, 2001-05-09 + */ + lport = cptr->acpt != NULL ? cptr->acpt->port : 0; + rport = cptr->port; + +#ifdef INET6 + lip = cptr->acpt != NULL ? inetntop(AF_INET6, (char *)&cptr->acpt->ip, + mydummy, MYDUMMY_SIZE) : ""; + rip = inetntop(AF_INET6, (char *)&cptr->ip, + mydummy2, MYDUMMY_SIZE); +#else + if (cptr->acpt != NULL) + { + lip = inetntoa((char *)&cptr->acpt->ip); + strncpyzt(tip, lip, 18); + lip = tip; + } + else + { + lip = ""; + } + rip = inetntoa((char *)&cptr->ip); +#endif + +#endif /* LOG_IP */ + /* ** Aha, cptr->firsttime is time when user connected, ** so we syslog() it anyway. I'm waving big ** "rewrite log format" flag --Beeth. */ (void)sprintf(linebuf, - "%s (%s): %s@%s [%s] %c %lu %luKb %lu %luKb\n", +#ifndef LOG_IP +#ifdef LOG_IRCNAME + "%s (%s): %s@%s [%s] [%s] %c %lu %luKb %lu %luKb\n", +#else + "%s (%s): %s@%s [%s] %c %lu %luKb %lu %luKb\n", +#endif +#else /* LOG_IP */ +#ifdef LOG_IRCNAME + "%s (%s): %s@%s [%s@%s#%u,%s#%u] [%s] %c %lu %luKb %lu %luKb\n", +#else + "%s (%s): %s@%s [%s@%s#%u,%s#%u] %c %lu %luKb %lu %luKb\n", +#endif +#endif /* LOG_IP */ myctime(cptr->firsttime), msg ? msg : buf, username, hostname, cptr->auth, +#ifdef LOG_IP + rip,rport,lip,lport, +#endif /* LOG_IP */ +#ifdef LOG_IRCNAME + cptr->info, +#endif cptr->exitc, cptr->sendM, cptr->sendK, cptr->receiveM, cptr->receiveK); diff -ru --new-file irc2.10.3p3/common/struct_def.h irc2.10.3p3+sd7/common/struct_def.h --- irc2.10.3p3/common/struct_def.h Mon May 14 15:02:08 2001 +++ irc2.10.3p3+sd7/common/struct_def.h Mon Feb 3 14:31:07 2003 @@ -40,27 +40,28 @@ #define HOSTLEN 63 /* Length of hostname. Updated to */ /* comply with RFC1123 */ -#define NICKLEN 9 /* Necessary to put 9 here instead of 10 +#define NICKLEN 20 /* Necessary to put 9 here instead of 10 ** if s_msg.c/m_nick has been corrected. ** This preserves compatibility with old ** servers --msa */ #define USERLEN 10 #define REALLEN 50 -#define TOPICLEN 80 -#define CHANNELLEN 50 -#define PASSWDLEN 20 -#define KEYLEN 23 +#define TOPICLEN 250 +#define CHANNELLEN 100 +#define PASSWDLEN 30 +#define KEYLEN 80 #define BUFSIZE 512 /* WARNING: *DONT* CHANGE THIS!!!! */ -#define MAXRECIPIENTS 20 -#define MAXBANS 30 +#define MAXRECIPIENTS 50 +#define MAXBANS 100 #define MAXBANLENGTH 1024 #define BANLEN (USERLEN + NICKLEN + HOSTLEN + 3) #define MAXPENALTY 10 #define CHIDLEN 5 /* WARNING: *DONT* CHANGE THIS!!!! */ #define READBUF_SIZE 16384 /* used in s_bsd.c *AND* s_zip.c ! */ - + +#define MAXMODEPARAMS 3 /* do _!not!_ change this */ /* * Make up some numbers which should reflect average leaf server connect * queue max size. @@ -166,6 +167,9 @@ #define FLAGS_ZIP 0x400000 /* link is zipped */ #define FLAGS_ZIPRQ 0x800000 /* zip requested */ #define FLAGS_ZIPSTART 0x1000000 /* start of zip (ignore any CRLF) */ +#ifdef SPLIT_HANDLE +#define FLAGS_EOBWAIT 0x2000000 /* waiting for EOB */ +#endif #define FLAGS_HELD 0x8000000 /* connection held and reconnect try */ #define FLAGS_OPER 0x0001 /* Operator */ @@ -174,14 +178,43 @@ #define FLAGS_INVISIBLE 0x0008 /* makes user invisible */ #define FLAGS_RESTRICTED 0x0010 /* Restricted user */ #define FLAGS_AWAY 0x0020 /* user is away */ +#define FLAGS_FORCE 0x0100 /* user can force channel modes */ + +#define FLAGS_BADBOY 0x0200 /* delay close this client */ + +#ifdef ILINE_FLAGS +#ifdef RECOVER +#define FLAGS_IMMORTAL 0x0400 /* immortal user (recover from collision) */ +#endif +#define FLAGS_EXEMPT 0x0800 /* user is exempt from k-lines */ +#ifdef CAN_FLOOD +#define FLAGS_FLOOD 0x1000 /* user can flood !bad! */ +#endif +#ifdef USE_SSL +#define FLAGS_DOT 0x2000 /* '.' in username for non-ssl */ +#endif +#endif + +#ifdef CAN_FLOOD +#define _FLAGS_FLOOD FLAGS_FLOOD +#else +#define _FLAGS_FLOOD 0 +#endif + +#ifdef RECOVER +#define _FLAGS_IMMORTAL FLAGS_IMMORTAL +#else +#define _FLAGS_IMMORTAL 0 +#endif #define SEND_UMODES (FLAGS_INVISIBLE|FLAGS_OPER|FLAGS_WALLOP|FLAGS_AWAY) -#define ALL_UMODES (SEND_UMODES|FLAGS_LOCOP|FLAGS_RESTRICTED) +#define ALL_UMODES (SEND_UMODES|FLAGS_LOCOP|FLAGS_RESTRICTED|_FLAGS_IMMORTAL|_FLAGS_FLOOD) /* * flags macros. */ #define IsOper(x) ((x)->user && (x)->user->flags & FLAGS_OPER) +#define IsForce(x) ((x)->user && (x)->user->flags & FLAGS_FORCE) #define IsLocOp(x) ((x)->user && (x)->user->flags & FLAGS_LOCOP) #define IsInvisible(x) ((x)->user->flags & FLAGS_INVISIBLE) #define IsRestricted(x) ((x)->user && \ @@ -199,6 +232,7 @@ #define CBurst(x) ((x)->flags & FLAGS_CBURST) #define SetOper(x) ((x)->user->flags |= FLAGS_OPER) +#define SetForce(x) ((x)->user->flags |= FLAGS_FORCE) #define SetLocOp(x) ((x)->user->flags |= FLAGS_LOCOP) #define SetInvisible(x) ((x)->user->flags |= FLAGS_INVISIBLE) #define SetRestricted(x) ((x)->user->flags |= FLAGS_RESTRICTED) @@ -214,6 +248,7 @@ #define NoNewLine(x) ((x)->flags & FLAGS_NONL) #define ClearOper(x) ((x)->user->flags &= ~FLAGS_OPER) +#define ClearForce(x) ((x)->user->flags &= ~FLAGS_FORCE) #define ClearInvisible(x) ((x)->user->flags &= ~FLAGS_INVISIBLE) #define ClearRestricted(x) ((x)->user->flags &= ~FLAGS_RESTRICTED) #define ClearWallops(x) ((x)->user->flags &= ~FLAGS_WALLOP) @@ -222,6 +257,20 @@ #define ClearXAuth(x) ((x)->flags &= ~FLAGS_XAUTH) #define ClearWXAuth(x) ((x)->flags &= ~FLAGS_WXAUTH) +#ifdef SPLIT_HANDLE +#define SetBurst(x) ((x)->flags |= FLAGS_EOBWAIT) +#define ClearBurst(x) ((x)->flags &= ~FLAGS_EOBWAIT) +#define IsBurst(x) ((x)->flags & FLAGS_EOBWAIT) +#endif +#ifdef ILINE_FLAGS +#define IsKlineExempt(x) ((x)->user && (x)->user->flags & FLAGS_EXEMPT) +#endif +#ifdef CAN_FLOOD +#define CanFlood(x) ((x)->user && (x)->user->flags & FLAGS_FLOOD) +#endif +#ifdef RECOVER +#define IsImmortal(x) ((x)->user && (x)->user->flags & FLAGS_IMMORTAL) +#endif /* * defined debugging levels */ @@ -264,6 +313,12 @@ char *host; char *passwd; char *name; +#ifdef SPOOF + char *spoof; +#endif +#ifdef USE_SSL + char *cert; +#endif int port; u_int pref; /* preference value */ struct CPing *ping; @@ -276,6 +331,24 @@ #define CONF_ILLEGAL 0x80000000 #define CONF_MATCH 0x40000000 + +#ifdef DELAY_ACCEPT +#define CONF_DELAY 0x20000000 +#define CONF_ACTIVE 0x10000000 +#define CONF_SERVERONLY 0x8000000 +#endif + +#ifdef ILINE_FLAGS +#define CONF_FLOOD 0x200000 +#define CONF_EXEMPT 0x400000 /* user is exempted from K: */ +#define CONF_RNODNS 0x800000 +#define CONF_DOT 0x1000000 +#define CONF_IMMORTAL 0x2000000 + +/* put all your i-line flags here! -sd */ +#define CONF_ILINE_FLAGS (CONF_FLOOD|CONF_EXEMPT|CONF_RNODNS|CONF_DOT|CONF_IMMORTAL) +#endif + #define CONF_QUARANTINED_SERVER 0x000001 #define CONF_CLIENT 0x000002 #define CONF_RCLIENT 0x000004 @@ -299,6 +372,7 @@ #define CONF_BOUNCE 0x040000 #define CONF_OTHERKILL 0x080000 #define CONF_DENY 0x100000 +#define CONF_SSL 0x200000 #define CONF_OPS (CONF_OPERATOR | CONF_LOCOP) #define CONF_SERVER_MASK (CONF_CONNECT_SERVER | CONF_NOCONNECT_SERVER |\ @@ -307,7 +381,6 @@ CONF_SERVER_MASK) #define IsIllegal(x) ((x)->status & CONF_ILLEGAL) - typedef struct { u_long pi_id; u_long pi_seq; @@ -368,6 +441,8 @@ char username[USERLEN+1]; char host[HOSTLEN+1]; char *server; + struct User *hnext; + int hashv; }; struct Server { @@ -382,6 +457,10 @@ ** from anUser (field servp), aService (field ** servp) and aClient (field serv) */ + int usercnt[3]; /* # of clients - all, invisible, opers */ +#ifdef EXTRA_STATISTICS + int usermax; /* max # of users on this server */ +#endif struct Server *nexts, *prevs, *shnext; aClient *bcptr; char by[NICKLEN+1]; @@ -389,6 +468,7 @@ time_t lastload; /* penalty like counters, see s_serv.c ** should be in the local part, but.. */ + Link *down; /* list of downlinks */ }; struct Service { @@ -445,13 +525,23 @@ char *auth; u_short port; /* and the remote port# too :-) */ struct IN_ADDR ip; /* keep real ip# too */ +#if defined(SPOOF) && defined(OPERS_WATCHING_USERS) + struct IN_ADDR real_ip; +#endif struct hostent *hostp; char sockhost[HOSTLEN+1]; /* This is the host name from the socket ** and after which the connection was ** accepted. */ char passwd[PASSWDLEN+1]; + char *reason; /* internal quit reason */ char exitc; + +#ifdef USE_SSL + SSL *ssl; /* ssl structure, if NULL, ssl not used */ + int handshake; /* in SSL_accept() ? */ + int forcessl; +#endif }; #define CLIENT_LOCAL_SIZE sizeof(aClient) @@ -531,6 +621,14 @@ u_long bytes; }; +#define SET_TYPE_INT 0 +#define SET_TYPE_STRING 1 +struct Set_Message { + char *cmd; + int *value; + char **values; +}; + #define MSG_LAG 0x0001 #define MSG_NOU 0x0002 /* Not available to users */ #define MSG_SVC 0x0004 /* Services only */ @@ -570,6 +668,10 @@ u_int hashv; /* raw hash value */ Mode mode; char topic[TOPICLEN+1]; +#ifdef TOPICWHOTIME + char topic_nuh[BANLEN+1]; + time_t topic_time; +#endif int users; /* current membership total */ Link *members; /* channel members */ Link *invites; /* outstanding invitations */ @@ -674,6 +776,16 @@ x->prev->service->servp == x->serv))) typedef struct { +#ifdef EXTRA_STATISTICS + time_t is_last_cnt_t; /* timestamp for last count */ + u_long is_last_cnt; /* last count */ + u_long is_m_users; /* maximum users connected */ + u_long is_m_serv; /* maximum servers connected */ + u_long is_m_service; /* maximum services connected */ + u_long is_m_myclnt; /* maximum local clients */ + u_long is_m_myserv; /* maximum local servers */ + u_long is_m_myservice; /* maximum local services */ +#endif u_long is_user[2]; /* users, non[0] invis and invis[1] */ u_long is_serv; /* servers */ u_long is_service; /* services */ @@ -715,8 +827,21 @@ u_int is_dbufmin; /* min number of dbuf in use */ u_int is_dbufmax; /* max number of dbuf in use */ u_int is_dbufmore; /* how many times we increased the bufferpool*/ +#ifdef DELAY_CLOSE + u_long is_delayclosed; +#endif +#ifdef SPLIT_HANDLE + u_long is_eobservers; /* # of servers which sent EOB */ +#endif } istat_t; +typedef struct { + u_int split; + u_int aconnect; /* if we want aconnect or not */ +#ifdef DELAY_ACCEPT + u_int caccept; /* enable/disable client ports */ +#endif +} iconf_t; /* String manipulation macros */ /* strncopynt --> strncpyzt to avoid confusion, sematics changed @@ -771,7 +896,22 @@ #define SCH_SERVICE 9 #define SCH_DEBUG 10 #define SCH_AUTH 11 -#define SCH_MAX 11 +#define SCH_CLIENTS 12 +#define SCH_SMODE 13 + +#ifdef CLIENTS_CHANNEL + #ifdef SMODE_CHAN + #define SCH_MAX 14 + #else + #define SCH_MAX 13 + #endif +#else + #ifdef SMODE_CHAN + #define SCH_MAX 13 + #else + #define SCH_MAX 12 + #endif +#endif /* used for async dns values */ diff -ru --new-file irc2.10.3p3/common/support.c irc2.10.3p3+sd7/common/support.c --- irc2.10.3p3/common/support.c Thu May 31 17:00:02 2001 +++ irc2.10.3p3+sd7/common/support.c Mon Feb 3 14:31:07 2003 @@ -849,7 +849,7 @@ char *make_version() { int ve, re, mi, dv, pl; - char ver[15]; + char ver[50]; sscanf(PATCHLEVEL, "%2d%2d%2d%2d%2d", &ve, &re, &mi, &dv, &pl); /* version & revision */ @@ -863,7 +863,27 @@ sprintf(ver + strlen(ver), "p%d", pl); return mystrdup(ver); } +#ifndef CLIENTCOMPILE +#ifdef SEND_ISUPPORT +/* + * Make ISUPPORT string + */ +char *make_isupport() +{ + char tisupport[200]; + char *p = tisupport; +#ifdef SERVER_MAP + strcpy(tisupport,"MAP "); + p +=4; +#endif + SPRINTF(p,"PREFIX=(ov)@+ MODES=%d CHANTYPES=#&!+ MAXCHANNELS=%d NICKLEN=%d TOPICLEN=%d KICKLEN=%d NETWORK=%s CHANMODES=beI,k,l,imnpstaqr", + MAXMODEPARAMS, MAXCHANNELSPERUSER, NICKLEN, TOPICLEN, TOPICLEN,NETWORKNAME); + + return mystrdup(tisupport); +} +#endif +#endif #ifndef HAVE_TRUNCATE /* truncate: set a file to a specified length * I don't know of any UNIX that doesn't have truncate, but CYGWIN32 beta18 diff -ru --new-file irc2.10.3p3/common/support_ext.h irc2.10.3p3+sd7/common/support_ext.h --- irc2.10.3p3/common/support_ext.h Sat Dec 9 00:15:21 2000 +++ irc2.10.3p3+sd7/common/support_ext.h Mon Feb 3 14:31:07 2003 @@ -72,6 +72,9 @@ #endif /* USE_STDARG */ EXTERN int dgets __P((int fd, char *buf, int num)); EXTERN char *make_version(); +#ifdef SEND_ISUPPORT +EXTERN char *make_isupport(); +#endif #if SOLARIS_2_3 EXTERN struct hostent *solaris_gethostbyname __P((const char *name)); #endif /* SOLARIS_2_3 */ diff -ru --new-file irc2.10.3p3/iauth/a_conf.c irc2.10.3p3+sd7/iauth/a_conf.c --- irc2.10.3p3/iauth/a_conf.c Sat Apr 7 03:51:48 2001 +++ irc2.10.3p3+sd7/iauth/a_conf.c Mon Feb 3 14:31:07 2003 @@ -26,6 +26,7 @@ #define A_CONF_C #include "a_externs.h" #undef A_CONF_C +#undef USE_DSM static aModule *Mlist[16]; @@ -86,6 +87,7 @@ Mlist[Mcnt++] = &Module_rfc931; Mlist[Mcnt++] = &Module_socks; + Mlist[Mcnt++] = &Module_webproxy; Mlist[Mcnt++] = &Module_pipe; Mlist[Mcnt++] = &Module_lhex; Mlist[Mcnt] = NULL; @@ -247,6 +249,7 @@ (*last)->hostname = NULL; (*last)->address = NULL; (*last)->timeout = timeout; + (*last)->reason = NULL; if (Mlist[i] == &Module_rfc931) ident = *last; @@ -290,6 +293,17 @@ mystrdup(buffer + 10); continue; } + if (!strncasecmp(buffer+1, "reason = ", 9)) + { + if ((*last)->reason) + conf_err(lnnb, + "Duplicate reason keyword: ignored.", + cfile); + else + (*last)->reason = + mystrdup(buffer + 10); + continue; + } if (!strncasecmp(buffer+1, "host = ", 7)) { needh = 1; diff -ru --new-file irc2.10.3p3/iauth/a_conf_def.h irc2.10.3p3+sd7/iauth/a_conf_def.h --- irc2.10.3p3/iauth/a_conf_def.h Mon Jul 5 01:09:09 1999 +++ irc2.10.3p3+sd7/iauth/a_conf_def.h Mon Feb 3 14:31:07 2003 @@ -40,6 +40,7 @@ u_char in; /* instance number */ aModule *mod; /* module */ char *opt; /* options read from file */ + char *reason; /* reject reason */ char *popt; /* options to send to ircd */ void *data; /* private data: stats, ... */ aTarget *address; diff -ru --new-file irc2.10.3p3/iauth/a_externs.h irc2.10.3p3+sd7/iauth/a_externs.h --- irc2.10.3p3/iauth/a_externs.h Mon Apr 12 22:45:04 1999 +++ irc2.10.3p3+sd7/iauth/a_externs.h Mon Feb 3 14:31:07 2003 @@ -30,5 +30,6 @@ #include "mod_rfc931_ext.h" #include "mod_socks_ext.h" +#include "mod_webproxy_ext.h" #include "mod_pipe_ext.h" #include "mod_lhex_ext.h" diff -ru --new-file irc2.10.3p3/iauth/a_log_def.h irc2.10.3p3+sd7/iauth/a_log_def.h --- irc2.10.3p3/iauth/a_log_def.h Thu Oct 18 22:51:08 2001 +++ irc2.10.3p3+sd7/iauth/a_log_def.h Mon Feb 3 14:31:07 2003 @@ -37,5 +37,7 @@ #define ALOG_DSOCKSC 0x040000 /* debug: module socks cache */ #define ALOG_DPIPE 0x080000 /* debug: module pipe */ #define ALOG_DLHEX 0x100000 /* debug: module pipe */ +#define ALOG_DWEBPROXY 0x200000 /* debug: module webproxy */ +#define ALOG_DWEBPROXYC 0x400000 /* debug: module webproxy */ -#define ALOG_DALL 0x1F3700 /* any debug flag */ +#define ALOG_DALL 0x7F3700 /* any debug flag */ diff -ru --new-file irc2.10.3p3/iauth/mod_socks.c irc2.10.3p3+sd7/iauth/mod_socks.c --- irc2.10.3p3/iauth/mod_socks.c Thu May 31 02:40:00 2001 +++ irc2.10.3p3+sd7/iauth/mod_socks.c Mon Feb 3 14:31:07 2003 @@ -62,6 +62,7 @@ struct socks_private { struct proxylog *cache; + char *reason; u_int lifetime; u_char options; /* stats */ @@ -81,13 +82,19 @@ char *strver; { struct socks_private *mydata = cldata[cl].instance->data; + char *reason = mydata->reason; +#ifdef IAUTH_VERBOSE_REJECTS + char verbose = 'K'; +#else + char verbose = 'k'; +#endif /* open proxy */ if (mydata->options & OPT_DENY) { cldata[cl].state |= A_DENY; - sendto_ircd("k %d %s %u ", cl, cldata[cl].itsip, - cldata[cl].itsport); + sendto_ircd("%c %d %s %u #socks %s", verbose, cl, cldata[cl].itsip, + cldata[cl].itsport,reason ? reason : ""); } if (mydata->options & OPT_LOG) sendto_log(ALOG_FLOG, LOG_INFO, "socks%s: open proxy: %s[%s]", @@ -525,7 +532,10 @@ sprintf(cbuf, ", Cache %d (min)", mydata->lifetime); strcat(txtbuf, cbuf); mydata->lifetime *= 60; - + if (self->reason) + { + mydata->reason = mystrdup(self->reason); + } self->popt = mystrdup(tmpbuf+1); self->data = mydata; return txtbuf+2; diff -ru --new-file irc2.10.3p3/iauth/mod_webproxy.c irc2.10.3p3+sd7/iauth/mod_webproxy.c --- irc2.10.3p3/iauth/mod_webproxy.c Thu Jan 1 02:00:00 1970 +++ irc2.10.3p3+sd7/iauth/mod_webproxy.c Mon Feb 3 14:31:07 2003 @@ -0,0 +1,596 @@ +/************************************************************************ + * IRC - Internet Relay Chat, iauth/mod_webproxy.c + * Copyright (C) 2001 Dan Merillat + * + * Original code (iauth/mod_socks.c) is + * Copyright (C) 1998 Christophe Kalt + * + * 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_webproxy.c,v 1.25 1999/08/13 21:06:30 chopin Exp $"; +#endif + +#include "os.h" +#include "a_defines.h" +#define MOD_WEBGATE_C +#include "a_externs.h" + +/****************************** PRIVATE *************************************/ + +#define CACHETIME 30 + +struct proxylog { + struct proxylog *next; + char ip[HOSTLEN + 1]; + u_char state; /* 0 = no proxy, 1 = open proxy, 2 = closed proxy */ + time_t expire; + u_int port; +}; + +#define OPT_LOG 0x001 +#define OPT_DENY 0x002 +#define OPT_PARANOID 0x004 +#define OPT_CAREFUL 0x008 +#define OPT_V4ONLY 0x010 +#define OPT_V5ONLY 0x020 +#define OPT_PROTOCOL 0x100 + +#define PROXY_NONE 0 +#define PROXY_OPEN 1 +#define PROXY_CLOSE 2 +#define PROXY_UNEXPECTED 3 +#define PROXY_BADPROTO 4 + +struct webproxy_private { + struct proxylog *cache; + u_int lifetime; + u_char options; + char *reason; + u_int ports[128]; + u_int portcount; + /* stats */ + u_int chitc, chito, chitn, cmiss, cnow, cmax; + u_int open[128], closed, noproxy; +}; +int webproxy_start(u_int); + +/* + * webproxy_open_proxy + * + * Found an open proxy for cl: deal with it! + */ + +static void +webproxy_open_proxy(cl,port) +int cl; +u_int port; +{ + struct webproxy_private *mydata = cldata[cl].instance->data; + char *reason = mydata->reason; +#ifdef IAUTH_VERBOSE_REJECTS + char verbose = 'K'; +#else + char verbose = 'k'; +#endif + char myreason[BUFSIZE]; + if (reason) + { + if (strstr(reason,"%d")) + { + sprintf(myreason,reason,port); + } + else + { + strcpy(myreason,reason); + } + myreason[300] = '\0'; + } + /* open proxy */ + if (mydata->options & OPT_DENY) { + cldata[cl].state |= A_DENY; + sendto_ircd("%c %d %s %u %s%d %s", verbose,cl, cldata[cl].itsip, + cldata[cl].itsport,"#webproxy-",port, + reason ? myreason : ""); + } + if (mydata->options & OPT_LOG) + sendto_log(ALOG_FLOG, LOG_INFO, "webproxy: open proxy: %s[%s], port %u", + cldata[cl].host, cldata[cl].itsip, + port); +} + +/* + * webproxy_add_cache + * + * Add an entry to the cache. + */ + +static void +webproxy_add_cache(cl, state) +int cl, state; +{ + struct webproxy_private *mydata = cldata[cl].instance->data; + struct proxylog *next; + + + if (state == PROXY_OPEN) { + if (cldata[cl].mod_status < mydata->portcount) + mydata->open[cldata[cl].mod_status] += 1; + + } else if (state == PROXY_NONE) + mydata->noproxy += 1; + else + /* state == PROXY_CLOSE|PROXY_UNEXPECTED|PROXY_BADPROTO */ + mydata->closed += 1; + + if (mydata->lifetime == 0) + return; + + mydata->cnow += 1; + if (mydata->cnow > mydata->cmax) + mydata->cmax = mydata->cnow; + + next = mydata->cache; + mydata->cache = (struct proxylog *) malloc(sizeof(struct proxylog)); + mydata->cache->expire = time(NULL) + mydata->lifetime; + strcpy(mydata->cache->ip, cldata[cl].itsip); + mydata->cache->port = mydata->ports[cldata[cl].mod_status - 1]; + mydata->cache->state = state; + mydata->cache->next = next; + DebugLog( + (ALOG_DWEBPROXYC, 0, + "webproxy_add_cache(%d): new cache %s, open=%d", cl, + mydata->cache->ip, state)); +} + +/* + * webproxy_check_cache + * + * Check cache for an entry. + */ +static int +webproxy_check_cache(cl) +{ + struct webproxy_private *mydata = cldata[cl].instance->data; + struct proxylog **last, *pl; + time_t now = time(NULL); + + if (!mydata || mydata->lifetime == 0) + return 0; + + DebugLog( + (ALOG_DWEBPROXYC, 0, + "webproxy_check_cache(%d): Checking cache for %s", cl, + cldata[cl].itsip)); + + last = &(mydata->cache); + while ((pl = *last)) { + DebugLog((ALOG_DWEBPROXYC, 0, "webproxy_check_cache(%d): cache %s", + cl, pl->ip)); + if (pl->expire < now) { + DebugLog((ALOG_DWEBPROXYC, 0, + "webproxy_check_cache(%d): free %s (%d < %d)", + cl, pl->ip, pl->expire, now)); + *last = pl->next; + free(pl); + mydata->cnow -= 1; + continue; + } + if (!strcasecmp(pl->ip, cldata[cl].itsip)) { + DebugLog((ALOG_DWEBPROXYC, 0, + "webproxy_check_cache(%d): match (%u)", cl, + pl->state)); + pl->expire = now + mydata->lifetime; /* dubious */ + if (pl->state == 1) { + webproxy_open_proxy(cl,pl->port); + mydata->chito += 1; + } else if (pl->state == 0) + mydata->chitn += 1; + else + mydata->chitc += 1; + return -1; + } + last = &(pl->next); + } + mydata->cmiss += 1; + return 0; +} + +static int +webproxy_write(u_int cl) +{ + + struct webproxy_private *mydata = cldata[cl].instance->data; + static u_char query[64]; /* big enough to hold all queries */ + static int query_len; /* lenght of socks4 query */ + static int wlen; + + + + query_len=snprintf(query, 64, "CONNECT %s:%d HTTP/1.0\n\n", + cldata[cl].ourip, cldata[cl].ourport); + + DebugLog((ALOG_DWEBPROXY, 0, "webproxy_write(%d): Checking %s:%u", + cl, cldata[cl].itsip, mydata->ports[cldata[cl].mod_status])); + if ((wlen=write(cldata[cl].wfd, query, query_len)) != query_len) { + /* most likely the connection failed */ + DebugLog( + (ALOG_DWEBPROXY, 0, + "webproxy_write(%d): write() failed: %d %s", cl, + wlen, strerror(errno))); + close(cldata[cl].wfd); + cldata[cl].rfd = cldata[cl].wfd = 0; + cldata[cl].buflen=0; + if (++cldata[cl].mod_status < mydata->portcount) + return webproxy_start(cl); + else + return 1; + } + cldata[cl].rfd = cldata[cl].wfd; + cldata[cl].wfd = 0; + return 0; +} + +static int +webproxy_read(u_int cl) +{ + /* Looking for "Connection established" + * HTTP/1.0 200 Connection established" */ + + struct webproxy_private *mydata = cldata[cl].instance->data; + int again = 1; + u_char state = PROXY_CLOSE; + char * lookfor="HTTP/1.0 200"; + u_int looklen=strlen(lookfor); + + /* data's in from the other end */ + if (cldata[cl].buflen < looklen) + return 0; + + /* zero it out so the debug log is sane */ + cldata[cl].inbuffer[cldata[cl].buflen]=0; + + /* got all we need */ + DebugLog( + (ALOG_DWEBPROXY, 0, "webproxy_read(%d): %d Got [%s]", + cl, mydata->ports[cldata[cl].mod_status], cldata[cl].inbuffer)); + + + if (!strncmp(cldata[cl].inbuffer, lookfor, looklen) || + !strncmp(cldata[cl].inbuffer, "HTTP/1.1 200",looklen) + ) { /* got it! */ + DebugLog((ALOG_DWEBPROXY, 0, "webproxy_read(%d): Open proxy on %s:%u", + cl, cldata[cl].itsip, mydata->ports[cldata[cl].mod_status])); + state = PROXY_OPEN; + webproxy_open_proxy(cl,mydata->ports[cldata[cl].mod_status]); + again = 0; + } + + cldata[cl].mod_status++; + close(cldata[cl].rfd); + cldata[cl].rfd = 0; + + if (again && cldata[cl].mod_status < mydata->portcount) { + cldata[cl].buflen = 0; + return webproxy_start(cl); + } + else { + webproxy_add_cache(cl, state); + return -1; + } + return 0; +} + +/******************************** PUBLIC ************************************/ + +/* + * webproxy_init + * + * This procedure is called when a particular module is loaded. + * Returns NULL if everything went fine, + * an error message otherwise. + */ + +char * +webproxy_init(AnInstance * self) +{ + struct webproxy_private *mydata; + char tmpbuf[80], cbuf[32]; + static char txtbuf[80]; + u_int portcount = 0; + + tmpbuf[0] = txtbuf[0] = '\0'; + + mydata = + (struct webproxy_private *) + malloc(sizeof(struct webproxy_private)); + bzero((char *) mydata, sizeof(struct webproxy_private)); + mydata->cache = NULL; + mydata->lifetime = CACHETIME; + if (!self->opt) + { + /* using default config: + ** log,deny,ports=3128;8080 + */ + mydata->options=OPT_DENY|OPT_LOG; + mydata->ports[portcount++] = 3128; + mydata->ports[portcount++] = 8080; + mydata->portcount=portcount; + strcat(tmpbuf, ",log"); + strcat(txtbuf, ", Log"); + strcat(tmpbuf, ",reject"); + strcat(txtbuf, ", Reject"); + strcat(tmpbuf, ",ports=3128;8080"); + strcat(txtbuf, ", Ports=3128;8080"); + + } + else + { + + char *ch = NULL, *portsp = NULL; + + if ((portsp=strstr(self->opt, "ports"))) + + { + char xbuf[128]; + char *c; + size_t slen; + bzero(xbuf,sizeof(xbuf)); + ch = strchr(portsp, '='); + if (!ch) + { + mydata->ports[portcount++] = 3128; + mydata->ports[portcount++] = 8080; + mydata->portcount=portcount; + } + else + { + c=index(ch, ','); + if (!c) + c=ch+strlen(ch); + /* now ch is at = and c is at the end of the ports line */ + ch++; + slen = (size_t) c - (size_t) ch; + if (slen > 30) + { + slen = 30; + } + memcpy(xbuf, ch, slen); + strcat(tmpbuf,",ports="); + + strcat(tmpbuf,xbuf); + ch=xbuf; + while((c=index(ch, ';'))) { + *c=0; + mydata->ports[portcount++]=atoi(ch); + ch=c+1; + } + mydata->ports[portcount++]=atoi(ch); + mydata->portcount=portcount; + } + } + if (strstr(self->opt, "log")) { + mydata->options |= OPT_LOG; + strcat(tmpbuf, ",log"); + strcat(txtbuf, ", Log"); + } + if (strstr(self->opt, "reject")) { + mydata->options |= OPT_DENY; + strcat(tmpbuf, ",reject"); + strcat(txtbuf, ", Reject"); + } + if (strstr(self->opt, "cache")) { + char *ch = index(self->opt, '='); + + if (ch) + mydata->lifetime = atoi(ch + 1); + } + } + sprintf(cbuf, ",cache=%d", mydata->lifetime); + strcat(tmpbuf, cbuf); + sprintf(cbuf, ", Cache %d (min)", mydata->lifetime); + strcat(txtbuf, cbuf); + mydata->lifetime *= 60; + if (self->reason) + { + mydata->reason = mystrdup(self->reason); + } + self->popt = mystrdup(tmpbuf + 1); + self->data = mydata; + return txtbuf + 2; +} + +/* + * webproxy_release + * + * This procedure is called when a particular module is unloaded. + */ +void +webproxy_release(self) +AnInstance *self; +{ + struct webproxy_private *mydata = self->data; + free(mydata); + free(self->popt); +} + +/* + * webproxy_stats + * + * This procedure is called regularly to update statistics sent to ircd. + */ +void +webproxy_stats(self) +AnInstance *self; +{ + struct webproxy_private *mydata = self->data; + char mybuf[256]; + int len; + int i; + + len=snprintf(mybuf, 256, "S webproxy port:open"); + for (i=0;iportcount;i++) + len+=snprintf(mybuf+len, 256-len, " %u:%u", + mydata->ports[i], mydata->open[i]); + + len+=snprintf(mybuf+len, 256-len, " closed %u noproxy %u", + mydata->closed, mydata->noproxy); + + sendto_ircd(mybuf); + + sendto_ircd + ("S webproxy cache open %u closed %u noproxy %u miss %u (%u <= %u)", + mydata->chito, mydata->chitc, mydata->chitn, mydata->cmiss, + mydata->cnow, mydata->cmax); +} + +/* + * webproxy_start + * + * This procedure is called to start the socks check procedure. + * Returns 0 if everything went fine, + * -1 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. webproxy_clean + * will NOT be called) + */ +int +webproxy_start(cl) +u_int cl; +{ + + struct webproxy_private *mydata = cldata[cl].instance->data; + char *error; + int fd; + + if (cldata[cl].state & A_DENY) { + /* no point of doing anything */ + DebugLog((ALOG_DWEBPROXY, 0, + "webproxy_start(%d): A_DENY alredy set ", cl)); + return -1; + } + if (cldata[cl].mod_status == 0) + if (webproxy_check_cache(cl)) + return -1; + + if (strchr(cldata[cl].itsip,':')) + return -1; + + while (cldata[cl].mod_status < mydata->portcount) { + DebugLog( + (ALOG_DWEBPROXY, 0, "webproxy_start(%d): Connecting to %s:%u", + cl, cldata[cl].itsip, mydata->ports[cldata[cl].mod_status])); + fd = tcp_connect(cldata[cl].ourip, cldata[cl].itsip, + mydata->ports[cldata[cl].mod_status], + &error); + if (fd > 0) { + /*so that webproxy_work() is called when connected */ + cldata[cl].wfd = fd; + return 0; + } + DebugLog((ALOG_DWEBPROXY, 0, + "webproxy_start(%d): tcp_connect() reported %s", cl, + error)); + cldata[cl].mod_status++; + continue; + + } + + return -1; +} + +/* + * webproxy_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 +webproxy_work(cl) +u_int cl; +{ + struct webproxy_private *mydata = cldata[cl].instance->data; + + if (!mydata) + return -1; + + DebugLog( + (ALOG_DWEBPROXY, 0, "webproxy_work(%d): %d %d %d buflen=%d", + cl, mydata->ports[cldata[cl].mod_status], + 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. + */ + return webproxy_write(cl); + else + return webproxy_read(cl); +} + +/* + * webproxy_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 +webproxy_clean(cl) +u_int cl; +{ + DebugLog((ALOG_DWEBPROXY, 0, "webproxy_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; +} + +/* + * webproxy_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 +webproxy_timeout(cl) +u_int cl; +{ + DebugLog( + (ALOG_DWEBPROXY, 0, + "webproxy_timeout(%d): calling webproxy_clean ", cl)); + webproxy_clean(cl); + return -1; +} + +aModule Module_webproxy = +{"webproxy", webproxy_init, webproxy_release, webproxy_stats, + webproxy_start, webproxy_work, webproxy_timeout, webproxy_clean +}; diff -ru --new-file irc2.10.3p3/iauth/mod_webproxy_ext.h irc2.10.3p3+sd7/iauth/mod_webproxy_ext.h --- irc2.10.3p3/iauth/mod_webproxy_ext.h Thu Jan 1 02:00:00 1970 +++ irc2.10.3p3+sd7/iauth/mod_webproxy_ext.h Mon Feb 3 14:31:07 2003 @@ -0,0 +1,3 @@ +#ifndef MOD_WEBPROXY_C +extern aModule Module_webproxy; +#endif /* MOD_WEBPROXY_C */ diff -ru --new-file irc2.10.3p3/ircd/channel.c irc2.10.3p3+sd7/ircd/channel.c --- irc2.10.3p3/ircd/channel.c Sat Jul 7 17:29:33 2001 +++ irc2.10.3p3+sd7/ircd/channel.c Mon Feb 3 14:31:07 2003 @@ -55,9 +55,14 @@ static int add_modeid __P((int, aClient *, aChannel *, char *)); static int del_modeid __P((int, aChannel *, char *)); static Link *match_modeid __P((int, aClient *, aChannel *)); +static void send_names_one __P((aClient *,aClient *,char *,aChannel *,int)); static char *PartFmt = ":%s PART %s :%s"; +#ifdef SOPERCHAN +static aChannel *soperchan = NULL; +#endif + /* * some buffers for rebuilding channel/nick lists with ,'s */ @@ -611,6 +616,20 @@ add_user_to_channel(chptr, mp, CHFL_CHANOP); chptr->mode.mode = smode|MODE_SECRET; +#ifdef CLIENTS_CHANNEL + chptr = get_channel(mp, "&CLIENTS", CREATE); + strcpy(chptr->topic,"SERVER MESSAGES: client activities [various]"); + add_user_to_channel(chptr, mp, CHFL_CHANOP); + chptr->mode.mode = smode|MODE_SECRET; +#endif + +#ifdef SMODE_CHAN + chptr = get_channel(mp, "&SMODE", CREATE); + strcpy(chptr->topic, "SERVER MESSAGES: server modes received"); + add_user_to_channel(chptr, mp, CHFL_CHANOP); + chptr->mode.mode = smode | MODE_SECRET; +#endif + setup_svchans(); } @@ -854,6 +873,88 @@ return; } +#ifdef SOPER_SMODE + +/* + * m_smode + * parv[0] - sender + * parv[1] - target (channel only) + * parv[2] - modes + * ... - args + */ + +int m_smode(cptr, sptr, parc, parv) +aClient *cptr, *sptr; +int parc; +char *parv[]; +{ + aChannel *chptr = NULL; + int penalty = 0; + + if (MyClient(sptr)) + { + if (parc < 3) + { + sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS, parv[0]), + "SMODE"); + return 0; + } + + clean_channelname(parv[1]); + + chptr = get_channel(sptr, parv[1], 0); + + if (!chptr) + { + sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL, parv[0]), + parv[1]); + return 0; + } + + if (!UseModes(parv[1])) + { + sendto_one(sptr, err_str(ERR_NOCHANMODES, parv[0]), + parv[1]); + return 0; + } + + SetForce(sptr); + + if (!set_mode(cptr, sptr, chptr, &penalty, parc - 2, + parv + 2, modebuf, parabuf)) + return 0; + + ClearForce(sptr); + +#ifdef SOPERCHAN + if (soperchan = get_channel(&me, SOPERCHAN, 0)) + sendto_channel_butone(&me, &me, soperchan, + ":%s NOTICE %s :%s requested SMODE %s %s %s", + ME, SOPERCHAN, parv[0], parv[1], modebuf, parabuf); +#endif + +#ifdef SMODE_CHAN + sendto_flag(SCH_SMODE, "Servermode: %s MODE %s %s %s", + ME, parv[1], modebuf, parabuf); +#endif + + if (modebuf[1] == 'e' || modebuf[1] == 'I') + sendto_match_servs_v(chptr, &me, SV_NMODE, + ":%s MODE %s %s %s", ME, parv[1], modebuf, + parabuf); + else + sendto_match_servs(chptr, &me, ":%s MODE %s %s %s", + ME, parv[1], modebuf, parabuf); + + sendto_channel_butserv(chptr, &me, ":%s MODE %s %s %s", ME, + parv[1], modebuf, parabuf); + } + + return 0; +} + +#endif + /* * m_mode * parv[0] - sender @@ -930,6 +1031,12 @@ sendto_one(sptr, err_str(num, parv[0]), name); continue; } +#ifdef SMODE_CHAN + if (IsServer(sptr)) + sendto_flag(SCH_SMODE, + "Servermode: %s MODE %s %s %s", + parv[0], name, modebuf, parabuf); +#endif if (strlen(modebuf) > (size_t)1) { /* got new mode to pass on */ if (modebuf[1] == 'e' || modebuf[1] == 'I') @@ -1004,6 +1111,7 @@ aClient *who; Mode *mode, oldm; Link *plp = NULL; + char buf[KEYLEN+1]; int compat = -1; /* to prevent mixing old/new modes */ *mbuf = *pbuf = '\0'; @@ -1012,7 +1120,7 @@ mode = &(chptr->mode); bcopy((char *)mode, (char *)&oldm, sizeof(Mode)); - ischop = IsServer(sptr) || is_chan_op(sptr, chptr); + ischop = IsServer(sptr) || is_chan_op(sptr, chptr) || IsForce(sptr); new = mode->mode; while (curr && *curr && count >= 0) @@ -1060,7 +1168,7 @@ } else /* not IsMember() */ { - if (!IsServer(sptr)) + if (!IsServer(sptr) && !IsForce(sptr)) { sendto_one(sptr, err_str(ERR_NOTONCHANNEL, sptr->name), chptr->chname); @@ -1099,7 +1207,7 @@ if (MyClient(sptr) || opcnt >= MAXMODEPARAMS + 1) #endif break; - if (!IsServer(sptr) && !IsMember(sptr, chptr)) + if (!IsServer(sptr) && !IsMember(sptr, chptr) && !IsForce(sptr)) { sendto_one(sptr, err_str(ERR_NOTONCHANNEL, sptr->name), @@ -1120,7 +1228,8 @@ parv[0], chptr->chname); break; } - if (who == cptr && whatt == MODE_ADD && *curr == 'o') + if (who == cptr && whatt == MODE_ADD && *curr == 'o' + && !IsForce(cptr)) break; if (whatt == MODE_ADD) @@ -1166,8 +1275,17 @@ break; case 'k': *penalty += 1; - if (--parc <= 0) - break; + if (--parc <= 0) { /* a channel key query --fiction */ + *(curr+1) = '\0'; /* Stop MODE # bb.. */ + if ((*chptr->mode.key) && IsMember(sptr, chptr)) { + strncpy(buf, chptr->mode.key, KEYLEN); + } + else { *buf = '\0'; }; + + sendto_one(sptr, rpl_str(RPL_CHANNELMODEIS, sptr->name), + chptr->chname, (*chptr->mode.key) ? "+k" : "+", buf); + break; + } parv++; /* check now so we eat the parameter if present */ if (keychange) @@ -1366,7 +1484,33 @@ * limit 'l' to only *1* change per mode command but * eat up others. */ - if (limitset || !ischop) + + /* channel limit query ("mode -l" is an exception to also unset limit + * without extra parameter). To not break stuff. --fiction + */ + + if ((parc-1 <= 0) && (whatt != MODE_DEL)) { + *(curr+1) = '\0'; /* Stop MODE # bb.. */ + if ((chptr->mode.limit) && IsMember(sptr, chptr)) { + SPRINTF(buf, "%d", chptr->mode.limit); + } + else { *buf = '\0'; }; + + sendto_one(sptr, rpl_str(RPL_CHANNELMODEIS, sptr->name), + chptr->chname, (chptr->mode.limit) ? "+l" : "+" , buf); + break; + } + + /* just pretend that there was a mode change to be able to + * return an error later --fiction + */ + + if (!ischop) { + count++; + break; + } + + if (limitset) { if (whatt == MODE_ADD && --parc > 0) parv++; @@ -1398,9 +1542,14 @@ *penalty += 2; break; } - sendto_one(cptr, err_str(ERR_NEEDMOREPARAMS, - cptr->name), "MODE +l"); - break; +/* sendto_one(cptr, err_str(ERR_NEEDMOREPARAMS, + cptr->name), "MODE +l"); + break; + +Obosleted by new syntax - "mode +l" or just +"mode l" gives current limit --fiction +*/ + case 'i' : /* falls through for default case */ if (whatt == MODE_DEL && ischop) while ((lp = chptr->invites)) @@ -1452,9 +1601,13 @@ if (whatt == MODE_ADD) { if (*ip == MODE_PRIVATE) + { new &= ~MODE_SECRET; + } else if (*ip == MODE_SECRET) + { new &= ~MODE_PRIVATE; + } new |= *ip; } else @@ -1469,6 +1622,7 @@ break; } curr++; + /* * Make sure modes strings such as "+m +t +p +i" are parsed * fully. @@ -1761,6 +1915,12 @@ else if (lp == NULL) return (ERR_BANNEDFROMCHAN); +#ifdef CLIENTS_CHANNEL + if (chptr->chname[0]=='&') { + if (!strcmp(chptr->chname,"&CLIENTS") && !IsAnOper(sptr)) + return (ERR_INVITEONLYCHAN); + } +#endif if ((chptr->mode.mode & MODE_INVITEONLY) && !match_modeid(CHFL_INVITE, sptr, chptr) && (lp == NULL)) @@ -1773,6 +1933,20 @@ (lp == NULL)) return (ERR_CHANNELISFULL); +#ifdef SMODE_CHAN + if (chptr->chname[0] == '&') + { + if (!strcmp(chptr->chname, "&SMODE") && +#ifdef LOCOP_SMODE_CHAN + !IsAnOper(sptr) +#else + !IsOper(sptr) +#endif + ) + return (ERR_INVITEONLYCHAN); + } +#endif + if (banned) sendto_channel_butone(&me, &me, chptr, ":%s NOTICE %s :%s carries an invitation (overriding ban on %s).", @@ -1986,6 +2160,76 @@ } } +#ifdef SOPER_SJOIN + +/* + * m_sjoin + * parv[0] - sender + * parv[1] - channel + */ + +int m_sjoin(cptr, sptr, parc, parv) +aClient *cptr, *sptr; +int parc; +char *parv[]; +{ + aChannel *chptr = NULL; + int penalty = 0; + char *p; + + if (MyClient(sptr)) + { + if (parc < 2) + { + sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS, parv[0]), + "SJOIN"); + return 0; + } + + clean_channelname(p = parv[1]); + + chptr = get_channel(sptr, parv[1], 0); + + if (!chptr) + { + sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL, parv[0]), + parv[1]); + return 0; + } + + if (check_channelmask(sptr, cptr, parv[1]) == -1) + return 0; + + if (IsMember(sptr, chptr)) + return 0; + +#ifdef SOPERCHAN + if (soperchan = get_channel(&me, SOPERCHAN, 0)) + sendto_channel_butone(&me, &me, soperchan, + ":%s NOTICE %s :%s requested SJOIN %s", + ME, SOPERCHAN, parv[0], parv[1]); +#endif + + add_user_to_channel(chptr, sptr, 0); + + if (parv[1][1] == '!') + sendto_match_servs_v(chptr, cptr, SV_NCHAN, + ":%s JOIN %s", parv[0], parv[1]); + else + sendto_match_servs(chptr, cptr, ":%s JOIN %s", + parv[0], parv[1]); + + sendto_channel_butserv(chptr, cptr, ":%s JOIN %s", parv[0], + parv[1]); + + m_names(cptr, sptr, 2, parv); + } + + return 0; +} + +#endif + /* ** m_join ** parv[0] = sender prefix @@ -2226,11 +2470,32 @@ ** channel so make them (rightfully) the Channel ** Operator. */ + /* do not make them Channel Operator if the server seems + ** to be splitted (i.e. if total server count is less + ** than a given number and channel count is less + ** than another given number or user count is + ** less than a third number. (francesco) + */ flags = 0; chop[0] = '\0'; - if (MyConnect(sptr) && UseModes(name) && - (!IsRestricted(sptr) || (*name == '&')) && !chptr->users && - !(chptr->history && *chptr->chname == '!')) +#ifdef SPLIT_HANDLE + if (MyConnect(sptr) && UseModes(name) && + ((*name != '#') || !iconf.split) && +#else + if ( + MyConnect(sptr) && + UseModes(name) && +#endif + ( + !IsRestricted(sptr) || + (*name == '&') + ) && + !chptr->users && + !( + chptr->history + && *chptr->chname == '!' + ) + ) { if (*name == '!') strcpy(chop, "\007O"); @@ -2269,11 +2534,18 @@ { /* no need if user is creating the channel */ if (chptr->users != 1) + { sendto_channel_butserv(chptr, sptr, ":%s MODE %s +%s %s %s", cptr->name, name, s, parv[0], *(s+1)=='v'?parv[0]:""); +#ifdef SMODE_CHAN + sendto_flag(SCH_SMODE, + "Servermode: %s JOIN %s (with mode +%s)", + parv[0], name, s); +#endif + } *--s = '\007'; } /* @@ -2287,10 +2559,20 @@ { del_invite(sptr, chptr); if (chptr->topic[0] != '\0') + { sendto_one(sptr, rpl_str(RPL_TOPIC, parv[0]), name, chptr->topic); +#ifdef TOPICWHOTIME + if (chptr->topic_time>0) + { + sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME, parv[0]), + name, IsAnonymous(chptr) ? "Anonymous!Anonymous@Anomyous" : chptr->topic_nuh, + chptr->topic_time); + } +#endif + } parv[1] = name; - (void)m_names(cptr, sptr, 2, parv); + send_names_one(cptr,sptr,parv[0],chptr,1); if (IsAnonymous(chptr) && !IsQuiet(chptr)) { sendto_one(sptr, ":%s NOTICE %s :Channel %s has the anonymous flag set.", ME, chptr->chname, chptr->chname); @@ -2697,31 +2979,9 @@ sendto_serv_butone(cptr, ":%s KICK %s %s :%s", parv[0], name, nickbuf, comment); } /* loop on parv[1] */ - return penalty; } -int count_channels(sptr) -aClient *sptr; -{ -Reg aChannel *chptr; - Reg int count = 0; - - for (chptr = channel; chptr; chptr = chptr->nextch) - { - if (chptr->users) /* don't count channels in history */ -#ifdef SHOW_INVISIBLE_LUSERS - if (SecretChannel(chptr)) - { - if (IsAnOper(sptr)) - count++; - } - else -#endif - count++; - } - return (count); -} /* ** m_topic @@ -2781,14 +3041,28 @@ if (chptr->topic[0] == '\0') sendto_one(sptr, rpl_str(RPL_NOTOPIC, parv[0]), chptr->chname); - else + else { sendto_one(sptr, rpl_str(RPL_TOPIC, parv[0]), chptr->chname, chptr->topic); +#ifdef TOPICWHOTIME + sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME, parv[0]), + chptr->chname, IsAnonymous(chptr) ? "Anonymous!anonymous@anonymous" : chptr->topic_nuh, + chptr->topic_time); +#endif + } } else if ((chptr->mode.mode & MODE_TOPICLIMIT) == 0 || is_chan_op(sptr, chptr)) { /* setting a topic */ strncpyzt(chptr->topic, topic, sizeof(chptr->topic)); +#ifdef TOPICWHOTIME + strcpy(chptr->topic_nuh, sptr->name); + strcat(chptr->topic_nuh, "!"); + strcat(chptr->topic_nuh, sptr->user->username); + strcat(chptr->topic_nuh, "@"); + strcat(chptr->topic_nuh, sptr->user->host); + chptr->topic_time = timeofday; +#endif sendto_match_servs(chptr, cptr,":%s TOPIC %s :%s", parv[0], chptr->chname, chptr->topic); @@ -2900,7 +3174,6 @@ return 2; } - /* ** m_list ** parv[0] = sender prefix @@ -2917,22 +3190,53 @@ if (parc > 2 && hunt_server(cptr, sptr, ":%s LIST %s %s", 2, parc, parv)) - return 10; + return MAXPENALTY; + if (BadPtr(parv[1])) + { + + Reg Link *lp; + if (!sptr->user) + { + sendto_one(sptr, rpl_str(RPL_LISTEND, parv[0])); + return 2; + } + +#ifdef LIST_ALIS_NOTE + if (MyConnect(sptr)) + { + sendto_one(sptr,":%s NOTICE %s :%s",ME,parv[0],LIST_ALIS_NOTE); + } +#endif + + /* First, show all +s/+p user is on */ + for (lp = sptr->user->channel; lp; lp = lp->next) + { + chptr = lp->value.chptr; + if (SecretChannel(chptr) || HiddenChannel(chptr)) + { + sendto_one(sptr, rpl_str(RPL_LIST, parv[0]), + chptr->chname,chptr->users, + chptr->topic); + } + } + + /* Second, show all visible channels + * +p channels users is not on, are not reported anymore - jv + */ for (chptr = channel; chptr; chptr = chptr->nextch) - { - if (!sptr->user || - !chptr->users || /* empty locked channel */ - (SecretChannel(chptr) && !IsMember(sptr, chptr))) + { + if (!chptr->users || /* empty locked channel */ + SecretChannel(chptr) || HiddenChannel(chptr)) continue; - name = ShowChannel(sptr, chptr) ? chptr->chname : NULL; - rlen += sendto_one(sptr, rpl_str(RPL_LIST, parv[0]), - name ? name : "*", chptr->users, - name ? chptr->topic : ""); - if (!MyConnect(sptr) && rlen > CHREPLLEN) - break; - } - else { + + sendto_one(sptr, rpl_str(RPL_LIST, parv[0]), + chptr->chname, chptr->users, + chptr->topic); + } + } + else + { parv[1] = canonize(parv[1]); for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL) { @@ -2974,9 +3278,138 @@ return 2; } +/* + * send_names_one - send NAMES for one specific channel + * sends RPL_ENDOFNAMES when sendeon > 0 + */ +static void send_names_one(cptr,sptr,to,chptr,sendeon) +aClient *cptr,*sptr; +char *to; +aChannel *chptr; +int sendeon; +{ + Reg Link *lp; + Reg aClient *acptr; + char *pbuf = buf; + int pxlen,ismember,nlen,maxlen,showusers = 1, sent = 0; + + if (!chptr->users) /* channel in ND */ + { + showusers = 0; + } + else + { + ismember = (lp = find_channel_link(sptr->user->channel,chptr)) ? 1 : 0; + } + if (SecretChannel(chptr)) + { + if (!ismember) + { + showusers = 0; + } + else + { + *pbuf++ = '@'; + } + } + else if (HiddenChannel(chptr)) + { + *pbuf++ = '*'; + } + else + { + *pbuf++ = '='; + } + + if (showusers) + { + *pbuf++ = ' '; + pxlen = strlen(chptr->chname); + memcpy(pbuf,chptr->chname,pxlen); + pbuf += pxlen; + *pbuf++ = ' '; + *pbuf++ = ':'; + *pbuf = 0; + pxlen += 4; + if (IsAnonymous(chptr)) + { + if (ismember) + { + if (lp->flags & CHFL_CHANOP) + { + *pbuf++ = '@'; + } + else if (lp->flags & CHFL_VOICE) + { + *pbuf++ = '+'; + } + strcpy(pbuf,to); + } + sendto_one(sptr, rpl_str(RPL_NAMREPLY, to), buf); + } + else + { + /* server names + : : + spaces + "353" + nick length +\r\n + space for last + * entry. + */ + maxlen = BUFSIZE - 2 - 1 - strlen(ME) - 5 - strlen(to) - pxlen - NICKLEN - 2; + + for (lp = chptr->members;lp;lp=lp->next) + { + acptr = lp->value.cptr; + if (!ismember && IsInvisible(acptr)) + { + continue; + } + if (lp->flags & CHFL_CHANOP) + { + *pbuf++ = '@'; + } + else if (lp->flags & CHFL_VOICE) + { + *pbuf++ = '+'; + } + nlen = strlen(acptr->name); + /* This check is needed for server channels + * when someone removes +a mode from them. + * (server is member of such channel). + */ + if (nlen > NICKLEN) + { + nlen = NICKLEN; + } + memcpy(pbuf,acptr->name,nlen); + pbuf +=nlen; + *pbuf++ = ' '; + sent = 0; + if (((size_t) pbuf - (size_t) buf) > maxlen) + { + *pbuf = '\0'; + sendto_one(sptr, rpl_str(RPL_NAMREPLY, to), buf); + pbuf = buf + pxlen; + pbuf[0] = '\0'; + sent = 1; + } + } + if (!sent) + { + *pbuf = '\0'; + sendto_one(sptr, rpl_str(RPL_NAMREPLY, to), buf); + } + } + } + if (sendeon) + { + sendto_one(sptr, rpl_str(RPL_ENDOFNAMES, to), chptr->chname); + } + return; + +} + /************************************************************************ * m_names() - Added by Jto 27 Apr 1989 + * Rewritten by jv 27 Apr 2001 ************************************************************************/ /* @@ -2988,186 +3421,245 @@ aClient *cptr, *sptr; int parc; char *parv[]; +{ + Reg aChannel *chptr; + Reg aClient *acptr; + Reg Link *lp; + int maxlen ,pxlen,nlen,cansend = 0, sent = 1; + char *para = parc > 1 ? parv[1] : NULL,*name, *p = NULL, *pbuf = buf; + + if (parc > 2 && + hunt_server(cptr, sptr, ":%s NAMES %s %s", 2, parc, parv)) + { + return MAXPENALTY; + } + + if (!BadPtr(para)) + { + for (; (name = strtoken(&p,parv[1], ",")); parv[1] = NULL) + { + clean_channelname(name); + if BadPtr(name) + { + continue; + } + chptr = find_channel(name, NULL); + if (chptr) + { + send_names_one(cptr,sptr,parv[0],chptr,1); + } + else + { + sendto_one(sptr, rpl_str(RPL_ENDOFNAMES, parv[0]), name); + } + sent++; + if (!MyConnect(sptr) || sent > MAXPENALTY / 3) + { + break; + } + } + return sent ? 2 * sent : 2; + } + /* Client wants all nicks/channels which is seriously cpu intensive + * Allowed for local clients only. + * First, list all secret channels user is on + */ + for (lp = sptr->user->channel; lp; lp = lp->next) + { + chptr = lp->value.chptr; + if (SecretChannel(chptr)) + { + send_names_one(cptr,sptr,parv[0],chptr,0); + } + } + + /* Second, list all non-secret channels */ + for (chptr = channel; chptr; chptr = chptr->nextch) + { + if (!chptr->users || /* channel in CD */ + SecretChannel(chptr)) + { + continue; + } + send_names_one(cptr,sptr,parv[0],chptr,0); + } + /* Third, list all remaining users + * ie, those which aren't on any channel, or are at Anonymous one + */ + strcpy(pbuf,"* * :"); + pxlen = 5; + pbuf += pxlen; + maxlen = BUFSIZE - 2 - 1 - strlen(ME) - 5 - strlen(parv[0]) - 5 - NICKLEN - 2; + for (acptr = client; acptr ;acptr = acptr->next) + { + if (!IsPerson(acptr) || IsInvisible(acptr)) + { + continue; + } + + lp = acptr->user->channel; + cansend = 1; + while (lp) + { + chptr = lp->value.chptr; + if (PubChannel(chptr) || SecretChannel(chptr) || IsMember(sptr,chptr)) + { /* already shown */ + cansend = 0; + break; + } + lp = lp->next; + } + if (!cansend) + { + continue; + } + nlen = strlen(acptr->name); + if (nlen > NICKLEN) + { + nlen = NICKLEN; + } + + memcpy(pbuf, acptr->name, nlen); + pbuf += nlen; + *pbuf++ = ' '; + sent = 0; + if ((size_t) pbuf - (size_t) buf > maxlen) + { + *pbuf = '\0'; + sendto_one(sptr, rpl_str(RPL_NAMREPLY, parv[0]), buf,0); + sent = 1; + pbuf = buf + pxlen; + pbuf[0] = '\0'; + } + } + if (!sent) + { + *pbuf = '\0'; + sendto_one(sptr, rpl_str(RPL_NAMREPLY, parv[0]), buf,0); + } + sendto_one(sptr, rpl_str(RPL_ENDOFNAMES, parv[0]), "*"); + return MAXPENALTY; +} + +#ifdef SOPER_SNAMES + +/* + * m_snames (ripped m_names) + * parv[0] = sender prefix + * parv[1] = channel +*/ +int m_snames(cptr, sptr, parc, parv) +aClient *cptr, *sptr; +int parc; +char *parv[]; { Reg aChannel *chptr; Reg aClient *c2ptr; Reg Link *lp; - aChannel *ch2ptr = NULL; int idx, flag, len, mlen, rlen = 0; - char *s, *para = parc > 1 ? parv[1] : NULL; + char *s, *para; - if (parc > 2 && - hunt_server(cptr, sptr, ":%s NAMES %s %s", 2, parc, parv)) - return 10; + if (!MyClient(sptr)) + return 0; + + if (parc < 2) + { + sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS, parv[0]), + "SNAMES"); + return 0; + } mlen = strlen(ME) + 10; /* server names + : : + spaces + "353" */ mlen += strlen(parv[0]); - if (!BadPtr(para)) - { - s = index(para, ','); - if (s && MyConnect(sptr) && s != para) - { - parv[1] = ++s; - (void)m_names(cptr, sptr, parc, parv); - } - clean_channelname(para); - ch2ptr = find_channel(para, (aChannel *)NULL); - } + + clean_channelname(para = parv[1]); + chptr = get_channel(sptr, parv[1], 0); + + if (!chptr) + { + sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL, parv[0]), + parv[1]); + return 0; + } + +#ifdef SOPERCHAN + if (soperchan = get_channel(&me, SOPERCHAN, 0)) + sendto_channel_butone(&me, &me, soperchan, + ":%s NOTICE %s :%s requested SNAMES %s", + ME, SOPERCHAN, parv[0], parv[1]); +#endif *buf = '\0'; - /* - * First, do all visible channels (public and the one user self is) - */ + /* Find users on same channel (defined by chptr) */ - for (chptr = channel; chptr; chptr = chptr->nextch) - { - if (!chptr->users || /* locked empty channel */ - ((chptr != ch2ptr) && !BadPtr(para))) /* 'wrong' channel */ - continue; - if (!MyConnect(sptr) && (BadPtr(para) || (rlen > CHREPLLEN))) - break; - if ((BadPtr(para) || !HiddenChannel(chptr)) && - !ShowChannel(sptr, chptr)) - continue; /* -- users on this are not listed */ - - /* Find users on same channel (defined by chptr) */ - - (void)strcpy(buf, "* "); - len = strlen(chptr->chname); - (void)strcpy(buf + 2, chptr->chname); - (void)strcpy(buf + 2 + len, " :"); - - if (PubChannel(chptr)) - *buf = '='; - else if (SecretChannel(chptr)) - *buf = '@'; + (void)strcpy(buf, "* "); + len = strlen(chptr->chname); + (void)strcpy(buf + 2, chptr->chname); + (void)strcpy(buf + 2 + len, " :"); + + if (PubChannel(chptr)) + *buf = '='; + else if (SecretChannel(chptr)) + *buf = '@'; - if (IsAnonymous(chptr)) - { - if ((lp = find_user_link(chptr->members, sptr))) - { - if (lp->flags & CHFL_CHANOP) - (void)strcat(buf, "@"); - else if (lp->flags & CHFL_VOICE) - (void)strcat(buf, "+"); - (void)strcat(buf, parv[0]); - } - rlen += strlen(buf); - sendto_one(sptr, rpl_str(RPL_NAMREPLY, parv[0]), buf); - continue; - } - idx = len + 4; /* channel name + [@=] + 2?? */ - flag = 1; - for (lp = chptr->members; lp; lp = lp->next) - { - c2ptr = lp->value.cptr; - if (IsInvisible(c2ptr) && !IsMember(sptr,chptr)) - continue; - if (lp->flags & CHFL_CHANOP) - { - (void)strcat(buf, "@"); - idx++; - } - else if (lp->flags & CHFL_VOICE) - { - (void)strcat(buf, "+"); - idx++; - } - (void)strncat(buf, c2ptr->name, NICKLEN); - idx += strlen(c2ptr->name) + 1; - flag = 1; - (void)strcat(buf," "); - if (mlen + idx + NICKLEN + 1 > BUFSIZE - 2) - { - sendto_one(sptr, rpl_str(RPL_NAMREPLY, - parv[0]), buf); - (void)strncpy(buf, "* ", 3); - (void)strncpy(buf+2, chptr->chname, - len + 1); - (void)strcat(buf, " :"); - if (PubChannel(chptr)) - *buf = '='; - else if (SecretChannel(chptr)) - *buf = '@'; - idx = len + 4; - flag = 0; - } - } - if (flag) - { - rlen += strlen(buf); - sendto_one(sptr, rpl_str(RPL_NAMREPLY, parv[0]), buf); - } - } /* for(channels) */ - if (!BadPtr(para)) - { - if (!MyConnect(sptr) && (rlen > CHREPLLEN)) - sendto_one(sptr, err_str(ERR_TOOMANYMATCHES, parv[0]), - para); - sendto_one(sptr, rpl_str(RPL_ENDOFNAMES, parv[0]), para); - return(1); - } + idx = len + 4; /* channel name + [@=] + 2?? */ + flag = 1; - /* Second, do all non-public, non-secret channels in one big sweep */ + for (lp = chptr->members; lp; lp = lp->next) + { + c2ptr = lp->value.cptr; - (void)strncpy(buf, "* * :", 6); - idx = 5; - flag = 0; - for (c2ptr = client; c2ptr; c2ptr = c2ptr->next) - { - aChannel *ch3ptr; - int showflag = 0, secret = 0; + if (lp->flags & CHFL_CHANOP) + { + (void)strcat(buf, "@"); + idx++; + } + + else if (lp->flags & CHFL_VOICE) + { + (void)strcat(buf, "+"); + idx++; + } - if (!IsPerson(c2ptr) || IsInvisible(c2ptr)) - continue; - if (!MyConnect(sptr) && (BadPtr(para) || (rlen > CHREPLLEN))) - break; - lp = c2ptr->user->channel; - /* - * don't show a client if they are on a secret channel or - * they are on a channel sptr is on since they have already - * been show earlier. -avalon - */ - while (lp) - { - ch3ptr = lp->value.chptr; - if (PubChannel(ch3ptr) || IsMember(sptr, ch3ptr)) - showflag = 1; - if (SecretChannel(ch3ptr)) - secret = 1; - lp = lp->next; - } - if (showflag) /* have we already shown them ? */ - continue; - if (secret) /* on any secret channels ? */ - continue; (void)strncat(buf, c2ptr->name, NICKLEN); idx += strlen(c2ptr->name) + 1; - (void)strcat(buf," "); flag = 1; - if (mlen + idx + NICKLEN > BUFSIZE - 2) - { - rlen += strlen(buf); - sendto_one(sptr, rpl_str(RPL_NAMREPLY, parv[0]), buf); - (void)strncpy(buf, "* * :", 6); - idx = 5; + (void)strcat(buf," "); + if (mlen + idx + NICKLEN + 1 > BUFSIZE - 2) + { + sendto_one(sptr, rpl_str(RPL_NAMREPLY, + parv[0]), buf); + (void)strncpy(buf, "* ", 3); + (void)strncpy(buf+2, chptr->chname, + len + 1); + (void)strcat(buf, " :"); + if (PubChannel(chptr)) + *buf = '='; + else if (SecretChannel(chptr)) + *buf = '@'; + idx = len + 4; flag = 0; - } - } + } + } + if (flag) - { + { rlen += strlen(buf); sendto_one(sptr, rpl_str(RPL_NAMREPLY, parv[0]), buf); - } - if (!MyConnect(sptr) && rlen > CHREPLLEN) - sendto_one(sptr, err_str(ERR_TOOMANYMATCHES, parv[0]), - para ? para : "*"); - /* This is broken.. remove the recursion? */ - sendto_one(sptr, rpl_str(RPL_ENDOFNAMES, parv[0]), "*"); - return 2; + } + + sendto_one(sptr, rpl_str(RPL_ENDOFNAMES, parv[0]), para); + + sendto_channel_butone(&me, &me, chptr, + ":%s NOTICE %s :%s does SNAMES on this channel (%s)", + ME, parv[1], parv[0], parv[1]); + + return 0; } +#endif + void send_user_joins(cptr, user) aClient *cptr, *user; { @@ -3408,7 +3900,11 @@ if (curh_nb == 0) { #ifdef DEBUGMODE +#ifdef LOCAL_REJECTIONS_ONLY + sendto_flag(SCH_NOTICE, +#else sendto_flag(SCH_LOCAL, +#endif "Channel garbage: live %u (max %u), hist %u (extended)", cur_nb - 1, max_nb - 1, curh_nb); #endif @@ -3445,7 +3941,11 @@ } #ifdef DEBUGMODE +#ifdef LOCAL_REJECTIONS_ONLY + sendto_flag(SCH_NOTICE, +#else sendto_flag(SCH_LOCAL, +#endif "Channel garbage: live %u (max %u), hist %u (removed %u)%s", cur_nb - 1, max_nb - 1, curh_nb, del - istat.is_hchan, (split) ? " split detected" : ""); @@ -3453,3 +3953,156 @@ /* Check again after CHECKFREQ seconds */ return (time_t) (now + CHECKFREQ); } + +#ifdef SOPER_SCLEAN + +/* + * m_sclean + * parv[0] - sender + * parv[1] - channel + */ + +int m_sclean(cptr, sptr, parc, parv) +aClient *cptr, *sptr; +int parc; +char *parv[]; +{ + aChannel *chptr; + Link *p; + char *q, deopbuf[BUFSIZ] = { 0 }, deopbuf2[BUFSIZ] = { 0 }; + int deopcount = 0, newchan; + + if (!MyClient(sptr)) + return 0; + + if (parc < 2) + { + sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS, parv[0]), + "SCLEAN"); + return 0; + } + + clean_channelname(q = parv[1]); + + chptr = get_channel(sptr, parv[1], 0); + + if (!chptr) + { + sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL, parv[0]), parv[1]); + return 0; + } + + if (!UseModes(parv[1])) + { + sendto_one(sptr, err_str(ERR_NOCHANMODES, parv[0]), parv[1]); + return 0; + } + +#ifdef SOPERCHAN + if (soperchan = get_channel(&me, SOPERCHAN, 0)) + sendto_channel_butone(&me, &me, soperchan, + ":%s NOTICE %s :%s requested SCLEAN %s", + ME, SOPERCHAN, parv[0], parv[1]); +#endif + + newchan = parv[1][1] == '!'; + + for (p = chptr->members; p; p = p->next) + { + if (is_chan_op(p->value.cptr, chptr)) + { + p->flags = CHFL_CHANOP & MODE_DEL; + change_chan_flag(p, chptr); + if (!deopcount) { + strcpy(deopbuf, "-"); + deopbuf2[0] = 0; + } + strcat(deopbuf, "o"); + strcat(deopbuf2, p->value.cptr->name); + strcat(deopbuf2, " "); + deopcount++; + if (deopcount == 3) + { + if (newchan) + sendto_match_servs_v(chptr, &me, + SV_NCHAN, ":%s MODE %s %s %s", ME, + parv[1], deopbuf, deopbuf2); + else + sendto_match_servs(chptr, &me, + ":%s MODE %s %s %s", ME, parv[1], + deopbuf, deopbuf2); + +#ifdef SMODE_CHAN + sendto_flag(SCH_SMODE, "Servermode: %s MODE %s %s %s", + ME, parv[1], deopbuf); +#endif + + sendto_channel_butserv(chptr, &me, + ":%s MODE %s %s %s", ME, parv[1], deopbuf, deopbuf2); + + deopbuf[0] = 0; + deopcount = 0; + } + } + } + + if (deopcount) + { +#ifdef SMODE_CHAN + sendto_flag(SCH_SMODE, "Servermode: %s MODE %s %s %s", + ME, parv[1], deopbuf, deopbuf2); +#endif + if (newchan) + sendto_match_servs_v(chptr, &me, + SV_NCHAN, ":%s MODE %s %s %s", ME, + parv[1], deopbuf, deopbuf2); + else + sendto_match_servs(chptr, &me, + ":%s MODE %s %s %s", ME, parv[1], + deopbuf, deopbuf2); + + sendto_channel_butserv(chptr, &me, + ":%s MODE %s %s %s", ME, parv[1], deopbuf, deopbuf2); + } + + if (IsMember(sptr, chptr)) + { + if (newchan) + sendto_match_servs_v(chptr, cptr, SV_NCHAN, + ":%s PART %s", parv[0], parv[1]); + else + sendto_match_servs(chptr, cptr, ":%s PART %s", + parv[0], parv[1]); + + sendto_channel_butserv(chptr, cptr, ":%s PART %s", parv[0], + parv[1]); + + remove_user_from_channel(sptr, chptr); + } + + add_user_to_channel(chptr, sptr, CHFL_CHANOP); + +#ifdef SMODE_CHAN + sendto_flag(SCH_SMODE, "Servermode: %s JOIN %s (with mode +%s)", + parv[0], parv[1], "o"); +#endif + + if (newchan) + sendto_match_servs_v(chptr, cptr, SV_NCHAN, + ":%s JOIN %s\007o", parv[0], parv[1]); + else + sendto_match_servs(chptr, cptr, ":%s JOIN %s\007o", + parv[0], parv[1]); + + sendto_channel_butserv(chptr, cptr, ":%s JOIN %s", parv[0], + parv[1]); + +// m_names(cptr, sptr, 2, parv); + send_names_one(cptr, sptr, ME, chptr, 1); + sendto_channel_butserv(chptr, cptr, ":%s MODE %s +o %s", ME, + parv[1], sptr->name); + + return 0; +} + +#endif diff -ru --new-file irc2.10.3p3/ircd/channel_def.h irc2.10.3p3+sd7/ircd/channel_def.h --- irc2.10.3p3/ircd/channel_def.h Wed Sep 3 20:45:47 1997 +++ irc2.10.3p3+sd7/ircd/channel_def.h Mon Feb 3 14:31:07 2003 @@ -25,5 +25,3 @@ #define NullChn ((aChannel *)0) #define ChannelExists(n) (find_channel(n, NullChn) != NullChn) - -#define MAXMODEPARAMS 3 diff -ru --new-file irc2.10.3p3/ircd/channel_ext.h irc2.10.3p3+sd7/ircd/channel_ext.h --- irc2.10.3p3/ircd/channel_ext.h Fri Jan 23 15:28:13 1998 +++ irc2.10.3p3+sd7/ircd/channel_ext.h Mon Feb 3 14:31:07 2003 @@ -45,20 +45,25 @@ EXTERN void send_channel_modes __P((aClient *cptr, aChannel *chptr)); EXTERN void send_channel_members __P((aClient *cptr, aChannel *chptr)); EXTERN int m_mode __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); +EXTERN int m_smode __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); EXTERN void clean_channelname __P((Reg char *cn)); EXTERN void del_invite __P((aClient *cptr, aChannel *chptr)); EXTERN int m_join __P((Reg aClient *cptr, Reg aClient *sptr, int parc, char *parv[])); +EXTERN int m_sjoin __P((Reg aClient *cptr, Reg aClient *sptr, int parc, + char *parv[])); +EXTERN int m_sclean __P((Reg aClient *cptr, Reg aClient *sptr, int parc, + char *parv[])); EXTERN int m_njoin __P((Reg aClient *cptr, Reg aClient *sptr, int parc, char *parv[])); EXTERN int m_part __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); EXTERN int m_kick __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); -EXTERN int count_channels __P((aClient *sptr)); EXTERN int m_topic __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); EXTERN int m_invite __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); EXTERN int m_list __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); EXTERN int m_names __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); +EXTERN int m_snames __P((aClient *cptr, aClient *sptr, int parc, char *parv[])); EXTERN void send_user_joins __P((aClient *cptr, aClient *user)); EXTERN time_t collect_channel_garbage __P((time_t now)); #undef EXTERN diff -ru --new-file irc2.10.3p3/ircd/class.c irc2.10.3p3+sd7/ircd/class.c --- irc2.10.3p3/ircd/class.c Fri Dec 19 15:35:57 1997 +++ irc2.10.3p3+sd7/ircd/class.c Mon Feb 3 14:31:07 2003 @@ -134,8 +134,16 @@ * immeadiately after the first one (class 0). */ void add_class(class, ping, confreq, maxli, sendq, hlocal, uhlocal, - hglobal, uhglobal) -int class, ping, confreq, maxli, hlocal, uhlocal, hglobal, uhglobal; + hglobal, uhglobal +#ifdef USE_SSL +,ssl +#endif +) +int class, ping, confreq, maxli, hlocal, uhlocal, hglobal, uhglobal +#ifdef USE_SSL + ,ssl +#endif +; long sendq; { aClass *t, *p; @@ -165,6 +173,7 @@ MaxUHLocal(p) = uhlocal; MaxHGlobal(p) = hglobal; MaxUHGlobal(p) = uhglobal; + UseSSL(p) = ssl; if (p != t) Links(p) = 0; } diff -ru --new-file irc2.10.3p3/ircd/class_ext.h irc2.10.3p3+sd7/ircd/class_ext.h --- irc2.10.3p3/ircd/class_ext.h Tue Sep 23 23:47:56 1997 +++ irc2.10.3p3+sd7/ircd/class_ext.h Mon Feb 3 14:31:07 2003 @@ -38,9 +38,15 @@ EXTERN int get_client_class __P((aClient *acptr)); EXTERN int get_client_ping __P((aClient *acptr)); EXTERN int get_con_freq __P((aClass *clptr)); +#ifndef USE_SSL EXTERN void add_class __P((int class, int ping, int confreq, int maxli, long sendq, int hlocal, int uhlocal, int hglobal, int uhglobal)); +#else +EXTERN void add_class __P((int class, int ping, int confreq, int maxli, + long sendq, int hlocal, int uhlocal, + int hglobal, int uhglobal, int ssl)); +#endif EXTERN aClass *find_class __P((int cclass)); EXTERN void check_class(); EXTERN void initclass(); diff -ru --new-file irc2.10.3p3/ircd/hash.c irc2.10.3p3+sd7/ircd/hash.c --- irc2.10.3p3/ircd/hash.c Sun Feb 11 01:32:34 2001 +++ irc2.10.3p3+sd7/ircd/hash.c Mon Feb 3 14:31:07 2003 @@ -29,13 +29,16 @@ static aHashEntry *clientTable = NULL; static aHashEntry *channelTable = NULL; static aHashEntry *serverTable = NULL; +static aHashEntry *hostnameTable = NULL; static unsigned int *hashtab = NULL; static int clhits = 0, clmiss = 0, clsize = 0; static int chhits = 0, chmiss = 0, chsize = 0; +static int cnhits = 0, cnmiss = 0 ,cnsize = 0; static int svsize = 0; int _HASHSIZE = 0; int _CHANNELHASHSIZE = 0; int _SERVERSIZE = 0; +int _HOSTNAMEHASHSIZE = 0; /* * Hashing. @@ -74,6 +77,7 @@ char *nname; int *store; { + Reg u_char *name = (u_char *)nname; Reg u_char ch; Reg u_int hash = 1; @@ -123,6 +127,31 @@ return (hash); } + + +/* + * hash_host_name + */ +static u_int hash_host_name(hname, store) +char *hname; +int *store; +{ + + Reg u_char *name = (u_char *)hname; + Reg u_int hash = 0; + + for (; *name; name++) + { + hash = 31 * hash + hashtab[*name]; + } + + if (store) + *store = hash; + hash %= _HOSTNAMEHASHSIZE; + return (hash); +} + + /* bigger prime * * given a positive integer, return a prime number that's larger @@ -195,6 +224,21 @@ Debug((DEBUG_DEBUG, "Channel Hash Table Init: %d (%d)", _CHANNELHASHSIZE, size)); } +static void clear_hostname_hash_table(size) +int size; +{ + _HOSTNAMEHASHSIZE = bigger_prime(size); + cnhits = 0; + cnmiss = 0; + cnsize = 0; + if (!hostnameTable) + hostnameTable = (aHashEntry *)MyMalloc(_HOSTNAMEHASHSIZE * + sizeof(aHashEntry)); + bzero((char *)hostnameTable, sizeof(aHashEntry) * _HOSTNAMEHASHSIZE); + Debug((DEBUG_DEBUG, "Client Hash Table Init: %d (%d)", + _HOSTNAMEHASHSIZE, size)); +} + static void clear_server_hash_table(size) int size; @@ -218,6 +262,7 @@ : CHANNELHASHSIZE); clear_server_hash_table((_SERVERSIZE) ? _SERVERSIZE : SERVERSIZE); + clear_hostname_hash_table((_HOSTNAMEHASHSIZE) ? _HOSTNAMEHASHSIZE : HOSTNAMEHASHSIZE); /* * Moved multiplication out from the hashfunctions and into * a pre-generated lookup table. Should save some CPU usage @@ -236,6 +281,8 @@ Reg aClient *cptr; Reg aChannel *chptr; Reg aServer *sptr; + Reg anUser *user; + aHashEntry *otab = table; int osize = *size; @@ -282,19 +329,44 @@ clhits = 0; clsize = 0; clientTable = table; - + for (i = 0; i < osize; i++) { for (cptr = (aClient *)otab[i].list; cptr; cptr = next) { next = cptr->hnext; - (void)add_to_client_hash_table(cptr->name, + (void)add_to_client_hash_table(cptr->name, cptr); } } MyFree(otab); } + else if (otab == hostnameTable) + { + int i; + anUser *next; + Debug((DEBUG_ERROR, "Hostname Hash Table from %d to %d (%d)", + osize, new, clsize)); + sendto_flag(SCH_HASH, "Hostname Hash Table from %d to %d (%d)", + osize, new, clsize); + cnmiss = 0; + cnhits = 0; + cnsize = 0; + hostnameTable = table; + + for (i = 0; i < osize; i++) + { + for (user = (anUser *)otab[i].list; user; + user = next) + { + next = user->hnext; + (void)add_to_hostname_hash_table(user->host, + user); + } + } + MyFree(otab); + } else if (otab == serverTable) { Debug((DEBUG_ERROR, "Server Hash Table from %d to %d (%d)", @@ -352,6 +424,26 @@ } /* + * add_to_client_hash_table + */ +int add_to_hostname_hash_table(hostname, user) +char *hostname; +anUser *user; +{ + Reg u_int hashv; + + hashv = hash_host_name(hostname, &user->hashv); + user->hnext = (anUser *)hostnameTable[hashv].list; + hostnameTable[hashv].list = (void *)user; + hostnameTable[hashv].links++; + hostnameTable[hashv].hits++; + cnsize++; + if (cnsize > _HOSTNAMEHASHSIZE) + bigger_hash_table(&_HOSTNAMEHASHSIZE, hostnameTable, 0); + return 0; +} + +/* * add_to_server_hash_table */ int add_to_server_hash_table(sptr, cptr) @@ -456,7 +548,49 @@ } return 0; } +/* + * del_from_hostname_hash_table + */ +int del_from_hostname_hash_table(hostname, user) +char *hostname; +anUser *user; +{ + Reg anUser *tmp, *prev = NULL; + Reg u_int hashv; + hashv = user->hashv; + hashv %= _HOSTNAMEHASHSIZE; + for (tmp = (anUser *)hostnameTable[hashv].list; tmp; tmp = tmp->hnext) + { + if (tmp == user) + { + if (prev) + prev->hnext = tmp->hnext; + else + hostnameTable[hashv].list = (void *)tmp->hnext; + tmp->hnext = NULL; + if (hostnameTable[hashv].links > 0) + { + hostnameTable[hashv].links--; + cnsize--; + return 1; + } + else + { + sendto_flag(SCH_ERROR, "hn-hash table failure"); + Debug((DEBUG_ERROR, "hn-hash table failure")); + /* + * Should never actually return from here and + * if we do it is an error/inconsistency in the + * hash table. + */ + return -1; + } + } + prev = tmp; + } + return 0; +} /* * del_from_server_hash_table @@ -649,6 +783,30 @@ chmiss++; return chptr; } +/* + * hash_find_hostname + */ +anUser *hash_find_hostname(hostname, user) +char *hostname; +anUser *user; +{ + Reg anUser *tmp, *prv = NULL; + Reg aHashEntry *tmp3; + u_int hashv, hv; + + hashv = hash_host_name(hostname, &hv); + tmp3 = &hostnameTable[hashv]; + + for (tmp = (anUser *)tmp3->list; tmp; prv = tmp, tmp = tmp->hnext) + if (hv == tmp->hashv && !mycmp(hostname, tmp->host)) + { + cnhits++; + return (tmp); + } + cnmiss++; + return user; +} + /* * hash_find_channels @@ -746,14 +904,23 @@ if (parc > 1) { ch = *parv[1]; - if (islower(ch)) - table = clientTable; - else { - table = channelTable; - size = _CHANNELHASHSIZE; + switch (tolower(ch)) + { + case 'c': + table = channelTable; + size = _CHANNELHASHSIZE; + break; + case 'q': + table = hostnameTable; + size = _HOSTNAMEHASHSIZE; + break; + default: + table = clientTable; } - if (ch == 'L' || ch == 'l') + if (isupper(ch)) + { showlist = 1; + } } else { ch = '\0'; table = clientTable; @@ -950,6 +1117,8 @@ parv[0], clhits, clmiss); sendto_one(sptr,"NOTICE %s :Channel hits %d miss %d", parv[0], chhits, chmiss); + sendto_one(sptr,"NOTICE %s :Hostnames hits %d miss %d", + parv[0], cnhits, cnmiss); return 2; #endif } diff -ru --new-file irc2.10.3p3/ircd/hash_def.h irc2.10.3p3+sd7/ircd/hash_def.h --- irc2.10.3p3/ircd/hash_def.h Wed Sep 3 20:45:50 1997 +++ irc2.10.3p3+sd7/ircd/hash_def.h Mon Feb 3 14:31:07 2003 @@ -30,3 +30,5 @@ #define HASHSIZE ((int)((float)MAXCONNECTIONS*1.75)) #define CHANNELHASHSIZE ((int)(((float)MAXCONNECTIONS*1.75)/2.0)) #define SERVERSIZE (MAXCONNECTIONS/10) +#define HOSTNAMEHASHSIZE ((int)((float)MAXCONNECTIONS*1.75)) + diff -ru --new-file irc2.10.3p3/ircd/hash_ext.h irc2.10.3p3+sd7/ircd/hash_ext.h --- irc2.10.3p3/ircd/hash_ext.h Sun Jan 17 03:13:54 1999 +++ irc2.10.3p3+sd7/ircd/hash_ext.h Mon Feb 3 14:31:07 2003 @@ -40,10 +40,13 @@ EXTERN int add_to_client_hash_table __P((char *name, aClient *cptr)); EXTERN int add_to_channel_hash_table __P((char *name, aChannel *chptr)); EXTERN int add_to_server_hash_table __P((aServer *sptr, aClient *cptr)); +EXTERN int add_to_hostname_hash_table __P((char *hostname, anUser *user)); EXTERN int del_from_client_hash_table __P((char *name, aClient *cptr)); EXTERN int del_from_channel_hash_table __P((char *name, aChannel *chptr)); EXTERN int del_from_server_hash_table __P((aServer *sptr, aClient *cptr)); +EXTERN int del_from_hostname_hash_table __P((char *hostname, anUser *user)); EXTERN aClient *hash_find_client __P((char *name, aClient *cptr)); +EXTERN anUser *hash_find_hostname __P((char *hostname, anUser *user)); EXTERN aClient *hash_find_server __P((char *server, aClient *cptr)); EXTERN aChannel *hash_find_channel __P((char *name, aChannel *chptr)); EXTERN aChannel *hash_find_channels __P((char *name, aChannel *chptr)); diff -ru --new-file irc2.10.3p3/ircd/ircd.c irc2.10.3p3+sd7/ircd/ircd.c --- irc2.10.3p3/ircd/ircd.c Sun May 6 16:42:30 2001 +++ irc2.10.3p3+sd7/ircd/ircd.c Mon Feb 3 14:31:07 2003 @@ -30,10 +30,19 @@ aClient me; /* That's me */ aClient *client = &me; /* Pointer to beginning of Client list */ +#ifdef RECOVER +char md5me[RECOVER_SMDLEN]; +#endif static void open_debugfile(), setup_signals(), io_loop(); +#if defined(OPER_KLINE) || defined(LOCOP_KLINE) || \ + defined(OPER_TKLINE) || defined(LOCOP_TKLINE) +int kline_added = 0; +#endif + istat_t istat; +iconf_t iconf; char **myargv; int rehashed = 0; int portnum = -1; /* Server port number, listening this */ @@ -43,6 +52,7 @@ char *debugmode = ""; /* -"- -"- -"- -"- */ char *sbrk0; /* initial sbrk(0) */ char *tunefile = IRCDTUNE_PATH; +int initialconf = 1; static int dorehash = 0, dorestart = 0, restart_iauth = 0; @@ -54,6 +64,10 @@ time_t nextexpire = 1; /* next expire run on the dns cache */ time_t nextiarestart = 1; /* next time to check if iauth is alive */ +#ifdef DELAY_CLOSE +time_t nextdelayclose = 0; +#endif + #ifdef PROFIL extern etext(); @@ -337,6 +351,143 @@ return; } } +#ifdef DELAY_CLOSE +time_t delay_close(fd,reason) +int fd; +char *reason; +{ + struct fdlog + { + struct fdlog *next; + int fd; + time_t time; + char reason[BUFSIZE]; + }; + static struct fdlog *first = NULL, *last = NULL; + static int delayedfdnum = 0; + struct fdlog *next = first, *tmp; + + while (tmp = next) + if ((fd == -2) || (delayedfdnum == MAXCONNECTIONS / 10) + || tmp->time + DELAYCLOSETIME < timeofday) + { + next = tmp->next; + if (*(tmp->reason)) + { + send(tmp->fd,tmp->reason,strlen(tmp->reason),0); + } + close(tmp->fd); + delayedfdnum--; + MyFree(tmp); + if (!next) + { + if (first != last) + abort(); + first = last = NULL; + break; + } + first = next; + } + else + break; + + if (fd == -2) + { + nextdelayclose = 0; + return 0; + } + if (fd < 0) + return first ? first->time + DELAYCLOSETIME : 0; + /* disallow further receives */ + /* this should be shutdown(fd, SHUT_RD) but some OSes do- + * not define this. Check shutdown(2) if it matches. + * -- Beeth + */ +#ifndef SHUT_RD +#define SHUT_RD 0 +#endif + shutdown(fd, SHUT_RD); + + /* first create a new entry with fd and time */ + tmp = (struct fdlog *)MyMalloc(sizeof(*tmp)); + tmp->next = NULL; + tmp->fd = fd; + tmp->time = timeofday; + if (reason) + { + strncpy(tmp->reason,reason,BUFSIZE-3); + tmp->reason[BUFSIZE-3] = 0; + strcat(tmp->reason,"\r\n"); + } + delayedfdnum++; + istat.is_delayclosed++; + /* then add it to the list */ + if (last) + { + last->next = tmp; + last = tmp; + } + else + first = last = tmp; + + nextdelayclose = first ? first->time + DELAYCLOSETIME : 0; + return nextdelayclose; + +} + +#endif /* DELAY_CLOSE */ + +#if defined(OPER_KLINE) || defined(LOCOP_KLINE) || \ + defined(OPER_TKLINE) || defined(LOCOP_TKLINE) +void check_klines(void) +{ + Reg aClient *cptr; + int kflag, i; + char *reason; + + kline_added=0; + + for (i = highest_fd ; i>=0; i--) + { + + if (!(cptr = local[i]) || IsListening(cptr) || IsLog(cptr) || + IsHeld(cptr)) + continue; +#ifdef ILINE_FLAGS + if (IsKlineExempt(cptr)) + { + continue; + } +#endif + if ( IsPerson(cptr) ) + { + kflag = find_kill(cptr, 1, &reason); + } + else + { + kflag = 0; + reason = NULL; + } + + if (kflag && IsPerson(cptr)) + { + char buf[100]; + + sendto_flag(SCH_NOTICE, + "Kill line active for %s", + get_client_name(cptr, FALSE)); + cptr->exitc = EXITC_KLINE; + if (reason) + sprintf(buf, "Kill line active: %.80s", + reason); + (void)exit_client(cptr, cptr, &me, (reason) ? + buf : "Kill line active"); + } + } + + return; +} +#endif static time_t check_pings(currenttime) @@ -354,7 +505,6 @@ if (!(cptr = local[i]) || IsListening(cptr) || IsLog(cptr) || IsHeld(cptr)) continue; - /* * K and R lines once per minute, max. This is the max. * granularity in K-lines anyway (with time field). @@ -365,7 +515,11 @@ #endif /* TIMEDKLINES */ rehashed) { - if (IsPerson(cptr)) + if (IsPerson(cptr) +#ifdef ILINE_FLAGS + && !IsKlineExempt(cptr) +#endif + ) { kflag = find_kill(cptr, rehashed, &reason); #ifdef R_LINES_OFTEN @@ -656,6 +810,12 @@ ROOT_PATH); exit(5); } + if (chdir("/") != 0) + { + perror("chdir"); + (void)fprintf(stderr, "%s: Cannot chdir to /\n", IRCD_PATH); + exit(5); + } #endif /*CHROOTDIR*/ #ifdef ZIP_LINKS @@ -680,7 +840,9 @@ bzero((char *)&me, sizeof(me)); version = make_version(); /* Generate readable version string */ - +#ifdef SEND_ISUPPORT + isupport = make_isupport(); /* generate 005 numeric */ +#endif /* ** All command line parameters have the syntax "-fstring" ** or "-f string" (e.g. the space is optional). String may @@ -804,7 +966,6 @@ } #endif -#if !defined(CHROOTDIR) (void)setuid((uid_t)euid); # if defined(IRC_UID) && defined(IRC_GID) if ((int)getuid() == 0) @@ -817,7 +978,6 @@ (void)setuid(IRC_UID); } # endif -#endif /*CHROOTDIR/UID/GID*/ #if defined(USE_IAUTH) if ((bootopt & BOOT_NOIAUTH) == 0) @@ -862,8 +1022,8 @@ timeofday = time(NULL); #ifdef CACHED_MOTD motd = NULL; - read_motd(IRCDMOTD_PATH); #endif + read_motd(IRCDMOTD_PATH); inithashtables(); initlists(); initclass(); @@ -873,6 +1033,7 @@ timeofday = time(NULL); (void)init_sys(); logfiles_open(); + init_ssl(); #ifdef USE_SYSLOG openlog(mybasename(myargv[0]), LOG_PID|LOG_NDELAY, LOG_FACILITY); @@ -908,9 +1069,10 @@ if (!find_me()) exit(-1); } - + initialconf = 0; dbuf_init(); setup_me(&me); + rehash_ssl(); check_class(); ircd_writetune(tunefile); if (bootopt & BOOT_INETD) @@ -984,7 +1146,11 @@ ** active C lines, this call to Tryconnections is ** made once only; it will return 0. - avalon */ +#ifdef OPER_SET + if (iconf.aconnect && nextconnect && timeofday >= nextconnect) +#else if (nextconnect && timeofday >= nextconnect) +#endif nextconnect = try_connections(timeofday); /* ** Every once in a while, hunt channel structures that @@ -1066,6 +1232,19 @@ rehashed = 0; } +#ifdef DELAY_CLOSE + if (nextdelayclose && (timeofday >= nextdelayclose)) + { + nextdelayclose = delay_close(-1,NULL); + } +#endif + +#if defined(OPER_KLINE) || defined(LOCOP_KLINE) || \ + defined(OPER_TKLINE) || defined(LOCOP_TKLINE) + if (kline_added) + check_klines(); +#endif + if (dorestart) restart("Caught SIGINT"); if (dorehash) diff -ru --new-file irc2.10.3p3/ircd/ircd_ext.h irc2.10.3p3+sd7/ircd/ircd_ext.h --- irc2.10.3p3/ircd/ircd_ext.h Fri Feb 12 06:00:47 1999 +++ irc2.10.3p3+sd7/ircd/ircd_ext.h Mon Feb 3 14:31:07 2003 @@ -27,6 +27,7 @@ extern aClient me; extern aClient *client; extern istat_t istat; +extern iconf_t iconf; extern char **myargv; extern int rehashed; extern int portnum; @@ -41,6 +42,10 @@ extern time_t nextping; extern time_t nextdnscheck; extern time_t nextexpire; +extern int initialconf; +#ifdef DELAY_CLOSE +extern time_t nextdelayclose; +#endif #endif /* IRCD_C */ /* External definitions for global functions. @@ -59,4 +64,7 @@ EXTERN void server_reboot(); EXTERN void ircd_writetune __P((char *filename)); EXTERN void ircd_readtune __P((char *filename)); +#ifdef DELAY_CLOSE +EXTERN time_t delay_close __P((int fd,char *reason)); +#endif #undef EXTERN diff -ru --new-file irc2.10.3p3/ircd/list.c irc2.10.3p3+sd7/ircd/list.c --- irc2.10.3p3/ircd/list.c Mon May 7 00:36:55 2001 +++ irc2.10.3p3+sd7/ircd/list.c Mon Feb 3 14:31:07 2003 @@ -121,6 +121,10 @@ cptr->info = DefInfo; if (size == CLIENT_LOCAL_SIZE) { +#ifdef USE_SSL + cptr->ssl = NULL; + cptr->handshake = 0; +#endif cptr->since = cptr->lasttime = cptr->firsttime = timeofday; cptr->confs = NULL; cptr->sockhost[0] = '\0'; @@ -147,6 +151,13 @@ istat.is_auth -= 1; MyFree(cptr->auth); } + if (cptr->hopcount == 0) + { + if (cptr->reason) + MyFree(cptr->reason); + } + if (MyConnect(cptr)) + free_ssl(cptr); MyFree((char *)cptr); } @@ -190,6 +201,7 @@ if (!serv) { serv = (aServer *)MyMalloc(sizeof(aServer)); + memset(serv,0,sizeof(aServer)); #ifdef DEBUGMODE servs.inuse++; #endif @@ -201,8 +213,11 @@ serv->up = NULL; serv->refcnt = 1; serv->nexts = NULL; +#ifdef SERVER_MAP + serv->down = NULL; +#endif cptr->serv = serv; - + bzero((void *)serv->usercnt,3*sizeof(int)); for (sp = svrtop; sp; spp = sp, sp = sp->nexts) if (spp && ((spp->ltok) + 1 < sp->ltok)) break; @@ -309,6 +324,10 @@ cptr, cptr ? cptr->name : "", buf); #endif } + if (serv->up && serv->up != ME) + { + MyFree((char *)serv->up); + } MyFree((char *)serv); } } @@ -547,6 +566,12 @@ aconf->status = CONF_ILLEGAL; aconf->pref = -1; aconf->hold = time(NULL); +#ifdef SPOOF + aconf->spoof = NULL; +#endif +#ifdef USE_SSL + aconf->cert = NULL; +#endif Class(aconf) = NULL; return (aconf); } @@ -584,6 +609,14 @@ bzero(aconf->passwd, strlen(aconf->passwd)); if (aconf->ping) MyFree((char *)aconf->ping); +#ifdef SPOOF + if (aconf->spoof) + MyFree(aconf->spoof); +#endif +#ifdef USE_SSL + if (aconf->cert) + MyFree(aconf->cert); +#endif MyFree(aconf->passwd); MyFree(aconf->name); MyFree((char *)aconf); diff -ru --new-file irc2.10.3p3/ircd/s_auth.c irc2.10.3p3+sd7/ircd/s_auth.c --- irc2.10.3p3/ircd/s_auth.c Fri May 4 22:34:52 2001 +++ irc2.10.3p3+sd7/ircd/s_auth.c Mon Feb 3 14:31:07 2003 @@ -272,15 +272,15 @@ } iauth_stats = (aExtData *) MyMalloc(sizeof(aExtData)); - iauth_stats->line = MyMalloc(60); + iauth_stats->line = MyMalloc(80); sprintf(iauth_stats->line, "iauth modules statistics (%s)", myctime(timeofday)); iauth_stats->next = (aExtData *) MyMalloc(sizeof(aExtData)); - iauth_stats->next->line = MyMalloc(60); + iauth_stats->next->line = MyMalloc(80); sprintf(iauth_stats->next->line, - "spawned: %d, current options: %X (%.11s)", + "spawned: %d, current options: %X (%.20s)", iauth_spawn, iauth_options, (iauth_version) ? iauth_version : "???"); iauth_stats->next->next = NULL; @@ -440,6 +440,13 @@ ** yet: we don't even know if this is a server ** or a user connection! */ + int i; + char *reason; + reason = strchr(start,'#'); + if (reason) + { + cptr->reason = mystrdup(reason+1); + } if (start[0] == 'K') cptr->exitc = EXITC_AREF; else diff -ru --new-file irc2.10.3p3/ircd/s_bsd.c irc2.10.3p3+sd7/ircd/s_bsd.c --- irc2.10.3p3/ircd/s_bsd.c Sat Jun 30 23:18:55 2001 +++ irc2.10.3p3+sd7/ircd/s_bsd.c Mon Feb 3 14:31:07 2003 @@ -314,7 +314,6 @@ #endif if (inetport(cptr, aconf->host, aconf->name, aconf->port)) cptr->fd = -2; - if (cptr->fd >= 0) { cptr->confs = make_link(); @@ -328,7 +327,32 @@ free_client(cptr); return 0; } - +#ifdef DELAY_ACCEPT +void activate_delayed_listeners() +{ + aConfItem *aconf = NULL; + int pcnt = 0; + + for (aconf = conf; aconf; aconf = aconf->next) + { + if (!(aconf->status & CONF_LISTEN_PORT) + || (conf->status & CONF_ILLEGAL)) + { + continue; + } + if (!(aconf->status & CONF_ACTIVE)) + { + aconf->status |= CONF_ACTIVE; + pcnt++; + add_listener(aconf); + } + } + if (pcnt) + { + sendto_flag(SCH_NOTICE,"Activating delayed listening ports"); + } +} +#endif #ifdef UNIXPORT /* * unixport @@ -1055,7 +1079,40 @@ "Lost C-Line for %s", get_client_name(cptr,FALSE)); return -1; } - if (!BadPtr(aconf->passwd)) + if (!BadPtr(aconf->passwd)) { +#ifdef USE_SSL + /* shall we use ssl ? */ + if (UseSSL(Class(aconf)) == 1) { + int ret; + struct sockaddr tmp; + int tl = sizeof(tmp); + /* we need to do that, because of buggy openssl + which segfaults on dead socket ;-( */ + if (getpeername(cptr->fd, &tmp, &tl)) { + sendto_flag(SCH_ERROR, + "Failed ssl connection to %s: dead socket (connection refused ?)", + get_client_name(cptr, TRUE)); + return -1; + } + if (!aconf->cert) { + sendto_flag(SCH_NOTICE, + "Using default cert for %s", + get_client_name(cptr, TRUE)); + } + ret = ssl_server_connect(cptr, aconf->cert); + if (ret <= 0) { + sendto_flag(SCH_ERROR, + "Failed ssl connection to %s", + get_client_name(cptr, TRUE)); + return -1; + } + sendto_flag(SCH_NOTICE, + "Server ssl connection to %s established sucesfully", + get_client_name(cptr, TRUE)); + } else { + cptr->handshake = 1; + } +#endif #ifndef ZIP_LINKS sendto_one(cptr, "PASS %s %s IRC|%s %s", aconf->passwd, pass_version, serveropts, @@ -1066,6 +1123,7 @@ (bootopt & BOOT_STRICTPROT) ? "P" : "", (aconf->status == CONF_ZCONNECT_SERVER) ? "Z" : ""); #endif + } aconf = find_conf(cptr->confs, cptr->name, CONF_NOCONNECT_SERVER); if (!aconf) @@ -1146,6 +1204,7 @@ bcopy((char *)&cptr->ip, (char *)&sin.SIN_ADDR, sizeof(cptr->ip)); bcopy((char *)&cptr->ip, (char *)&acptr->ip, sizeof(cptr->ip)); +// acptr->handshake = 3; if (connect(acptr->fd, (SAP)&sin, sizeof(sin)) < 0 && errno != EINPROGRESS) { @@ -1154,7 +1213,8 @@ MyFree((char *)acptr); return -1; } - +// if (!errno) +// acptr->handshake = 0; acptr->status = STAT_RECONNECT; if (acptr->fd > highest_fd) highest_fd = acptr->fd; @@ -1297,8 +1357,21 @@ } del_fd(i, &fdall); local[i] = NULL; - (void)close(i); - +#ifdef DELAY_CLOSE + if (cptr->user && (cptr->user->flags & FLAGS_BADBOY)) + { + delay_close(i,cptr->buffer); + if (!nextdelayclose) + { + nextdelayclose = timeofday + DELAYCLOSETIME; + } + } + else +#endif + { + (void)close(i); + } + cptr->fd = -2; DBufClear(&cptr->sendQ); DBufClear(&cptr->recvQ); @@ -1465,6 +1538,47 @@ return; } +/* + * set_blocking - Set the client connection into non-blocking mode. + * If your system doesn't support this, you're screwed, ircd will run like + * crap. + * returns true (1) if successful, false (0) otherwise + */ +int set_blocking(int fd) +{ + /* + * NOTE: consult ALL your relevant manual pages *BEFORE* changing + * these ioctl's. There are quite a few variations on them, + * as can be seen by the PCS one. They are *NOT* all the same. + * Heed this well. - Avalon. + */ + /* This portion of code might also apply to NeXT. -LynX */ +#ifdef NBLOCK_SYSV + int res = 0; + + if (ioctl(fd, FIONBIO, &res) == -1) + return 0; + +#else /* !NBLOCK_SYSV */ + int nonb = 0; + int res; + +#ifdef NBLOCK_POSIX + nonb |= O_NONBLOCK; +#endif +#ifdef NBLOCK_BSD + nonb |= O_NDELAY; +#endif + + res = fcntl(fd, F_GETFL, 0); + if (!(res&nonb)) return 0; + if (-1 == res || fcntl(fd, F_SETFL, res ^ nonb) == -1) + return 0; +#endif /* !NBLOCK_SYSV */ + return 1; +} + + #ifdef CLONE_CHECK /* * check_clones @@ -1557,15 +1671,23 @@ report_error("Failed in connecting to %s :%s", cptr); add_con_refuse: + (void)close(fd); +add_con_delay_refuse: ircstp->is_ref++; acptr->fd = -2; free_client(acptr); - (void)close(fd); return NULL; } /* don't want to add "Failed in connecting to" here.. */ if (aconf && IsIllegal(aconf)) goto add_con_refuse; +#ifdef DELAY_ACCEPT + /* we are not accepting connections because of split */ + if (aconf && (aconf->status & CONF_DELAY) && (iconf.caccept < 2)) + { + goto add_con_refuse; + } +#endif /* Copy ascii address to 'sockhost' just in case. Then we * have something valid to put into error messages... */ @@ -1607,10 +1729,15 @@ (acptr->hostp) ? acptr->hostp->h_name : acptr->sockhost); del_queries((char *)acptr); +#ifdef DELAY_CLOSE + delay_close(fd,"ERROR :Too rapid connections from your host"); + goto add_con_delay_refuse; +#else (void)send(fd, "ERROR :Too rapid connections from your host\r\n", 46, 0); goto add_con_refuse; +#endif } #endif acptr->fd = fd; @@ -1843,8 +1970,12 @@ #ifdef INET6 length = recvfrom(cptr->fd, readbuf, sizeof(readbuf), 0, 0, 0); #else +#ifdef USE_SSL + length = safe_read(cptr, readbuf, sizeof(readbuf)); +#else length = recv(cptr->fd, readbuf, sizeof(readbuf), 0); #endif +#endif #if defined(DEBUGMODE) && defined(DEBUG_READ) if (length > 0) Debug((DEBUG_READ, @@ -1896,8 +2027,11 @@ if (length && dbuf_put(&cptr->recvQ, readbuf, length) < 0) return exit_client(cptr, cptr, &me, "dbuf_put fail"); - if (IsPerson(cptr) && - DBufLength(&cptr->recvQ) > CLIENT_FLOOD) + if (IsPerson(cptr) +#ifdef CAN_FLOOD + && !CanFlood(cptr) +#endif + && DBufLength(&cptr->recvQ) > CLIENT_FLOOD) { cptr->exitc = EXITC_FLOOD; return exit_client(cptr, cptr, &me, "Excess Flood"); @@ -2438,6 +2572,7 @@ (void)set_sock_opts(cptr->fd, cptr); (void)signal(SIGALRM, dummy); (void)alarm(4); +// cptr->handshake = 3; if (connect(cptr->fd, (SAP)svp, len) < 0 && errno != EINPROGRESS) { i = errno; /* other system calls may eat errno */ @@ -2455,6 +2590,8 @@ errno = ETIMEDOUT; return -1; } +// if (!errno) +// cptr->handshake = 0; (void)alarm(0); /* Attach config entries to client here rather than in diff -ru --new-file irc2.10.3p3/ircd/s_bsd_ext.h irc2.10.3p3+sd7/ircd/s_bsd_ext.h --- irc2.10.3p3/ircd/s_bsd_ext.h Fri Feb 5 01:50:21 1999 +++ irc2.10.3p3+sd7/ircd/s_bsd_ext.h Mon Feb 3 14:31:07 2003 @@ -54,6 +54,7 @@ EXTERN void close_connection __P((aClient *cptr)); EXTERN int get_sockerr __P((aClient *cptr)); EXTERN void set_non_blocking __P((int fd, aClient *cptr)); +EXTERN int set_blocking __P((int fd)); EXTERN aClient *add_connection __P((aClient *cptr, int fd)); EXTERN int read_message __P((time_t delay, FdAry *fdp, int ro)); EXTERN int connect_server __P((aConfItem *aconf, aClient *by, @@ -61,6 +62,9 @@ EXTERN void get_my_name __P((aClient *cptr, char *name, int len)); EXTERN int setup_ping __P((aConfItem *aconf)); EXTERN void send_ping __P((aConfItem *aconf)); +#ifdef DELAY_ACCEPT +EXTERN void activate_delayed_listeners(); +#endif #if defined(ENABLE_SUMMON) || defined(ENABLE_USERS) EXTERN int utmp_open(); EXTERN int utmp_read __P((int fd, char *name, char *line, char *host, diff -ru --new-file irc2.10.3p3/ircd/s_conf.c irc2.10.3p3+sd7/ircd/s_conf.c --- irc2.10.3p3/ircd/s_conf.c Fri Jul 6 01:08:58 2001 +++ irc2.10.3p3+sd7/ircd/s_conf.c Mon Feb 3 14:31:07 2003 @@ -51,6 +51,7 @@ static char rcsid[] = "@(#)$Id: s_conf.c,v 1.42.2.15 2001/07/05 22:08:58 chopin Exp $"; #endif +#include #include "os.h" #include "s_defines.h" #define S_CONF_C @@ -63,6 +64,21 @@ aConfItem *conf = NULL; aConfItem *kconf = NULL; +#ifdef RECOVER +extern char * ltoid(unsigned); +extern char md5me[RECOVER_SMDLEN]; +void md_server_name(char *buf, char *a, char *b) +{ + char mdbuf[16]; + MD5_CTX md5; + MD5_Init(&md5); + if (a) MD5_Update(&md5, a, strlen(a)); + if (b) MD5_Update(&md5, b, strlen(b)); + MD5_Final(mdbuf, &md5); + memcpy(buf, ltoid(*((time_t *) mdbuf)), RECOVER_SMDLEN); +} +#endif + /* * remove all conf entries from the client except those which match * the status field mask. @@ -161,6 +177,38 @@ return -1; } +#ifdef SPOOF +/* this replaces '%'-s in spoofed hostnames by md5 bytes of real host|ip */ +static void do_spoof(char *host, char *spoof) +{ + char mdbuf[16]; + int mdp[32], i; + + if ((!spoof) || (!*spoof)) + return; + + MD5(host, strlen(host), mdbuf); + for (i = 0; i < 32; i++) { + if (!(i&1)) { + mdp[i] = (mdbuf[i >> 1] >> 4) & 0xf; + } else { + mdp[i] = mdbuf[i >> 1] & 0xf; + } + } + + i = 0; + do { + if (*spoof == '%') { + *host++ = 'a' + mdp[i % 32]; + i++; + } else { + *host++ = *spoof; + } + } while (*spoof++); + *host = 0; +} +#endif + /* * find the first (best) I line to attach. */ @@ -177,9 +225,13 @@ for (aconf = conf; aconf; aconf = aconf->next) { - if ((aconf->status != CONF_CLIENT) && - (aconf->status != CONF_RCLIENT)) + Debug((DEBUG_DNS, "ya %s %s", aconf->name, aconf->host)); + if (IsIllegal(aconf)) continue; + + if (!(aconf->status & (CONF_CLIENT | CONF_RCLIENT))) + continue; + Debug((DEBUG_DNS, "client => name = %s host = %s", aconf->name, aconf->host)); if (aconf->port && aconf->port != cptr->acpt->port) continue; if (!aconf->host || !aconf->name) @@ -229,9 +281,46 @@ attach_iline: if (aconf->status & CONF_RCLIENT) SetRestricted(cptr); +#ifdef ILINE_FLAGS + if (aconf->status & CONF_EXEMPT) + { + cptr->user->flags |= FLAGS_EXEMPT; + } + if (aconf->status & CONF_FLOOD) + { + cptr->user->flags |= FLAGS_FLOOD; + } + if (!hp && (aconf->status & CONF_RNODNS)) + { + SetRestricted(cptr); + } + if (aconf->status & CONF_DOT) + { + cptr->user->flags |= FLAGS_DOT; + } +#ifdef RECOVER + if (aconf->status & CONF_IMMORTAL) + { + cptr->user->flags |= FLAGS_IMMORTAL; + } +#endif +#endif get_sockhost(cptr, uhost); if ((i = attach_conf(cptr, aconf)) < -1) find_bounce(cptr, ConfClass(aconf), -1); + +#ifdef USE_SSL + cptr->forcessl = UseSSL(Class(aconf)); +#endif + +#ifdef SPOOF + do_spoof(cptr->sockhost, aconf->spoof); + if ((aconf->spoof) && (*aconf->spoof)) +#if defined(OPERS_WATCHING_USERS) + cptr->real_ip = cptr->ip; +#endif + inetaton("1.3.3.7", &cptr->ip); +#endif return i; } find_bounce(cptr, 0, -2); @@ -271,6 +360,7 @@ aConfItem *aconf; { Reg Link **lp, *tmp; + aConfItem **aconf2,*aconf3; lp = &(cptr->confs); @@ -291,7 +381,23 @@ } } if (aconf && !--aconf->clients && IsIllegal(aconf)) - free_conf(aconf); + { + /* Remove the conf entry from the Conf linked list */ + for (aconf2 = &conf; (aconf3 = *aconf2); ) + { + if (aconf3 == aconf) + { + *aconf2 = aconf3->next; + aconf3->next = NULL; + free_conf(aconf); + + } + else + { + aconf2 = &aconf3->next; + } + } + } tmp = *lp; *lp = tmp->next; free_link(tmp); @@ -329,7 +435,7 @@ aClient *cptr; { Reg Link *lp; - + if (is_attached(aconf, cptr)) return 1; if (IsIllegal(aconf)) @@ -342,9 +448,10 @@ return -3; /* Use this for printing error message */ } if ((aconf->status & (CONF_CLIENT | CONF_RCLIENT))) - { + { int hcnt = 0, ucnt = 0; - + int ghcnt = 0, gucnt = 0; + Reg anUser *user = NULL; /* check on local/global limits per host and per user@host */ /* @@ -352,7 +459,64 @@ ** host check is done on the IP address. ** user check is done on the IDENT reply. */ - if (ConfMaxHLocal(aconf) > 0 || ConfMaxUHLocal(aconf) > 0) { + if (ConfMaxHLocal(aconf) > 0 || ConfMaxUHLocal(aconf) > 0 || + ConfMaxHGlobal(aconf) > 0 || ConfMaxUHGlobal(aconf) > 0 ) + { + for ((user = hash_find_hostname(cptr->sockhost,NULL));user;user=user->hnext) + { + if (!mycmp(cptr->sockhost,user->host)) + { + ghcnt++; + if (MyConnect(user->bcptr)) + { + hcnt++; + if (!mycmp(user->bcptr->auth,cptr->auth)) + { + ucnt++; + gucnt++; + } + } + else + { + if (!mycmp(user->username,cptr->user->username)) + { + gucnt++; + } + } + if (ConfMaxUHLocal(aconf) > 0 && + ucnt >= ConfMaxUHLocal(aconf)) + { + return -5; + } + + if (ConfMaxHLocal(aconf) > 0 && + hcnt >= ConfMaxHLocal(aconf)) + { + return -4; + } + if (ConfMaxUHGlobal(aconf) > 0 && + gucnt >= ConfMaxUHGlobal(aconf)) + { + return -7; + } + if (ConfMaxHGlobal(aconf) > 0 && + ghcnt >= ConfMaxHGlobal(aconf)) + { + return -6; + } + } + } + } +#ifndef NO_EXTENSIVE_LOCAL_LIMIT_CHECK + /* Part of old cpu intensive code which is checking user's + * ip against all all other local clients. Needed only when + * client changes it's hostname between connects. + * Won't be needed on pure 2.11 net -- jv + */ + + /* now, check local IP too */ + if (ConfMaxHLocal(aconf) > 0 || ConfMaxUHLocal(aconf) > 0) + { Reg aClient *acptr; Reg int i; @@ -374,38 +538,8 @@ ucnt >= ConfMaxUHLocal(aconf)) return -5; /* for error message */ } - /* - ** Global limits - ** host check is done on the hostname (IP if unresolved) - ** user check is done on username - */ - if (ConfMaxHGlobal(aconf) > 0 || ConfMaxUHGlobal(aconf) > 0) - { - Reg aClient *acptr; - Reg int ghcnt = hcnt, gucnt = ucnt; - - for (acptr = client; acptr; acptr = acptr->next) - { - if (!IsPerson(acptr)) - continue; - if (MyConnect(acptr) && - (ConfMaxHLocal(aconf) > 0 || - ConfMaxUHLocal(aconf) > 0)) - continue; - if (!strcmp(cptr->sockhost, acptr->user->host)) - { - if (ConfMaxHGlobal(aconf) > 0 && - ++ghcnt >= ConfMaxHGlobal(aconf)) - return -6; - if (ConfMaxUHGlobal(aconf) > 0 && - !strcmp(cptr->user->username, - acptr->user->username) && - (++gucnt >=ConfMaxUHGlobal(aconf))) - return -7; - } - } - } - } +#endif + } lp = make_link(); istat.is_conflink++; @@ -570,7 +704,6 @@ #endif ); - for (tmp = conf; tmp; tmp = tmp->next) { if (!(tmp->status & (CONF_OPS)) || !tmp->name || !tmp->host || @@ -582,14 +715,37 @@ */ if (match(tmp->host, userhost) && match(tmp->host, userip) && (!strchr(tmp->host, '/') - || match_ipmask(tmp->host, cptr))) + || match_ipmask(tmp->host, cptr))) { continue; - if (tmp->clients < MaxLinks(Class(tmp))) + } + if (tmp->clients < MaxLinks(Class(tmp))) { return tmp; + } } return NULL; } +aConfItem *get_ssl_line(void) +{ + Reg aConfItem *tmp; + char *p; + + for (tmp = conf; tmp; tmp = tmp->next) { + if (tmp->status & CONF_SSL) { + if (tmp->host) { + for (p = tmp->host; *p; p++) + if (*p == '^') *p = ':'; + } + if (tmp->passwd) { + for (p = tmp->passwd; *p; p++) + if (*p == '^') *p = ':'; + } + return tmp; + } + } + return NULL; +} + aConfItem *find_conf_name(name, statmask) char *name; @@ -713,12 +869,20 @@ if (!BadPtr(bconf->host) && mycmp(bconf->host, aconf->host)) continue; +#ifdef DELAY_ACCEPT + /* ignore ->passwd field */ + if (!(aconf->status & CONF_LISTEN_PORT)) + { +#endif if ((BadPtr(bconf->passwd) && !BadPtr(aconf->passwd)) || (BadPtr(aconf->passwd) && !BadPtr(bconf->passwd))) continue; if (!BadPtr(bconf->passwd) && mycmp(bconf->passwd, aconf->passwd)) continue; +#ifdef DELAY_ACCEPT + } +#endif if ((BadPtr(bconf->name) && !BadPtr(aconf->name)) || (BadPtr(aconf->name) && !BadPtr(bconf->name))) @@ -730,8 +894,7 @@ return bconf; } -/* - * rehash +/* rehash * * Actual REHASH service routine. Called with sig == 0 if it has been called * as a result of an operator issuing this command, else assume it has been @@ -831,18 +994,18 @@ * flush out deleted I and P lines although still in use. */ for (tmp = &conf; (tmp2 = *tmp); ) - if (!(tmp2->status & CONF_ILLEGAL)) + if (!(tmp2->status & CONF_ILLEGAL) || tmp2->clients) tmp = &tmp2->next; else { *tmp = tmp2->next; tmp2->next = NULL; - if (!tmp2->clients) - free_conf(tmp2); + free_conf(tmp2); } #ifdef CACHED_MOTD read_motd(IRCDMOTD_PATH); #endif + rehash_ssl(); rehashed = 1; return ret; } @@ -974,7 +1137,7 @@ {'\\', '\\'}, { 0, 0}}; Reg char *tmp, *s; int fd, i; - char line[512], c[80], *tmp2 = NULL, *tmp3 = NULL, *tmp4 = NULL; + char line[512], c[80], *tmp2 = NULL, *tmp3 = NULL, *tmp4 = NULL, *tmp5 = NULL; int ccount = 0, ncount = 0; aConfItem *aconf = NULL; @@ -1040,7 +1203,7 @@ if (tmp2) MyFree(tmp2); - tmp3 = tmp4 = NULL; + tmp3 = tmp4 = tmp5 = NULL; tmp = getfield(line); if (!tmp) continue; @@ -1141,6 +1304,10 @@ case 'y': aconf->status = CONF_CLASS; break; + case 'X': + case 'x': + aconf->status = CONF_SSL; + break; default: Debug((DEBUG_ERROR, "Error in config file: %s", line)); break; @@ -1173,7 +1340,50 @@ DupString(aconf->passwd, tmp); if ((tmp = getfield(NULL)) == NULL) break; - DupString(aconf->name, tmp); +#ifdef ILINE_FLAGS + if (aconf->status & (CONF_CLIENT | CONF_RCLIENT)) + { + /* parse i-line flags using more + sophisticated (and more obfuscated) + way -sd */ + static unsigned int conf_tab[] = + { CONF_EXEMPT, CONF_RNODNS +#ifdef CAN_FLOOD + , CONF_FLOOD +#endif +#ifdef USE_SSL + , CONF_DOT +#endif +#ifdef RECOVER + , CONF_IMMORTAL +#endif + }; + + static char *p, char_tab[] = "<+" +#ifdef CAN_FLOOD + "|" +#endif +#ifdef USE_SSL + "." +#endif +#ifdef RECOVER + "^" +#endif + ; + while (*tmp && (p = index(char_tab, *tmp))) { + aconf->status |= conf_tab[p-char_tab]; + Debug((DEBUG_DNS, "Parsing I-flag '%c'", *tmp)); + tmp++; + + } + Debug((DEBUG_DNS, "Rest of I-Line = %s\n", tmp)); + DupString(aconf->name, tmp); + } + else +#endif + { + DupString(aconf->name, tmp); + } if ((tmp = getfield(NULL)) == NULL) break; aconf->port = 0; @@ -1190,7 +1400,11 @@ /* the following are only used for Y: */ if ((tmp3 = getfield(NULL)) == NULL) break; - tmp4 = getfield(NULL); + if ((tmp4 = getfield(NULL)) == NULL) + break; +#ifdef USE_SSL + tmp5 = getfield(NULL); +#endif break; } istat.is_confmem += aconf->host ? strlen(aconf->host)+1 : 0; @@ -1218,7 +1432,11 @@ atoi(index(tmp3, '.') + 1) : 1, tmp4 ? atoi(tmp4) : 1, (tmp4 && index(tmp4, '.')) ? - atoi(index(tmp4, '.') + 1) : 1); + atoi(index(tmp4, '.') + 1) : 1 +#ifdef USE_SSL + ,tmp5 ? atoi(tmp5) : 0 +#endif + ); continue; } /* @@ -1232,26 +1450,95 @@ if (MaxLinks(Class(aconf)) < 0) Class(aconf) = find_class(0); } - if (aconf->status & (CONF_LISTEN_PORT|CONF_CLIENT)) +#ifdef DELAY_ACCEPT + if (aconf->status & (CONF_LISTEN_PORT)) + { + if (aconf->passwd && strchr(aconf->passwd,'D')) + { + aconf->status |= CONF_DELAY; + } + if (aconf->passwd && strchr(aconf->passwd,'S')) + { + aconf->status |= CONF_SERVERONLY; + /* feature, remove delay if serveronly */ + aconf->status &= ~CONF_DELAY; + } + } +#endif + + if (aconf->status & (CONF_LISTEN_PORT|CONF_CLIENT|CONF_RCLIENT)) { - aConfItem *bconf; + aConfItem *bconf = NULL; if ((bconf = find_conf_entry(aconf, aconf->status))) { delist_conf(bconf); bconf->status &= ~CONF_ILLEGAL; - if (aconf->status == CONF_CLIENT) - { + if (aconf->status & (CONF_CLIENT | CONF_RCLIENT)) { +#ifdef ILINE_FLAGS + /* a bit of bitmagic, *ahem* -sd */ + bconf->status &= ~CONF_ILINE_FLAGS; + bconf->status |= aconf->status & CONF_ILINE_FLAGS; +#endif bconf->class->links -= bconf->clients; bconf->class = aconf->class; bconf->class->links += bconf->clients; } +#ifdef DELAY_ACCEPT + if (aconf->status & CONF_LISTEN_PORT) + { + if (aconf->status & CONF_DELAY) + { + bconf->status &= ~CONF_SERVERONLY; + bconf->status |= CONF_DELAY; + } + else + { + bconf->status &= ~CONF_DELAY; + } + if (aconf->status & CONF_SERVERONLY) + { + bconf->status &= ~CONF_DELAY; + bconf->status |= CONF_SERVERONLY; + } + else + { + bconf->status &= ~CONF_SERVERONLY; + } + } +#endif + free_conf(aconf); aconf = bconf; } - else if (aconf->host && - aconf->status == CONF_LISTEN_PORT) - (void)add_listener(aconf); + + if (aconf->host && + aconf->status & CONF_LISTEN_PORT) + { +#ifdef DELAY_ACCEPT + if (aconf->status & CONF_DELAY) + { + /* we have Delayed ports and we + * are starting, don't bind them. + */ + if (initialconf) + iconf.caccept = 1; + } + if (!((iconf.caccept < 2) && + (aconf->status & CONF_DELAY))) + { + aconf->status |= CONF_ACTIVE; + } + + if (aconf->status & CONF_ACTIVE) +#endif + { + if (!bconf) + { + add_listener(aconf); + } + } + } } if (aconf->status & CONF_SERVICE) aconf->port &= SERVICE_MASK_ALL; @@ -1296,7 +1583,13 @@ MyFree(tmp2); tmp2 = NULL; } - +#ifdef USE_SSL + if (tmp3) { + DupString(aconf->cert, tmp3); + MyFree(tmp3); + tmp3 = NULL; + } +#endif } /* ** Name cannot be changed after the startup. @@ -1312,12 +1605,29 @@ MyFree(me.info); me.info = MyMalloc(REALLEN+1); strncpyzt(me.info, aconf->name, REALLEN+1); +#ifdef NAMECHANGE_HACK + /* you must be very careful when you're going + to change this. at least squit all servers + before changeing. -sd */ if (ME[0] == '\0' && aconf->host[0]) +#endif + { strncpyzt(ME, aconf->host, sizeof(ME)); + } +#ifdef RECOVER + md_server_name(md5me, me.name, me.info); + sendto_flag(SCH_NOTICE, "md5me = '%3s'", md5me); +#endif if (aconf->port) setup_ping(aconf); } +#ifdef SPOOF + if ((tmp3) && (aconf->status & (CONF_CLIENT|CONF_RCLIENT))) { + DupString(aconf->spoof, tmp3); + } +#endif + (void)collapse(aconf->host); (void)collapse(aconf->name); Debug((DEBUG_NOTICE, diff -ru --new-file irc2.10.3p3/ircd/s_conf_ext.h irc2.10.3p3+sd7/ircd/s_conf_ext.h --- irc2.10.3p3/irc