From 7b88c81ef2d03e0db25f86c520cfa4d9bcc75a21 Mon Sep 17 00:00:00 2001 From: stskeeps Date: Fri, 17 Jan 2003 22:07:01 +0000 Subject: [PATCH] beta14 --- .RELEASE.NOTES | 6 +- Changes | 62 +++++ Makefile.in | 4 +- Unreal.nfo | 11 +- doc/unreal32docs.html | 57 +---- help.conf | 1 + include/channel.h | 2 +- include/config.h | 10 +- include/dynconf.h | 2 + include/h.h | 9 + include/hash.h | 9 + include/struct.h | 33 ++- include/version.h | 2 +- makefile.win32 | 5 +- src/Makefile | 9 +- src/auth.c | 3 +- src/badwords.c | 34 +-- src/channel.c | 10 +- src/hash.c | 94 ++++++++ src/ircd.c | 4 + src/match.c | 13 +- src/modules/l_commands.c | 8 +- src/modules/m_htm.c | 130 ++++++++++- src/modules/m_mkpasswd.c | 3 - src/modules/m_oper.c | 8 +- src/modules/m_tkl.c | 5 +- src/modules/m_tsctl.c | 8 +- src/modules/scan.c | 15 +- src/random.c | 172 ++++++++++++++ src/res.c | 30 +-- src/s_bsd.c | 24 +- src/s_conf.c | 476 ++++++++++++++++++++++++++++----------- src/s_extra.c | 2 +- src/s_kline.c | 2 +- src/s_serv.c | 36 +-- src/s_user.c | 108 ++++++++- src/win32/unrealinst.iss | 2 +- 37 files changed, 1103 insertions(+), 306 deletions(-) create mode 100644 src/random.c diff --git a/.RELEASE.NOTES b/.RELEASE.NOTES index 5c7adec18..c1b2f7182 100644 --- a/.RELEASE.NOTES +++ b/.RELEASE.NOTES @@ -1,5 +1,5 @@ -Unreal3.2-beta13 Release Notes +Unreal3.2-beta14 Release Notes ====================================== I M P O R T A N T R E A D I N G @@ -226,5 +226,9 @@ Unreal3.2-beta13 Release Notes * UNKLINE and UNZLINE have been removed in favor of a system like G:lines, to remove you now /kline -user@host or /zline -user@host +* We now support ranges in listen blocks, for example listen *:6660-6669; + +* If you want throttling protection, read include/config.h + * MAKE SURE YOU RERUN ./Config AND RUN make clean BEFORE USING THIS VERSION!!! diff --git a/Changes b/Changes index d7d147a3e..014f0391c 100644 --- a/Changes +++ b/Changes @@ -1719,3 +1719,65 @@ seen. gmtime warning still there - Changed base version name to Unreal3.2, instead of Unreal3.2-Selene - Made McSkaf part of core coder team *** beta13 released *** +- Added set::htm to set HTM options via the config. set::htm is only valid if either + commands.so or m_htm.so is loaded. +- Recoded some of +G to work MUCH faster. A compiled copy of the regex is now stored + in memory rather than compiling the regex each time the swear stripping was trigged. + This uses slightly more memory, but saves a signifigant amount of execution time. + Idea inspired by a suggestion from CaliMonk +- Fixed a bug where makeconf was still included in make install +- Fixed a bug reported by |Zerwas| where tsctl required all lowercase params (#0000537) +- Fixed a bug reported by |Zerwas| where forgetting to have an oper::flags would cause a + crash (#0000543) +- Added a max of 500:500 to +f (higher than this is just stupid), this fixes + (#0000542) reported by BiGi +- Fixed a bug where included files were not added to the file list in the Config menu under + win32. Reported by PoisonDart316 (#0000535) +- Added chmode +u to help.conf, reported by Jaw959 (#0000544) +- Fixed a docs typo 'channes' instead of 'channels' and a typo that said +I is limited to + netadmins, reported by PoisonDart316 (#0000547), also removed /unkline and /unzline from + the docs (replaced with /kline - and /zline -, also reported by PoisonDart316 (#0000548) +- Fixed bug with INET6 and find_tkline_zap (..) +- Fixed include bug +- Created StripControlCodes() and call it from stripbadwords() to fix bug 552 +- Made 3 param TKL funcs Perm with reason instead of timed with no reason +- Added set::snomask-on-oper to set the default snomask when users /oper (oper::snomask + overrides this) +- Fixed a bug reported by AngryWolf where setting umode -o didn't remove umode + h. (#0000556) +- Added a pretty_time_val function, this converts a number such as 86400 to "1 day" + to make it easier to read. +- Fixed a bug in the binary search functions that could cause crashes when unknown config + directives were added. Reported by 1of10 (#0000587) +- Fixed a bug at synch time that could cause more parameters to be sent than should be +- Fixed a TKL bug where leaving out the reason caused a crash (reported by Ravage) +- Added the ability to specify port ranges, for example listen *:6660-6669; listens + on ports 6660, 6661, ... 6669. Suggested by Krisztian Romek +- Removed USE_LONGMODE, if it was #undef'ed problems could occur, so there is no reason to + have it if it doesn't to anything. +- Fixed a bug where leaving out a value for certain config directives would cause a crash, + reported by AngryWolf (#0000596) +- Fixed whole bunch of users in empty channel bug (probably) +- Added a patch by Syzop to increase the "randomness" of well... the random numbers +- Fixed a bug in the empty channel fix +- Fixed a bug in the random patch under win32 +- Added a suggestion by AngryWolf to generate an error if a link::password-connect + is specified as encrypted. (#0000597) +- Fixed bug #0000601 reported by cate where specifying just a :port number for set::scan::endpoint + caused a seg fault. +- Added some patches by Syzop to fix a variety of different bugs +- Added some bugfixes for IPv6 and others by Syzop +- Fixed a bug where leaving out the parameter to a password config entry would cause a + crash, reported by AngryWolf (#0000623) +- Adding throttling, read config.h for more info. For the uneducated, + throttling is to reconnect way too fast repeatedly. Thanks to [Real] for + the idea +- Fixed bug #000613 reported by AngryWolf where we were writing a null to the log file when + we reached max size. +- Fixed a bug where helpop would pass on a null pointer +- One more fix to the above +- Patch by Syzop to fix a bug in the resolver +- Preperations for beta14. Will be a recommended upgrade +- Compile fixes regarding throttling +- Fix when you use another make than make +** beta14 released ** diff --git a/Makefile.in b/Makefile.in index 8a9f75bb7..60cb9295f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -180,7 +180,7 @@ cleandir: clean makex: chmod +x Config newnet ircd ircdcron/ircdchk killircd - chmod +x makeconf rehash ircdreg + chmod +x rehash ircdreg fromdos: cleandir $(FROMDOS) -dv * @@ -218,7 +218,7 @@ install: all $(TOUCH) $(IRCDDIR)/unrealircd.conf chmod 0600 $(IRCDDIR)/unrealircd.conf $(INSTALL) -m 0600 badwords.*.conf help.conf LICENSE Donation $(IRCDDIR) - $(INSTALL) -m 0700 bugreport makeconf unreal $(IRCDDIR) + $(INSTALL) -m 0700 bugreport unreal $(IRCDDIR) $(INSTALL) -m 0700 -d $(IRCDDIR)/modules $(INSTALL) -m 0700 src/modules/*.so $(IRCDDIR)/modules diff --git a/Unreal.nfo b/Unreal.nfo index 4da05b67e..e5526b422 100644 --- a/Unreal.nfo +++ b/Unreal.nfo @@ -1,5 +1,5 @@ =============================================== -= UnrealIRCd v3.2 (beta13) = += UnrealIRCd v3.2 (beta14) = =============================================== Was brought to you by: @@ -7,20 +7,19 @@ ============== * Stskeeps * codemastr - * Griever * Luke - * nighthawk * McSkaf + * Syzop - Coders team: + Contributors ============ * Zogg * NiQuiL * assyrian - - In former versions: + * nighthawk * DrBin * llthangel + * Griever Documentation: ============== diff --git a/doc/unreal32docs.html b/doc/unreal32docs.html index 94a22102e..3ed84bc3b 100644 --- a/doc/unreal32docs.html +++ b/doc/unreal32docs.html @@ -627,7 +627,7 @@
B
can_unkline
- Can use /unkline + Can use /kline -u@h
t
@@ -1738,8 +1738,7 @@
I
- Invisible Join/Part's. Makes you hidden in channes (For Network Admins - only, and MUST be enabled) (Set In Oper Block) + Invisible Join/Part's. Makes you hidden in channels (requires the can_stealth/I flag, and +I must also be enabled on the particular server.) (Set In Oper Block)
t
@@ -2045,72 +2044,40 @@ IRCop - kline <hostmask> <reason> + kline +-<hostmask> <time to ban> <reason> Bans the hostmask from the server it is issued on. It is not a global - ban. + ban. Time to ban is in seconds, or you can use 1d for 1 days. If the hostmask is prefixed with a -, the kline is removed IRCop - unkline <hostmask> - Removes a kline + zline +-<ip> <time to ban> <reason> + Bans an IP Address from the local server it is issued on. Time to ban is in seconds, or you can use 1d for 1 days. If the ip is prefixed with a - then the zline is removed.
IRCop - zline <ip> :<reason> - Bans an IP Address from the local server it is issued on
- IRCop - - - unzline <ip> - Removes a zline - IRCop - - - gline <user@host> <time to ban> :<reason>
+ gline +-<user@host> <time to ban> :<reason>
Adds a global ban to anyone that matches. Time to ban is in seconds, or - u can use 1d for 1 days. To remove a gline, put a –user@host
+ you can use 1d for 1 days. To remove a gline, put a –user@host
IRCop shun +-<user@host> <time to shun> :<reason>
Prevents a user from executing ANY commands on the server, and prevents - them from speaking. Time to ban is in seconds, or u can use 1d for 1 days. + them from speaking. Time to shun is in seconds, or you can use 1d for 1 days. To remove a shun, put a –user@host. Setting time to 0 makes it permanent.
IRCop - gzline <ip> <time to ban> :<reason>
- Adds a global zline. Time to ban is in seconds, or u can use 1d for 1 + gzline +-<ip> <time to ban> :<reason>
+ Adds a global zline. Time to ban is in seconds, or you can use 1d for 1 days. To remove a gzline, put a –user@host. Setting time to 0 makes it permanent.
IRCop - - tkline <user@host> <time to ban> :<reason>
- Timed Kline. . Time to ban is in seconds, or u can use 1d for 1 days. - To remove a tkline, put a –user@host. Setting time to 0 makes it permanent.
- IRCop - - - tzline <ip> <time to ban> :<reason>
- Timed Zline. . Time to ban is in seconds, or u can use 1d for 1 days. - To remove a tzline, put a –user@host. Setting time to 0 makes it permanent - IRCop - - - akill <user@host> :<reason>
- Adds an akill (Services Admins & Network Admins ONLY)
- IRCop - - - rakill <user@host>
- Removes an akill
- IRCop - rehash <server> –<flags> - Rehashes the servers config file. Incluidng a server name allows you to + Rehashes the servers config file. Including a server name allows you to rehash a remote servers config file. Several flags are also available. They Include
-dccdeny - Rehashes dccdeny.conf
diff --git a/help.conf b/help.conf index fa50d3d72..af9b48d31 100644 --- a/help.conf +++ b/help.conf @@ -168,6 +168,7 @@ help Chmodes { " R = Only registered (+r) users may join the channel"; " S = Strips mIRC color codes"; " V = /INVITE is not allowed"; + " u = Auditorium mode /names and /who #channel only show channel ops"; " ==------------------------------oOo----------------------------=="; }; diff --git a/include/channel.h b/include/channel.h index c2bbf1eaa..17427c87b 100644 --- a/include/channel.h +++ b/include/channel.h @@ -37,7 +37,7 @@ * before Dreamforge aren't safe with more than six. -Donwulff */ #include "msg.h" -#define MAXMODEPARAMS (MAXPARA-2) /* Maximum modes processed */ +#define MAXMODEPARAMS (MAXPARA-3) /* Maximum modes processed */ #define RESYNCMODES 12 /* Max modes per MODE in resync */ #define MODEPARAMS 6 /* Max modes from user */ diff --git a/include/config.h b/include/config.h index c5e24853e..a653ba99a 100644 --- a/include/config.h +++ b/include/config.h @@ -135,6 +135,14 @@ */ #undef OPEROVERRIDE_VERIFY +/* + * THROTTLING + * This will only allow 1 connection per ip in THROTTLING_PERIOD time + * this will be adaptable using conf later +*/ +#undef THROTTLING +#define THROTTLING_PERIOD 15 + /* * NAZIISH_CHBAN_HANDLING (formerly ANNOYING_BAN_THING) * Reject bans that are matched by existing bans, causes chanserv @@ -638,8 +646,6 @@ error You stuffed up config.h signals #ifdef _WIN32 # undef FORCE_CORE #endif -/* use cflag longmodes */ -#define USE_LONGMODE #ifdef NEED_BCMP #define bcmp memcmp #endif diff --git a/include/dynconf.h b/include/dynconf.h index af341c138..95bd53892 100644 --- a/include/dynconf.h +++ b/include/dynconf.h @@ -66,6 +66,7 @@ struct zConfiguration { char *kline_address; long conn_modes; long oper_modes; + char *oper_snomask; char *auto_join_chans; char *oper_auto_join_chans; char *oper_only_stats; @@ -89,6 +90,7 @@ extern aConfiguration iConf; #define KLINE_ADDRESS iConf.kline_address #define CONN_MODES iConf.conn_modes #define OPER_MODES iConf.oper_modes +#define OPER_SNOMASK iConf.oper_snomask #define SHOWOPERMOTD iConf.som #define HIDE_ULINES iConf.hide_ulines #define ALLOW_CHATOPS iConf.allow_chatops diff --git a/include/h.h b/include/h.h index faabf39b7..af07382d4 100644 --- a/include/h.h +++ b/include/h.h @@ -100,6 +100,10 @@ extern int completed_connection(aClient *); extern void clear_unknown(); extern EVENT(tkl_check_expire); extern EVENT(e_unload_module_delayed); +#ifdef THROTTLING +extern EVENT(e_clean_out_throttling_buckets); +#endif + extern void module_loadall(int module_load); extern long set_usermode(char *umode); extern char *get_modestr(long umodes); @@ -307,6 +311,7 @@ extern int check_for_target_limit(aClient *sptr, void *target, const char *name extern char *stripbadwords_message(char *str); extern char *stripbadwords_channel(char *str); extern unsigned char *StripColors(unsigned char *); +extern const char *StripControlCodes(unsigned char *text); extern char *canonize(char *buffer); extern int webtv_parse(aClient *sptr, char *string); extern ConfigItem_deny_dcc *dcc_isforbidden(aClient *cptr, aClient *sptr, aClient *target, char *filename); @@ -324,6 +329,7 @@ extern int parse(aClient *, char *, char *); extern int do_numeric(int, aClient *, aClient *, int, char **); extern int hunt_server(aClient *, aClient *, char *, int, int, char **); extern int hunt_server_token(aClient *, aClient *, char *, char *, char *, int, int, char **); +extern int hunt_server_token_quiet(aClient *, aClient *, char *, char *, char *, int, int, char **); extern aClient *next_client(aClient *, char *); extern int m_umode(aClient *, aClient *, int, char **); extern int m_names(aClient *, aClient *, int, char **); @@ -524,6 +530,7 @@ extern u_long cres_mem(aClient *sptr, char *nick); extern void flag_add(char *ch); extern void flag_del(char ch); extern void init_dynconf(void); +extern char *pretty_time_val(long); extern int init_conf(char *filename, int rehash); extern void validate_configuration(void); extern void run_configuration(void); @@ -543,5 +550,7 @@ char *ssl_get_cipher(SSL *ssl); #endif long config_checkval(char *value, unsigned short flags); void config_status(char *format, ...); +void init_random(); +u_int32_t getrandom32(); #define EVENT_DRUGS BASE_VERSION diff --git a/include/hash.h b/include/hash.h index fdb8451de..997aa1a68 100644 --- a/include/hash.h +++ b/include/hash.h @@ -60,7 +60,16 @@ typedef struct hashentry { #define WATCHHASHSIZE 10007 /* prime number */ +/* + * Throttling +*/ +#ifdef THROTTLING +#define THROTTLING_HASH_SIZE 1024 +#endif + + #define NullChn ((aChannel *)0) #define find_channel hash_find_channel + #endif /* __hash_include__ */ diff --git a/include/struct.h b/include/struct.h index 439bc9e28..0b09d4fd2 100644 --- a/include/struct.h +++ b/include/struct.h @@ -57,6 +57,11 @@ #include #endif #include "auth.h" +#ifdef HAVE_REGEX +#include +#else +#include "../extras/regex/regex.h" +#endif extern int sendanyways; @@ -1012,6 +1017,7 @@ struct _configitem_badword { ConfigItem *prev, *next; ConfigFlag flag; char *word, *replace; + regex_t expr; }; struct _configitem_deny_dcc { @@ -1087,10 +1093,12 @@ struct _configitem_alias_format { short type; char *format, *parameters; }; + +#define INCLUDE_NOTLOADED 1 struct _configitem_include { ConfigItem *prev, *next; - ConfigFlag flag; + ConfigFlag_ban flag; char *file; }; @@ -1158,11 +1166,7 @@ struct ListOptions { /* mode structure for channels */ struct SMode { -#ifndef USE_LONGMODE - unsigned int mode; -#else long mode; -#endif int limit; char key[KEYLEN + 1]; char link[LINKLEN + 1]; @@ -1439,5 +1443,24 @@ struct Command { #endif }; +#ifdef THROTTLING + +struct ThrottlingBucket +{ + struct ThrottlingBucket *next, *prev; + struct IN_ADDR in; + time_t since; +}; + +void init_throttling_hash(); +int hash_throttling(struct IN_ADDR *in); +struct ThrottlingBucket *find_throttling_bucket(struct IN_ADDR *in); +void add_throttling_bucket(struct IN_ADDR *in); +void del_throttling_bucket(struct ThrottlingBucket *bucket); +int throttle_can_connect(struct IN_ADDR *in); + +#endif + + #endif /* __struct_include__ */ diff --git a/include/version.h b/include/version.h index 6c92893de..d32531e9a 100644 --- a/include/version.h +++ b/include/version.h @@ -29,7 +29,7 @@ #define UnrealProtocol 2303 #define PATCH1 "3" #define PATCH2 ".2" -#define PATCH3 "-beta13" +#define PATCH3 "-beta14" #define PATCH4 "" #define PATCH5 "" #define PATCH6 "" diff --git a/makefile.win32 b/makefile.win32 index fc1aa7faf..c80611783 100644 --- a/makefile.win32 +++ b/makefile.win32 @@ -35,7 +35,7 @@ OBJ_FILES=SRC/CHANNEL.OBJ SRC/SEND.OBJ SRC/SOCKET.OBJ \ SRC/S_KLINE.OBJ SRC/S_EXTRA.OBJ SRC/IRCSPRINTF.OBJ SRC/LUSERS.OBJ \ SRC/SCACHE.OBJ SRC/ALN.OBJ SRC/BADWORDS.OBJ SRC/WEBTV.OBJ SRC/RES.OBJ SRC/MODULES.OBJ \ SRC/S_SVS.OBJ SRC/EVENTS.OBJ SRC/UMODES.OBJ SRC/AUTH.OBJ SRC/CIDR.OBJ SRC/SSL.OBJ \ - SRC/SERVICE.OBJ SRC/DEBUG.OBJ + SRC/SERVICE.OBJ SRC/DEBUG.OBJ SRC/RANDOM.OBJ MOD_FILES=SRC/L_COMMANDS.OBJ SRC/M_CHGHOST.OBJ SRC/M_SDESC.OBJ SRC/M_SETIDENT.OBJ \ SRC/M_SETNAME.OBJ SRC/M_SETHOST.OBJ SRC/M_CHGIDENT.OBJ SRC/M_SVSMOTD.OBJ \ @@ -228,6 +228,9 @@ src/auth.obj: src/auth.c $(INCLUDES) src/cidr.obj: src/cidr.c $(INCLUDES) $(CC) $(CFLAGS) src/cidr.c +src/random.obj: src/random.c $(INCLUDES) + $(CC) $(CFLAGS) src/random.c + src/ssl.obj: src/ssl.c $(INCLUDES) $(CC) $(CFLAGS) src/ssl.c diff --git a/src/Makefile b/src/Makefile index 7b051822c..d1f19a109 100644 --- a/src/Makefile +++ b/src/Makefile @@ -28,7 +28,7 @@ OBJS=auth.o aln.o badwords.o channel.o cloak.o crule.o dbuf.o \ s_bsd.o s_conf.o s_debug.o s_err.o s_extra.o s_kline.o \ s_misc.o s_numeric.o s_serv.o s_svs.o $(STRTOUL) socket.o \ ssl.o s_user.o scache.o send.o support.o umodes.o \ - version.o webtv.o whowas.o zip.o cidr.o + version.o webtv.o whowas.o zip.o cidr.o random.o SRC=$(OBJS:%.o=%.c) @@ -53,7 +53,7 @@ all: build build: ircd mods custommodule: - cd modules; make $(MAKEARGS) MODULEFILE=$(MODULEFILE) EXLIBS=$(EXLIBS) custommodule + cd modules; $(MAKE) MODULEFILE=$(MODULEFILE) EXLIBS=$(EXLIBS) custommodule ircd: $(OBJS) $(CC) $(CFLAGS) $(CRYPTOLIB) -o ircd $(OBJS) $(LDFLAGS) $(IRCDLIBS) $(CRYPTOLIB) @@ -76,7 +76,7 @@ mods: @if [ ! -r modules ] ; then \ echo "You havent done cvs update -P -d"; \ fi - cd modules; make $(MAKEARGS) all + cd modules; $(MAKE) all version.c: version.c.SH ../Changes $(SHELL) version.c.SH @@ -237,5 +237,8 @@ crule.o: crule.c $(INCLUDES) cidr.o: cidr.c $(INCLUDES) $(CC) $(CFLAGS) -c cidr.c +random.o: random.c $(INCLUDES) + $(CC) $(CFLAGS) -c random.c + # DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/src/auth.c b/src/auth.c index 00ca3a11a..cd8d11124 100644 --- a/src/auth.c +++ b/src/auth.c @@ -91,8 +91,7 @@ int Auth_CheckError(ConfigEntry *ce) if (!ce->ce_vardata) { config_error("%s:%i: authentication module failure: missing parameter", - ce->ce_fileptr->cf_filename, ce->ce_varlinenum, - ce->ce_entries->ce_varname); + ce->ce_fileptr->cf_filename, ce->ce_varlinenum); return -1; } if (ce->ce_entries) diff --git a/src/badwords.c b/src/badwords.c index 09ec72174..1f4b5eab1 100644 --- a/src/badwords.c +++ b/src/badwords.c @@ -44,11 +44,10 @@ void badwords_stats(aClient *sptr) char *stripbadwords_channel(char *str) { regmatch_t pmatch[MAX_MATCH]; - regex_t pcomp; static char cleanstr[4096]; char buf[4096]; char *ptr; - int errorcode, matchlen, stringlen; + int matchlen, stringlen, cleaned; ConfigItem_badword *this_word; if (!conf_badword_channel) return str; @@ -56,30 +55,24 @@ char *stripbadwords_channel(char *str) /* * work on a copy */ - stringlen = strlcpy(cleanstr, str, sizeof cleanstr); + stringlen = strlcpy(cleanstr, StripControlCodes(str), sizeof cleanstr); memset(&pmatch, 0, sizeof pmatch); matchlen = 0; buf[0] = '\0'; + cleaned = 0; for (this_word = conf_badword_channel; this_word; this_word = (ConfigItem_badword *)this_word->next) { - if ((errorcode = - regcomp(&pcomp, this_word->word, REG_ICASE)) > 0) - { - regfree(&pcomp); - return cleanstr; - } - /* * Set pointer to start of string */ ptr = cleanstr; - while (regexec(&pcomp, ptr, MAX_MATCH, pmatch, - 0) != REG_NOMATCH) + while (regexec(&this_word->expr, ptr, MAX_MATCH, pmatch,0) != REG_NOMATCH) { if (pmatch[0].rm_so == -1) break; + cleaned = 1; matchlen += pmatch[0].rm_eo - pmatch[0].rm_so; strlncat(buf, ptr, sizeof buf, pmatch[0].rm_so); if (this_word->replace) @@ -93,22 +86,19 @@ char *stripbadwords_channel(char *str) strlcat(buf, ptr, sizeof buf); memcpy(cleanstr, buf, sizeof cleanstr); memset(buf, 0, sizeof(buf)); - regfree(&pcomp); if (matchlen == stringlen) break; } - - return (cleanstr); + return (cleaned) ? cleanstr : str; } char *stripbadwords_message(char *str) { regmatch_t pmatch[MAX_MATCH]; - regex_t pcomp; static char cleanstr[4096]; char buf[4096]; char *ptr; - int errorcode, matchlen, stringlen; + int matchlen, stringlen; ConfigItem_badword *this_word; if (!conf_badword_message) return str; @@ -123,19 +113,12 @@ char *stripbadwords_message(char *str) for (this_word = conf_badword_message; this_word; this_word = (ConfigItem_badword *)this_word->next) { - if ((errorcode = - regcomp(&pcomp, this_word->word, REG_ICASE)) > 0) - { - regfree(&pcomp); - return cleanstr; - } - /* * Set pointer to start of string */ ptr = cleanstr; - while (regexec(&pcomp, ptr, MAX_MATCH, pmatch, + while (regexec(&this_word->expr, ptr, MAX_MATCH, pmatch, 0) != REG_NOMATCH) { if (pmatch[0].rm_so == -1) @@ -153,7 +136,6 @@ char *stripbadwords_message(char *str) strlcat(buf, ptr, sizeof buf); memcpy(cleanstr, buf, sizeof cleanstr); memset(buf, 0, sizeof(buf)); - regfree(&pcomp); if (matchlen == stringlen) break; } diff --git a/src/channel.c b/src/channel.c index 843378762..b1eaaa802 100644 --- a/src/channel.c +++ b/src/channel.c @@ -103,7 +103,6 @@ static char nickbuf[BUFSIZE], buf[BUFSIZE]; char modebuf[MAXMODEPARAMS*2+1], parabuf[504]; #include "sjoin.h" -#ifdef USE_LONGMODE typedef struct { long mode; char flag; @@ -112,7 +111,6 @@ typedef struct { } aCtab; -// typedef struct CFlagTab aCtab; #define MODESYS_LINKOK /* We do this for a TEST */ aCtab cFlagTab[] = { {MODE_LIMIT, 'l', 0, 1}, @@ -151,7 +149,6 @@ aCtab cFlagTab[] = { {MODE_NONICKCHANGE, 'N', 0, 0}, {0x0, 0x0, 0x0} }; -#endif #define BADOP_BOUNCE 1 @@ -1586,7 +1583,7 @@ int do_mode_char(aChannel *chptr, long modetype, char modechar, char *param, char tmpbuf[512], *tmpstr; char tc = ' '; /* */ int chasing, x; - int xxi, xyi, xzi, hascolon; + int xxi, xyi, xzi, hascolon; char *xxx; char *xp; int notsecure; @@ -2142,6 +2139,8 @@ int do_mode_char(aChannel *chptr, long modetype, char modechar, char *param, '*' ? (param + 1) : param)); xp++; xyi = atoi(xp); + if (xxi > 500 || xyi > 500) + break; xp--; *xp = ':'; if ((xxi == 0) || (xyi == 0)) @@ -2621,7 +2620,8 @@ static void sub1_from_channel(aChannel *chptr) Ban *ban; Link *lp; - if (--chptr->users <= 0) + /* if (--chptr->users <= 0) */ + if (chptr->users == 0 || --chptr->users == 0) { /* * Now, find all invite links from channel structure diff --git a/src/hash.c b/src/hash.c index 934307a55..caf23124b 100644 --- a/src/hash.c +++ b/src/hash.c @@ -729,4 +729,98 @@ int hash_del_watch_list(aClient *cptr) return 0; } +/* + * Throttling + * -by Stskeeps +*/ +#ifdef THROTTLING + +struct ThrottlingBucket *ThrottlingHash[THROTTLING_HASH_SIZE+1]; + +void init_throttling_hash() +{ + bzero(ThrottlingHash, sizeof(ThrottlingHash)); + EventAddEx(NULL, "bucketcleaning", THROTTLING_PERIOD/2, 0, + e_clean_out_throttling_buckets, NULL); +} + +int hash_throttling(struct IN_ADDR *in) +{ +#ifndef INET6 + return ((int)in->s_addr % THROTTLING_HASH_SIZE); +#else + /* FIXME: This way it will work until we find a way to do it. */ + return 0; +#endif +} + +struct ThrottlingBucket *find_throttling_bucket(struct IN_ADDR *in) +{ + int hash = 0; + struct ThrottlingBucket *p; + hash = hash_throttling(in); + + for (p = ThrottlingHash[hash]; p; p = p->next) + { + if (bcmp(in, &p->in, sizeof(struct IN_ADDR)) == 0) + return(p); + } + return NULL; +} + +void add_throttling_bucket(struct IN_ADDR *in) +{ + int hash; + struct ThrottlingBucket *n; + + n = malloc(sizeof(struct ThrottlingBucket)); + n->next = n->prev = NULL; + bcopy(in, &n->in, sizeof(struct IN_ADDR)); + n->since = TStime(); + hash = hash_throttling(in); + AddListItem(n, ThrottlingHash[hash]); + return; +} + +void del_throttling_bucket(struct ThrottlingBucket *bucket) +{ + int hash; + struct ThrottlingBucket *n; + hash = hash_throttling(&bucket->in); + + DelListItem(n, ThrottlingHash[hash]); + return; +} + +int throttle_can_connect(struct IN_ADDR *in) +{ + if (!find_throttling_bucket(in)) + return 1; + else + return 0; +} + +EVENT(e_clean_out_throttling_buckets) +{ + struct ThrottlingBucket *n; + int i; + struct ThrottlingBucket z = { NULL, NULL, 0}; + + for (i = 0; i < THROTTLING_HASH_SIZE; i++) + for (n = ThrottlingHash[i]; n; n = n->next) + if (TStime() - n->since > THROTTLING_PERIOD) + { + if (n->prev) + n->prev->next = n->next; + else + ThrottlingHash[i] = n->next; + if (n->next) + n->next->prev = n->prev; + z.next = n->next; + n = &z; + } + return; +} + +#endif diff --git a/src/ircd.c b/src/ircd.c index 46f7531c0..328620ff4 100644 --- a/src/ircd.c +++ b/src/ircd.c @@ -1209,8 +1209,12 @@ int InitwIRCD(int argc, char *argv[]) } } #endif + init_random(); Debug((DEBUG_NOTICE, "Server ready...")); SetupEvents(); +#ifdef THROTTLING + init_throttling_hash(); +#endif loop.do_bancheck = 0; loop.ircd_booted = 1; #if defined(HAVE_SETPROCTITLE) diff --git a/src/match.c b/src/match.c index ba696b12a..1e3fedb0d 100644 --- a/src/match.c +++ b/src/match.c @@ -67,6 +67,10 @@ static inline int match2(char *mask, char *name) } else if (cm != '?' && lc(cm) != lc(*n)) return 1; /* most likely first chars won't match */ + else if ((*m == '\0') && (*n == '\0')) + return 0; /* true: both are empty */ + else if (*n == '\0') + return 1; /* false: name is empty */ else { m++; @@ -91,6 +95,7 @@ static inline int match2(char *mask, char *name) cm = *m; if (cm == '\\') /* don't do ? checking if a \ */ { + cm = *(++m); /* just skip this char, no ? checking */ } else if (cm == '?') /* if it's a ? */ @@ -98,6 +103,8 @@ static inline int match2(char *mask, char *name) do { m++; /* go to the next char of both */ + if (!*n) + return 1; /* false: no character left */ n++; if (!*n) /* if end of test string... */ return (!*m ? 0 : 1); /* true if end of mask str, else false */ @@ -110,9 +117,9 @@ static inline int match2(char *mask, char *name) cm = lc(cm); while (lc(*n) != cm) { /* compare */ - n++; /* go to next char of n */ if (!*n) /* if at end of n string */ return 1; /* function becomes false. */ + n++; /* go to next char of n */ } wsm = m; /* mark after where wildcard found */ cm = lc(*(++m)); /* go to next mask char */ @@ -123,6 +130,8 @@ static inline int match2(char *mask, char *name) if (cm == '?') /* found ? wildcard */ { cm = lc(*(++m)); /* just skip and go to next */ + if (!*n) + return 1; /* false: no character left */ n++; if (!*n) /* return true if end of both, */ return (cm ? 1 : 0); /* false if end of test str only */ @@ -143,9 +152,9 @@ static inline int match2(char *mask, char *name) cm = lc(*m); while (cm != lc(*n)) { /* compare them */ - n++; /* go to next char of n */ if (!*n) /* if we reached end of n string, */ return 1; /* function becomes false. */ + n++; /* go to next char of n */ } wsn = n; /* mark spot first char was found */ } diff --git a/src/modules/l_commands.c b/src/modules/l_commands.c index e598c380b..1f9507fc3 100644 --- a/src/modules/l_commands.c +++ b/src/modules/l_commands.c @@ -73,6 +73,7 @@ ModuleHeader l_commands_Header * want to */ +extern int m_htm_Test(ModuleInfo *modinfo); #ifdef SCAN_API extern int m_scan_Test(ModuleInfo *modinfo); #endif @@ -148,7 +149,6 @@ extern int m_scan_Unload(), scan_socks_Unload(), scan_http_Unload(); extern int invisibility_Unload(); #endif -#ifdef SCAN_API #ifdef DYNAMIC_LINKING DLLFUNC int Mod_Test(ModuleInfo *modinfo) #else @@ -157,14 +157,16 @@ int l_commands_Test(ModuleInfo *modinfo) { Module p; bcopy(modinfo,&ModCmdsInfo,modinfo->size); +#ifdef SCAN_API p.header = &scan_socks_Header; Module_Depend_Resolve(&p); p.header = &scan_http_Header; Module_Depend_Resolve(&p); - m_scan_Test(modinfo); + m_scan_Test(&ModCmdsInfo); +#endif + m_htm_Test(&ModCmdsInfo); return MOD_SUCCESS; } -#endif #ifdef DYNAMIC_LINKING diff --git a/src/modules/m_htm.c b/src/modules/m_htm.c index b0c8425fe..c2bb09f36 100644 --- a/src/modules/m_htm.c +++ b/src/modules/m_htm.c @@ -56,11 +56,6 @@ extern int LRV; #endif -#ifdef DYNAMIC_LINKING -Module *Mod_Handle = NULL; -#else -#define Mod_Handle NULL -#endif DLLFUNC int m_htm(aClient *cptr, aClient *sptr, int parc, char *parv[]); EVENT(lcf_check); EVENT(htm_calc); @@ -70,7 +65,12 @@ Event *e_lcf, *e_htmcalc; #define MSG_HTM "HTM" #define TOK_HTM "BH" +DLLFUNC int htm_config_test(ConfigFile *, ConfigEntry *, int, int *); +DLLFUNC int htm_config_run(ConfigFile *, ConfigEntry *, int); +DLLFUNC int htm_stats(aClient *, char *); +ModuleInfo HtmModInfo; +static Hook *ConfTest, *ConfRun, *ServerStats; #ifndef DYNAMIC_LINKING ModuleHeader m_htm_Header #else @@ -90,6 +90,21 @@ ModuleHeader Mod_Header * want to */ +#ifdef DYNAMIC_LINKING +DLLFUNC int Mod_Test(ModuleInfo *modinfo) +#else +int m_htm_Test(ModuleInfo *modinfo) +#endif +{ + /* + * We call our add_Command crap here + */ + bcopy(modinfo,&HtmModInfo,modinfo->size); + ConfTest = HookAddEx(HtmModInfo.handle, HOOKTYPE_CONFIGTEST, htm_config_test); + return MOD_SUCCESS; +} + + /* This is called on module init, before Server Ready */ #ifdef DYNAMIC_LINKING DLLFUNC int Mod_Init(ModuleInfo *modinfo) @@ -101,10 +116,12 @@ int m_htm_Init(ModuleInfo *modinfo) * We call our add_Command crap here */ add_Command(MSG_HTM, TOK_HTM, m_htm, MAXPARA); + ConfRun = HookAddEx(HtmModInfo.handle, HOOKTYPE_CONFIGRUN, htm_config_run); + ServerStats = HookAddEx(HtmModInfo.handle, HOOKTYPE_STATS, htm_stats); #ifndef NO_FDLIST LockEventSystem(); - e_lcf = EventAddEx(Mod_Handle, "lcf", LCF, 0, lcf_check, NULL); - e_htmcalc = EventAddEx(Mod_Handle, "htmcalc", 1, 0, htm_calc, NULL); + e_lcf = EventAddEx(HtmModInfo.handle, "lcf", LCF, 0, lcf_check, NULL); + e_htmcalc = EventAddEx(HtmModInfo.handle, "htmcalc", 1, 0, htm_calc, NULL); UnlockEventSystem(); #endif return MOD_SUCCESS; @@ -398,5 +415,102 @@ EVENT(htm_calc) highest_rate2 = currentrate2; last = TStime(); } - #endif + +DLLFUNC int htm_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) { + ConfigEntry *cep; + int errors = 0; + + if (type != CONFIG_SET) + return 0; + + if (!strcmp(ce->ce_varname, "htm")) + { + for (cep = ce->ce_entries; cep; cep = cep->ce_next) + { + if (!cep->ce_varname) + { + config_error("%s:%i: blank set::htm item", + cep->ce_fileptr->cf_filename, + cep->ce_varlinenum); + errors++; + continue; + } + if (!cep->ce_vardata) + { + config_error("%s:%i: set::htm::%s item without value", + cep->ce_fileptr->cf_filename, + cep->ce_varlinenum, cep->ce_varname); + errors++; + continue; + } + if (!strcmp(cep->ce_varname, "mode")) + { + + if (stricmp(cep->ce_vardata, "noisy") && stricmp(cep->ce_vardata, "quiet")) + { + config_error("%s%i: set::htm::mode: illegal mode", + cep->ce_fileptr->cf_filename, cep->ce_varlinenum); + errors++; + } + } + else if (!strcmp(cep->ce_varname, "incoming-rate")) + { + int value = config_checkval(cep->ce_vardata, CFG_SIZE); + if (value < 10240) + { + config_error("%s%i: set::htm::incoming-rate: must be at least 10kb", + cep->ce_fileptr->cf_filename, cep->ce_varlinenum); + errors++; + } + } + else + { + config_error("%s:%i: unknown directive set::htm::%s", + cep->ce_fileptr->cf_filename, cep->ce_varlinenum, + cep->ce_varname); + errors++; + } + + } + *errs = errors; + return errors ? -1 : 1; + } + else + return 0; +} + +DLLFUNC int htm_config_run(ConfigFile *cf, ConfigEntry *ce, int type) { + ConfigEntry *cep; + int errors = 0; + + if (type != CONFIG_SET) + return 0; + if (!strcmp(ce->ce_varname, "htm")) + { + for (cep = ce->ce_entries; cep; cep = cep->ce_next) + { + if (!strcmp(cep->ce_varname, "mode")) + { + if (!stricmp(cep->ce_vardata, "noisy")) + noisy_htm = 1; + else + noisy_htm = 0; + } + else if (!strcmp(cep->ce_varname, "incoming-rate")) + LRV = config_checkval(cep->ce_vardata, CFG_SIZE); + } + return 1; + } + return 0; +} + +DLLFUNC int htm_stats(aClient *sptr, char *stats) { + if (*stats == 'S') { + sendto_one(sptr, ":%s %i %s :htm::mode: %s", me.name, RPL_TEXT, + sptr->name, noisy_htm ? "noisy" : "quiet"); + sendto_one(sptr, ":%s %i %s :htm::incoming-rate: %d", me.name, RPL_TEXT, + sptr->name, LRV); + } + return 0; +} diff --git a/src/modules/m_mkpasswd.c b/src/modules/m_mkpasswd.c index b7e153c38..c86e57a95 100644 --- a/src/modules/m_mkpasswd.c +++ b/src/modules/m_mkpasswd.c @@ -125,9 +125,6 @@ int m_mkpasswd(aClient *cptr, aClient *sptr, int parc, char *parv[]) me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", parv[0]); return 0; } -#ifndef _WIN32 - srandom(TStime()); -#endif if ((type = Auth_FindType(parv[1])) == -1) { sendto_one(sptr, diff --git a/src/modules/m_oper.c b/src/modules/m_oper.c index 1b54f9a5a..ad2614d26 100644 --- a/src/modules/m_oper.c +++ b/src/modules/m_oper.c @@ -278,10 +278,12 @@ DLLFUNC int m_oper(aClient *cptr, aClient *sptr, int parc, char *parv[]) { user->virthost : sptr->user->realhost, parv[1], announce); } - if (!aconf->snomask) - set_snomask(sptr, SNO_DEFOPER); - else + if (aconf->snomask) set_snomask(sptr, aconf->snomask); + else if (OPER_SNOMASK) + set_snomask(sptr, OPER_SNOMASK); + else + set_snomask(sptr, SNO_DEFOPER); send_umode_out(cptr, sptr, old); sendto_one(sptr, rpl_str(RPL_SNOMASK), me.name, parv[0], get_sno_str(sptr)); diff --git a/src/modules/m_tkl.c b/src/modules/m_tkl.c index 416b4fea8..80d6a8d51 100644 --- a/src/modules/m_tkl.c +++ b/src/modules/m_tkl.c @@ -346,7 +346,7 @@ DLLFUNC int m_tkl_line(aClient *cptr, aClient *sptr, int parc, char *parv[], ch secs = 0; - if (whattodo == 0 && (parc > 2)) + if (whattodo == 0 && (parc > 3)) { secs = atime(parv[2]); if (secs < 0) @@ -373,9 +373,10 @@ DLLFUNC int m_tkl_line(aClient *cptr, aClient *sptr, int parc, char *parv[], ch ircsprintf(mo2, "%li", TStime()); tkllayer[6] = mo; tkllayer[7] = mo2; - tkllayer[8] = "No reason"; if (parc > 3) { tkllayer[8] = parv[3]; + } else if (parc > 2) { + tkllayer[8] = parv[2]; } /* call the tkl layer .. */ m_tkl(&me, &me, 9, tkllayer); diff --git a/src/modules/m_tsctl.c b/src/modules/m_tsctl.c index 1f715692e..e750e77c0 100644 --- a/src/modules/m_tsctl.c +++ b/src/modules/m_tsctl.c @@ -138,7 +138,7 @@ DLLFUNC int m_tsctl(aClient *cptr, aClient *sptr, int parc, char *parv[]) return 0; } - if (strcmp(parv[1], "offset") == 0) + if (stricmp(parv[1], "offset") == 0) { if (!parv[3]) { @@ -188,7 +188,7 @@ DLLFUNC int m_tsctl(aClient *cptr, aClient *sptr, int parc, char *parv[]) } return 0; } - if (strcmp(parv[1], "time") == 0) + if (stricmp(parv[1], "time") == 0) { sendto_one(sptr, ":%s NOTICE %s :*** TStime=%li time()=%li TSoffset=%li", @@ -196,7 +196,7 @@ DLLFUNC int m_tsctl(aClient *cptr, aClient *sptr, int parc, char *parv[]) TSoffset); return 0; } - if (strcmp(parv[1], "alltime") == 0) + if (stricmp(parv[1], "alltime") == 0) { sendto_one(sptr, ":%s NOTICE %s :*** Server=%s TStime=%li time()=%li TSoffset=%li", @@ -207,7 +207,7 @@ DLLFUNC int m_tsctl(aClient *cptr, aClient *sptr, int parc, char *parv[]) return 0; } - if (strcmp(parv[1], "svstime") == 0) + if (stricmp(parv[1], "svstime") == 0) { if (!parv[2] || *parv[2] == '\0') { diff --git a/src/modules/scan.c b/src/modules/scan.c index 719c8112c..247ec197f 100644 --- a/src/modules/scan.c +++ b/src/modules/scan.c @@ -199,7 +199,7 @@ int Scan_IsBeingChecked(struct IN_ADDR *ia) IRCMutexLock(Scannings_lock); for (sr = Scannings; sr; sr = sr->next) { - if (!bcmp(&sr->in, ia, sizeof(Scan_AddrStruct))) + if (!bcmp(&sr->in, ia, sizeof(struct IN_ADDR))) { ret = 1; break; @@ -347,7 +347,7 @@ DLLFUNC int h_scan_connect(aClient *sptr) * }; * */ -DLLFUNC h_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) { +DLLFUNC int h_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) { ConfigEntry *cep; int errors = 0; @@ -439,7 +439,7 @@ DLLFUNC h_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) { return 0; } -DLLFUNC h_config_run(ConfigFile *cf, ConfigEntry *ce, int type) { +DLLFUNC int h_config_run(ConfigFile *cf, ConfigEntry *ce, int type) { ConfigEntry *cep; int errors = 0; @@ -515,16 +515,17 @@ DLLFUNC int h_config_rehash() { if (scan_message) MyFree(scan_message); + return 1; } DLLFUNC int h_stats_scan(aClient *sptr, char *stats) { if (*stats == 'S') { sendto_one(sptr, ":%s %i %s :scan::endpoint: %s:%d", me.name, RPL_TEXT, sptr->name, Inet_si2p(&Scan_endpoint), ntohs(Scan_endpoint.SIN_PORT)); - sendto_one(sptr, ":%s %i %s :scan::bantime: %d", me.name, RPL_TEXT, sptr->name, - Scan_BanTime); - sendto_one(sptr, ":%s %i %s :scan::timeout: %d", me.name, RPL_TEXT, sptr->name, - Scan_TimeOut); + sendto_one(sptr, ":%s %i %s :scan::bantime: %s", me.name, RPL_TEXT, sptr->name, + pretty_time_val(Scan_BanTime)); + sendto_one(sptr, ":%s %i %s :scan::timeout: %s", me.name, RPL_TEXT, sptr->name, + pretty_time_val(Scan_TimeOut)); sendto_one(sptr, ":%s %i %s :scan::bind-ip: %s", me.name, RPL_TEXT, sptr->name, Inet_ia2p(&Scan_bind)); sendto_one(sptr, ":%s %i %s :scan::message: %s", diff --git a/src/random.c b/src/random.c new file mode 100644 index 000000000..368da47ac --- /dev/null +++ b/src/random.c @@ -0,0 +1,172 @@ +/************************************************************************ + * IRC - Internet Relay Chat, random.c + * (C) 2003 Bram Matthys (Syzop) + * + * See file AUTHORS in IRC package for additional names of + * the programmers. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "struct.h" +#include "common.h" +#include "sys.h" +#include "numeric.h" +#include "msg.h" +#include "channel.h" +#include "version.h" +#include +#ifdef _WIN32 +#include +#endif +#include +#include +#include +#include +#ifdef _WIN32 +#include +#endif +#include +#include "h.h" + +#ifdef NOSPOOF +/* + * getrandom32, written by Syzop. + * This function returns a random 32bit value + */ +u_int32_t getrandom32() +{ +u_int32_t result; +int n; +#ifndef _WIN32 +static struct timeval prevt; +struct timeval nowt; +#else +static struct _timeb prevt; +struct _timeb nowt; +#endif +#ifdef USE_SSL + #if OPENSSL_VERSION_NUMBER >= 0x000907000 + if (EGD_PATH) { + n = RAND_query_egd_bytes(EGD_PATH, (unsigned char *)&result, sizeof(result)); + if (n == sizeof(result)) + return result; + } + #endif +#endif + +#ifndef _WIN32 + gettimeofday(&nowt, NULL); + + /* [random() may return <31 random bits, I assume it will be at least 16 bits] + * 31bits (low) ^ 16bits (high) ^ 19bits (low) ^ 19bits (high) */ + result = random() ^ (random() << 16) ^ nowt.tv_usec ^ (prevt.tv_usec << 13); +#else + _ftime(&nowt); + + /* 15bits (0..14) ^ 15 bits (10..24) ^ 12 bits (20..31) ^ + * 10bits (10..19) ^ 10 bits (20..29) + */ + result = rand() ^ (rand() << 10) ^ (rand() << 20) ^ + (nowt.millitm << 10) ^ (prevt.millitm << 20); +#endif + + prevt = nowt; + return result; +} +#endif + +static unsigned int entropy_cfgcrc = 0, entropy_cfgsize = 0; +static time_t entropy_cfgmtime = 0; + +void add_entropy_configfile(struct stat st, char *buf) +{ + entropy_cfgsize = (entropy_cfgsize << 4) ^ st.st_size; + entropy_cfgmtime = (entropy_cfgmtime << 4) ^ st.st_mtime; + entropy_cfgcrc = entropy_cfgcrc ^ (unsigned int)crc32(buf, strlen(buf)); + Debug((DEBUG_INFO, "add_entropy_configfile: cfgsize: %u", entropy_cfgsize)); + Debug((DEBUG_INFO, "add_entropy_configfile: cfgmtime: %u", + (unsigned int)entropy_cfgmtime)); + Debug((DEBUG_INFO, "add_entropy_configfile: cfgcrc: %u", entropy_cfgcrc)); +} + +/* + * init_random, written by Syzop + * This function (hopefully) intialises the random generator securely + */ +void init_random() +{ +unsigned int seed, egd = 0; +time_t now = TStime(); +#ifndef _WIN32 +struct timeval nowt; +unsigned int xrnd = 0; +int fd, n; +#else +MEMORYSTATUS mstat; +struct _timeb nowt; +#endif + +#ifdef USE_SSL + #if OPENSSL_VERSION_NUMBER >= 0x000907000 + if (EGD_PATH) { + n = RAND_query_egd_bytes(EGD_PATH, (unsigned char *)&egd, sizeof(egd)); + Debug((DEBUG_INFO, + "init_random: RAND_query_egd_bytes() ret=%d, val=%.8x", n, egd)); + } + #endif +#endif + + /* Grab non-OS specific "random" data */ + + /* Grab OS specific "random" data */ +#ifndef _WIN32 + gettimeofday(&nowt, NULL); + fd = open("/dev/urandom", O_RDONLY); + if (fd) { + (void)read(fd, &xrnd, sizeof(int)); + Debug((DEBUG_INFO, "init_random: read from /dev/urandom: 0x%.8x", xrnd)); + close(fd); + } +#else + _ftime(&nowt); + GlobalMemoryStatus (&mstat); + #ifdef DEBUGMODE + Debug((DEBUG_INFO, "init_random: mstat.dwAvailPhys=%u, mstat.dwAvailPageFile=%u\n", + mstat.dwAvailPhys, mstat.dwAvailPageFile)); + #endif +#endif + + /* Build the seed (OS specific again) */ +#ifndef _WIN32 + seed = now ^ nowt.tv_usec ^ getpid() ^ (entropy_cfgsize << 24) ^ + (entropy_cfgmtime << 16) ^ entropy_cfgcrc ^ CLOAK_KEY1 ^ xrnd ^ egd; +#else + seed = now ^ nowt.millitm ^ getpid() ^ mstat.dwAvailPhys ^ + (mstat.dwAvailPageFile << 16) ^ (entropy_cfgsize << 8) ^ + (entropy_cfgmtime << 24) ^ entropy_cfgcrc ^ CLOAK_KEY1 ^ egd; +#endif + + Debug((DEBUG_INFO, "init_random: seeding to 0x%.8x (%u)", seed, seed)); + srand(seed); +#ifdef LRAND48 + srand48(seed); +#endif +#ifndef _WIN32 + srandom(seed); +#endif +} + diff --git a/src/res.c b/src/res.c index dffe91d0d..689b7bbad 100644 --- a/src/res.c +++ b/src/res.c @@ -118,9 +118,6 @@ int init_resolver(int op) } #endif -#ifdef LRAND48 - srand48(TStime()); -#endif if (op & RES_INITLIST) { bzero((char *)&reinfo, sizeof(reinfo)); @@ -697,20 +694,19 @@ static int query_name(char *name, int class, int type, ResRQ *rptr) return r; } hptr = (HEADER *) buf; -#ifdef LRAND48 - do - { - hptr->id = htons(ntohs(hptr->id) + k + lrand48() & 0xffff); -#else (void)gettimeofday(&tv, NULL); do { /* htons/ntohs can be assembler macros, which cannot be nested. Thus two lines. -Vesa */ +#ifdef LRAND48 u_short nstmp = ntohs(hptr->id) + k + - (u_short)(tv.tv_usec & 0xffff); - hptr->id = htons(nstmp); + (u_short)(tv.tv_usec & 0xffff) + (u_short)(lrand48() & 0xffff); +#else + u_short nstmp = ntohs(hptr->id) + k + + (u_short)(tv.tv_usec & 0xffff) + (u_short)(rand() & 0xffff); #endif /* LRAND48 */ + hptr->id = htons(nstmp); k++; } while (find_id(ntohs(hptr->id))); @@ -1159,6 +1155,7 @@ struct hostent *get_res(char *lp,long id) bcopy((char *)&rptr->cinfo, lp, sizeof(Link)); } #else +/* WIN32 */ he = rptr->he; if (he && he->h_name && ((struct IN_ADDR *)he->h_addr)->S_ADDR && rptr->locked < 2) @@ -1373,11 +1370,10 @@ static void update_list(ResRQ *rptr, aCache *cachep) */ #ifdef INET6 for (s = (char *)HE(rptr)->h_addr.S_ADDR; - ((struct IN_ADDR *)s)->S_ADDR; s += sizeof(struct IN_ADDR)) #else for (s = (char *)&HE(rptr)->h_addr.S_ADDR; - ((struct IN_ADDR *)s)->S_ADDR; s += sizeof(struct IN_ADDR)) #endif + WHOSTENTP(((struct IN_ADDR *)s)->S_ADDR); s += sizeof(struct IN_ADDR)) { #ifdef INET6 for (i = 0; (t = HE(cp)->h_addr_list[i]); i++) @@ -1407,10 +1403,18 @@ static void update_list(ResRQ *rptr, aCache *cachep) base = (char **)MyRealloc((char *)ab, (addrcount + 1) * sizeof(*ab)); HE(cp)->h_addr_list = base; + ab = (struct IN_ADDR **)HE(cp)->h_addr_list; /* Update after realloc -- Syzop */ #ifdef DEBUGMODE + #ifdef INET6 + Debug((DEBUG_DNS, "u_l:add IP %s hal %x ac %d", + inet_ntop(((struct IN_ADDR *)s), mydummy, + MYDUMMY_SIZE), + HE(cp)->h_addr_list, addrcount)); + #else Debug((DEBUG_DNS, "u_l:add IP %x hal %x ac %d", ntohl(((struct IN_ADDR *)s)->S_ADDR), HE(cp)->h_addr_list, addrcount)); + #endif #endif for (; addrcount; addrcount--) { @@ -1560,7 +1564,7 @@ static aCache *make_cache(ResRQ *rptr) ** shouldn't happen but it just might... */ #ifndef _WIN32 - if (!rptr->he.h_name || !rptr->he.h_addr.S_ADDR) + if (!rptr->he.h_name || !WHOSTENTP(rptr->he.h_addr.S_ADDR) ) #else if (!rptr->he->h_name || !((struct IN_ADDR *)rptr->he->h_addr)->S_ADDR) #endif diff --git a/src/s_bsd.c b/src/s_bsd.c index fc87c163f..696d3c789 100644 --- a/src/s_bsd.c +++ b/src/s_bsd.c @@ -750,8 +750,6 @@ int check_client(aClient *cptr) if ((i = AllowClient(cptr, hp, sockname))) { - Debug((DEBUG_DNS, "ch_cl: access denied: %s[%s]", - cptr->name, sockname)); return i; } @@ -1210,7 +1208,7 @@ add_con_refuse: ircsprintf(zlinebuf, "ERROR :Closing Link: [%s] (Too many unknown connections from your IP)" "\r\n", - inetntoa((char *)&acptr->ip)); + Inet_ia2p(&acptr->ip)); set_non_blocking(fd, acptr); set_sock_opts(fd, acptr); send(fd, zlinebuf, strlen(zlinebuf), 0); @@ -1225,7 +1223,7 @@ add_con_refuse: ircsprintf(zlinebuf, "ERROR :Closing Link: [%s] (You are not welcome on " "this server: %s. Email %s for more information.)\r\n", - inetntoa((char *)&acptr->ip), + Inet_ia2p(&acptr->ip), bconf->reason ? bconf->reason : "no reason", KLINE_ADDRESS); set_non_blocking(fd, acptr); @@ -1241,6 +1239,22 @@ add_con_refuse: send(fd, zlinebuf, strlen(zlinebuf), 0); goto add_con_refuse; } +#ifdef THROTTLING + else if (!throttle_can_connect(&acptr->ip)) + { + ircsprintf(zlinebuf, + "ERROR :Closing Link: [%s] (Throttling: Reconnecting too fast) -" + "Email %s for more information.)\r\n", + Inet_ia2p(&acptr->ip), + KLINE_ADDRESS); + set_non_blocking(fd, acptr); + set_sock_opts(fd, acptr); + send(fd, zlinebuf, strlen(zlinebuf), 0); + goto add_con_refuse; + } + else + add_throttling_bucket(&acptr->ip); +#endif acptr->port = ntohs(addr.SIN_PORT); } @@ -1856,7 +1870,7 @@ deadsocket: ) length = read_packet(cptr, &read_set); #ifdef USE_SSL - if ((cptr->ssl != NULL) && + if ((length != FLUSH_BUFFER) && (cptr->ssl != NULL) && (IsSSLAcceptHandshake(cptr) || IsSSLConnectHandshake(cptr)) && FD_ISSET(cptr->fd, &read_set)) { diff --git a/src/s_conf.c b/src/s_conf.c index 3b8c9c780..459ce160f 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -49,6 +49,7 @@ #ifdef _WIN32 #undef GLOBH #endif +#include "badwords.h" #define ircstrdup(x,y) if (x) MyFree(x); if (!y) x = NULL; else x = strdup(y) #define ircfree(x) if (x) MyFree(x); x = NULL @@ -296,6 +297,7 @@ struct { */ void ipport_seperate(char *string, char **ip, char **port); +void port_range(char *string, int *start, int *end); long config_checkval(char *value, unsigned short flags); /* @@ -320,6 +322,8 @@ extern void win_log(char *format, ...); extern void win_error(); #endif +extern void add_entropy_configfile(struct stat st, char *buf); + /* * Config parser (IRCd) */ @@ -365,45 +369,80 @@ ConfigFile *conf = NULL; int config_error_flag = 0; int config_verbose = 0; -/* -*/ -void ipport_seperate(char *string, char **ip, char **port) +/* Pick out the ip address and the port number from a string. + * The string syntax is: ip:port. ip must be enclosed in brackets ([]) if its an ipv6 + * address because they contain colon (:) separators. The ip part is optional. If the string + * contains a single number its assumed to be a port number. + * + * Returns with ip pointing to the ip address (if one was specified), a "*" (if only a port + * was specified), or an empty string if there was an error. port is returned pointing to the + * port number if one was specified, otherwise it points to a empty string. + */ +void ipport_seperate(char *string, char **ip, char **port) { char *f; + + /* assume failure */ + *ip = *port = ""; - if (*string == '[') + /* sanity check */ + if (string && strlen(string) > 0) { - f = strrchr(string, ':'); - if (f) - { - *f = '\0'; - } - else - { - *ip = NULL; - *port = NULL; - } - - *port = (f + 1); - f = strrchr(string, ']'); - if (f) *f = '\0'; - *ip = (*string == '[' ? (string + 1) : string); - - } - else if (strchr(string, ':')) - { - *ip = strtok(string, ":"); - *port = strtok(NULL, ""); - } - else if (!strcmp(string, my_itoa(atoi(string)))) - { - *ip = "*"; - *port = string; + /* handle ipv6 type of ip address */ + if (*string == '[') + { + if ((f = strrchr(string, ']'))) + { + *ip = string + 1; /* skip [ */ + *f = '\0'; /* terminate the ip string */ + /* next char must be a : if a port was specified */ + if (*++f == ':') + { + *port = ++f; + } + } + } + /* handle ipv4 and port */ + else if ((f = strchr(string, ':'))) + { + /* we found a colon... we may have ip:port or just :port */ + if (f == string) + { + /* we have just :port */ + *ip = "*"; + } + else + { + /* we have ip:port */ + *ip = string; + *f = '\0'; + } + *port = ++f; + } + /* no ip was specified, just a port number */ + else if (!strcmp(string, my_itoa(atoi(string)))) + { + *ip = "*"; + *port = string; + } } } - +void port_range(char *string, int *start, int *end) +{ + char *c = strchr(string, '-'); + if (!c) + { + int tmp = atoi(string); + *start = tmp; + *end = tmp; + return; + } + *c = '\0'; + *start = atoi(string); + *end = atoi((c+1)); +} long config_checkval(char *value, unsigned short flags) { char *text; @@ -493,7 +532,8 @@ tolower(*(text+1)) == 'n') || *text == '1' || tolower(*text) == 't') { break; } ret += atoi(sz+1)*mfactor; - + if (*text == '\0') + break; } } mfactor = 1; @@ -561,6 +601,7 @@ ConfigFile *config_load(char *filename) /* Just me or could this cause memory corrupted when ret <0 ? */ buf[ret] = '\0'; close(fd); + add_entropy_configfile(sb, buf); cfptr = config_parse(filename, buf); free(buf); return cfptr; @@ -946,7 +987,7 @@ void config_progress(char *format, ...) ConfigCommand *config_binary_search(char *cmd) { int start = 0; - int stop = sizeof(_ConfigCommands)/sizeof(_ConfigCommands[0]); + int stop = sizeof(_ConfigCommands)/sizeof(_ConfigCommands[0])-1; int mid; while (start <= stop) { mid = (start+stop)/2; @@ -969,6 +1010,7 @@ void free_iConf(aConfiguration *i) ircfree(i->auto_join_chans); ircfree(i->oper_auto_join_chans); ircfree(i->oper_only_stats); + ircfree(i->oper_snomask); ircfree(i->egd_path); ircfree(i->static_quit); #ifdef USE_SSL @@ -992,8 +1034,12 @@ void free_iConf(aConfiguration *i) ircfree(i->network.x_stats_server); } +int config_test(); + int init_conf(char *rootconf, int rehash) { + ConfigItem_include *inc, *next; + config_status("Loading IRCd configuration .."); if (conf) { @@ -1014,6 +1060,15 @@ int init_conf(char *rootconf, int rehash) #ifndef STATIC_LINKING Unload_all_testing_modules(); #endif + for (inc = conf_include; inc; inc = next) + { + next = (ConfigItem_include *)inc->next; + if (inc->flag.type != INCLUDE_NOTLOADED) + continue; + ircfree(inc->file); + DelListItem(inc, conf_include); + MyFree(inc); + } config_free(conf); conf = NULL; free_iConf(&tempiConf); @@ -1028,6 +1083,16 @@ int init_conf(char *rootconf, int rehash) #else RunHook0(HOOKTYPE_REHASH); #endif + for (inc = conf_include; inc; inc = next) + { + next = (ConfigItem_include *)inc->next; + if (inc->flag.type == INCLUDE_NOTLOADED) + continue; + ircfree(inc->file); + DelListItem(inc, conf_include); + MyFree(inc); + } + } #ifndef STATIC_LINKING Init_all_testing_modules(); @@ -1040,6 +1105,11 @@ int init_conf(char *rootconf, int rehash) l_commands_Init(&ModCoreInfo); } #endif + for (inc = conf_include; inc; inc = (ConfigItem_include *)inc->next) + { + if (inc->flag.type == INCLUDE_NOTLOADED) + inc->flag.type = 0; + } if (config_run() < 0) { config_error("Bad case of config errors. Server will now die. This really shouldn't happen"); @@ -1053,6 +1123,15 @@ int init_conf(char *rootconf, int rehash) } else { + for (inc = conf_include; inc; inc = next) + { + next = (ConfigItem_include *)inc->next; + if (inc->flag.type != INCLUDE_NOTLOADED) + continue; + ircfree(inc->file); + DelListItem(inc, conf_include); + MyFree(inc); + } config_error("IRCd configuration failed to load"); config_free(conf); conf = NULL; @@ -1078,6 +1157,7 @@ int load_conf(char *filename) ConfigFile *cfptr, *cfptr2, **cfptr3; ConfigEntry *ce; int ret; + ConfigItem_include *includes; if (config_verbose > 0) config_status("Loading config file %s ..", filename); @@ -1106,7 +1186,20 @@ int load_conf(char *filename) if (ret < 0) return ret; } - return 1; + if (stricmp(filename, CPATH)) { + for (includes = conf_include; includes; includes = (ConfigItem_include *)includes->next) { + if (includes->flag.type == INCLUDE_NOTLOADED && + !stricmp(includes->file, filename)) + break; + } + if (!includes) { + includes = MyMalloc(sizeof(ConfigItem_include)); + includes->file = strdup(filename); + includes->flag.type = INCLUDE_NOTLOADED; + AddListItem(includes, conf_include); + } + } + return 1; } else { @@ -1286,7 +1379,9 @@ void config_rehash() badword_ptr = (ConfigItem_badword *) next) { next = (ListStruct *)badword_ptr->next; ircfree(badword_ptr->word); + if (badword_ptr->replace) ircfree(badword_ptr->replace); + regfree(&badword_ptr->expr); DelListItem(badword_ptr, conf_badword_channel); MyFree(badword_ptr); } @@ -1294,7 +1389,9 @@ void config_rehash() badword_ptr = (ConfigItem_badword *) next) { next = (ListStruct *)badword_ptr->next; ircfree(badword_ptr->word); + if (badword_ptr->replace) ircfree(badword_ptr->replace); + regfree(&badword_ptr->expr); DelListItem(badword_ptr, conf_badword_message); MyFree(badword_ptr); } @@ -1379,13 +1476,6 @@ void config_rehash() DelListItem(alias_ptr, conf_alias); MyFree(alias_ptr); } - for (include_ptr = conf_include; include_ptr; include_ptr = (ConfigItem_include *)next) - { - next = (ListStruct *)include_ptr->next; - ircfree(include_ptr->file); - DelListItem(include_ptr, conf_include); - MyFree(include_ptr); - } for (help_ptr = conf_help; help_ptr; help_ptr = (ConfigItem_help *)next) { aMotd *text; next = (ListStruct *)help_ptr->next; @@ -1508,10 +1598,11 @@ int config_run() OperFlag *config_binary_flags_search(OperFlag *table, char *cmd, int size) { int start = 0; - int stop = size; + int stop = size-1; int mid; while (start <= stop) { mid = (start+stop)/2; + if (smycmp(cmd,table[mid].name) < 0) { stop = mid-1; } @@ -1931,6 +2022,26 @@ void init_dynconf(void) bzero(&tempiConf, sizeof(iConf)); } +char *pretty_time_val(long timeval) +{ + static char buf[512]; + + if (timeval == 0) + return "0"; + + buf[0] = 0; + + if (timeval/86400) + sprintf(buf, "%d day%s ", timeval/86400, timeval/86400 != 1 ? "s" : ""); + if ((timeval/3600) % 24) + sprintf(buf, "%s%d hour%s ", buf, (timeval/3600)%24, (timeval/3600)%24 != 1 ? "s" : ""); + if ((timeval/60)%60) + sprintf(buf, "%s%d minute%s ", buf, (timeval/60)%60, (timeval/60)%60 != 1 ? "s" : ""); + if ((timeval%60)) + sprintf(buf, "%s%d second%s", buf, timeval%60, timeval%60 != 1 ? "s" : ""); + return buf; +} + /* Report the unrealircd.conf info -codemastr*/ void report_dynconf(aClient *sptr) { @@ -1940,11 +2051,15 @@ void report_dynconf(aClient *sptr) sptr->name, KLINE_ADDRESS); sendto_one(sptr, ":%s %i %s :modes-on-connect: %s", me.name, RPL_TEXT, sptr->name, get_modestr(CONN_MODES)); + sendto_one(sptr, ":%s %i %s :modes-on-oper: %s", me.name, RPL_TEXT, + sptr->name, get_modestr(OPER_MODES)); + sendto_one(sptr, ":%s %i %s :snomask-on-oper: %s", me.name, RPL_TEXT, + sptr->name, OPER_SNOMASK ? OPER_SNOMASK : SNO_DEFOPER); if (OPER_ONLY_STATS) sendto_one(sptr, ":%s %i %s :oper-only-stats: %s", me.name, RPL_TEXT, sptr->name, OPER_ONLY_STATS); - sendto_one(sptr, ":%s %i %s :anti-spam-quit-message-time: %d", me.name, RPL_TEXT, - sptr->name, ANTI_SPAM_QUIT_MSG_TIME); + sendto_one(sptr, ":%s %i %s :anti-spam-quit-message-time: %s", me.name, RPL_TEXT, + sptr->name, pretty_time_val(ANTI_SPAM_QUIT_MSG_TIME)); #ifdef USE_SSL sendto_one(sptr, ":%s %i %s :ssl::egd: %s", me.name, RPL_TEXT, sptr->name, EGD_PATH ? EGD_PATH : (USE_EGD ? "1" : "0")); @@ -1982,8 +2097,8 @@ void report_dynconf(aClient *sptr) RPL_TEXT, sptr->name, OPER_AUTO_JOIN_CHANS ? OPER_AUTO_JOIN_CHANS : "0"); sendto_one(sptr, ":%s %i %s :static-quit: %s", me.name, RPL_TEXT, sptr->name, STATIC_QUIT ? STATIC_QUIT : ""); - sendto_one(sptr, ":%s %i %s :dns::timeout: %li", me.name, RPL_TEXT, - sptr->name, HOST_TIMEOUT); + sendto_one(sptr, ":%s %i %s :dns::timeout: %s", me.name, RPL_TEXT, + sptr->name, pretty_time_val(HOST_TIMEOUT)); sendto_one(sptr, ":%s %i %s :dns::retries: %d", me.name, RPL_TEXT, sptr->name, HOST_RETRIES); sendto_one(sptr, ":%s %i %s :dns::nameserver: %s", me.name, RPL_TEXT, @@ -2083,12 +2198,11 @@ int _conf_include(ConfigFile *conf, ConfigEntry *ce) cSlash--; *(cSlash+1)=0; } - hFind = FindFirstFile(ce->ce_vardata, &FindData); - if (!FindData.cFileName) { + if ( (hFind = FindFirstFile(ce->ce_vardata, &FindData)) == INVALID_HANDLE_VALUE ) + { config_status("%s:%i: include %s: invalid file given", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_vardata); - FindClose(hFind); return -1; } if (cPath) { @@ -2514,6 +2628,12 @@ int _test_oper(ConfigFile *conf, ConfigEntry *ce) ce->ce_varlinenum); errors++; } + if (!config_find_entry(ce->ce_entries, "flags")) + { + config_error("%s:%i: oper::flags missing", ce->ce_fileptr->cf_filename, + ce->ce_varlinenum); + errors++; + } if (!config_find_entry(ce->ce_entries, "class")) { config_error("%s:%i: oper::class missing", ce->ce_fileptr->cf_filename, @@ -2601,12 +2721,15 @@ int _test_class(ConfigFile *conf, ConfigEntry *ce) } if ((cep = config_find_entry(ce->ce_entries, "pingfreq"))) { - l = atol(cep->ce_vardata); - if (l < 1) + if (cep->ce_vardata) { - config_error("%s:%i: class::pingfreq with illegal value", - cep->ce_fileptr->cf_filename, cep->ce_varlinenum); - errors++; + l = atol(cep->ce_vardata); + if (l < 1) + { + config_error("%s:%i: class::pingfreq with illegal value", + cep->ce_fileptr->cf_filename, cep->ce_varlinenum); + errors++; + } } } else @@ -2617,12 +2740,15 @@ int _test_class(ConfigFile *conf, ConfigEntry *ce) } if ((cep = config_find_entry(ce->ce_entries, "maxclients"))) { - l = atol(cep->ce_vardata); - if (!l) + if (cep->ce_vardata) { - config_error("%s:%i: class::maxclients with illegal value", - cep->ce_fileptr->cf_filename, cep->ce_varlinenum); - errors++; + l = atol(cep->ce_vardata); + if (!l) + { + config_error("%s:%i: class::maxclients with illegal value", + cep->ce_fileptr->cf_filename, cep->ce_varlinenum); + errors++; + } } } else @@ -2633,12 +2759,15 @@ int _test_class(ConfigFile *conf, ConfigEntry *ce) } if ((cep = config_find_entry(ce->ce_entries, "sendq"))) { - l = atol(cep->ce_vardata); - if (!l) - { - config_error("%s:%i: class::sendq with illegal value", - cep->ce_fileptr->cf_filename, cep->ce_varlinenum); - errors++; + if (cep->ce_vardata) + { + l = atol(cep->ce_vardata); + if (!l) + { + config_error("%s:%i: class::sendq with illegal value", + cep->ce_fileptr->cf_filename, cep->ce_varlinenum); + errors++; + } } } else @@ -2649,12 +2778,15 @@ int _test_class(ConfigFile *conf, ConfigEntry *ce) } if ((cep = config_find_entry(ce->ce_entries, "connfreq"))) { - l = atol(cep->ce_vardata); - if (l < 10) + if (cep->ce_vardata) { - config_error("%s:%i: class::connfreq with illegal value (<10)", - cep->ce_fileptr->cf_filename, cep->ce_varlinenum); - errors++; + l = atol(cep->ce_vardata); + if (l < 10) + { + config_error("%s:%i: class::connfreq with illegal value (<10)", + cep->ce_fileptr->cf_filename, cep->ce_varlinenum); + errors++; + } } } @@ -2846,15 +2978,18 @@ int _test_tld(ConfigFile *conf, ConfigEntry *ce) } else { - if (((fd = open(cep->ce_vardata, O_RDONLY)) == -1)) + if (cep->ce_vardata) { - config_error("%s:%i: tld::motd: %s: %s", - cep->ce_fileptr->cf_filename, cep->ce_varlinenum, - cep->ce_vardata, strerror(errno)); - errors++; + if (((fd = open(cep->ce_vardata, O_RDONLY)) == -1)) + { + config_error("%s:%i: tld::motd: %s: %s", + cep->ce_fileptr->cf_filename, cep->ce_varlinenum, + cep->ce_vardata, strerror(errno)); + errors++; + } + else + close(fd); } - else - close(fd); } @@ -2866,15 +3001,18 @@ int _test_tld(ConfigFile *conf, ConfigEntry *ce) } else { - if (((fd = open(cep->ce_vardata, O_RDONLY)) == -1)) + if (cep->ce_vardata) { - config_error("%s:%i: tld::rules: %s: %s", - cep->ce_fileptr->cf_filename, cep->ce_varlinenum, - cep->ce_vardata, strerror(errno)); - errors++; + if (((fd = open(cep->ce_vardata, O_RDONLY)) == -1)) + { + config_error("%s:%i: tld::rules: %s: %s", + cep->ce_fileptr->cf_filename, cep->ce_varlinenum, + cep->ce_vardata, strerror(errno)); + errors++; + } + else + close(fd); } - else - close(fd); } return errors; @@ -2889,7 +3027,8 @@ int _conf_listen(ConfigFile *conf, ConfigEntry *ce) char copy[256]; char *ip; char *port; - int iport; + int start, end, iport; + int tmpflags =0; unsigned char isnew = 0; if (!ce->ce_vardata) @@ -2912,31 +3051,12 @@ int _conf_listen(ConfigFile *conf, ConfigEntry *ce) { return -1; } - iport = atol(port); - if ((iport < 0) || (iport > 65535)) + port_range(port, &start, &end); + if ((start < 0) || (start > 65535) || (end < 0) || (end > 65535)) { return -1; } - if (!(listen = Find_listen(ip, iport))) - { - listen = MyMallocEx(sizeof(ConfigItem_listen)); - listen->ip = strdup(ip); - listen->port = iport; - isnew = 1; - } - else - { - isnew = 0; - } - - if (listen->options & LISTENER_BOUND) - { - listen->options = 0; - listen->options |= LISTENER_BOUND; - } - else - listen->options = 0; - + end++; for (cep = ce->ce_entries; cep; cep = cep->ce_next) { if (!strcmp(cep->ce_varname, "options")) @@ -2944,24 +3064,42 @@ int _conf_listen(ConfigFile *conf, ConfigEntry *ce) for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next) { if ((ofp = config_binary_flags_search(_ListenerFlags, cepp->ce_varname, sizeof(_ListenerFlags)/sizeof(_ListenerFlags[0])))) - listen->options |= ofp->flag; + tmpflags |= ofp->flag; } #ifndef USE_SSL - if (listen->options & LISTENER_SSL) + if (tmpflags & LISTENER_SSL) { config_status("%s:%i: listen with SSL flag enabled on a non SSL compile", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, - cep->ce_varname); - listen->options &= ~LISTENER_SSL; + cep->ce_varname); + tmpflags &= ~LISTENER_SSL; } #endif } - } - if (isnew) - AddListItem(listen, conf_listen); - listen->flag.temporary = 0; + + for (iport = start; iport < end; iport++) + { + + if (!(listen = Find_listen(ip, iport))) + { + listen = MyMallocEx(sizeof(ConfigItem_listen)); + listen->ip = strdup(ip); + listen->port = iport; + isnew = 1; + } + else + isnew = 0; + + if (listen->options & LISTENER_BOUND) + tmpflags |= LISTENER_BOUND; + + listen->options = tmpflags; + if (isnew) + AddListItem(listen, conf_listen); + listen->flag.temporary = 0; + } return 1; } @@ -2974,7 +3112,7 @@ int _test_listen(ConfigFile *conf, ConfigEntry *ce) char copy[256]; char *ip; char *port; - int iport; + int start, end; int errors = 0; if (!ce->ce_vardata) @@ -3005,12 +3143,30 @@ int _test_listen(ConfigFile *conf, ConfigEntry *ce) ce->ce_fileptr->cf_filename, ce->ce_varlinenum); return 1; } - iport = atol(port); - if ((iport < 0) || (iport > 65535)) + port_range(port, &start, &end); + if (start == end) { - config_error("%s:%i: listen: illegal port (must be 0..65536)", - ce->ce_fileptr->cf_filename, ce->ce_varlinenum); - return 1; + if ((start < 0) || (start > 65535)) + { + config_error("%s:%i: listen: illegal port (must be 0..65535)", + ce->ce_fileptr->cf_filename, ce->ce_varlinenum); + return 1; + } + } + else + { + if (end < start) + { + config_error("%s:%i: listen: illegal port range end value is less than starting value", + ce->ce_fileptr->cf_filename, ce->ce_varlinenum); + return 1; + } + if ((start < 0) || (start > 65535) || (end < 0) || (end > 65535)) + { + config_error("%s:%i: listen: illegal port range values must be between 0 and 65535", + ce->ce_fileptr->cf_filename, ce->ce_varlinenum); + return 1; + } } for (cep = ce->ce_entries; cep; cep = cep->ce_next) { @@ -3295,10 +3451,7 @@ int _test_allow(ConfigFile *conf, ConfigEntry *ce) if (Auth_CheckError(cep) < 0) errors++; } - if ((cep = config_find_entry(ce->ce_entries, "class"))) - { - } - else + if (!(cep = config_find_entry(ce->ce_entries, "class"))) { config_error("%s:%i: allow::class missing", ce->ce_fileptr->cf_filename, @@ -3307,11 +3460,14 @@ int _test_allow(ConfigFile *conf, ConfigEntry *ce) } if ((cep = config_find_entry(ce->ce_entries, "maxperip"))) { - if (atoi(cep->ce_vardata) <= 0) + if (cep->ce_vardata) { - config_error("%s:%i: allow::maxperip with illegal value (must be >0)", - cep->ce_fileptr->cf_filename, cep->ce_varlinenum); - errors++; + if (atoi(cep->ce_vardata) <= 0) + { + config_error("%s:%i: allow::maxperip with illegal value (must be >0)", + cep->ce_fileptr->cf_filename, cep->ce_varlinenum); + errors++; + } } } if ((cep = config_find_entry(ce->ce_entries, "options"))) @@ -3819,9 +3975,15 @@ int _conf_badword(ConfigFile *conf, ConfigEntry *ce) ca->word = MyMalloc(strlen(cep->ce_vardata) + strlen(PATTERN) -1); ircsprintf(ca->word, PATTERN, cep->ce_vardata); } + /* Yes this is called twice, once in test, and once here, but it is still MUCH + faster than calling it each time a message is received like before. -- codemastr + */ + regcomp(&ca->expr, ca->word, REG_ICASE); if ((cep = config_find_entry(ce->ce_entries, "replace"))) { ircstrdup(ca->replace, cep->ce_vardata); } + else + ca->replace = NULL; if (!strcmp(ce->ce_vardata, "channel")) AddListItem(ca, conf_badword_channel); else if (!strcmp(ce->ce_vardata, "message")) @@ -3833,6 +3995,7 @@ int _conf_badword(ConfigFile *conf, ConfigEntry *ce) int _test_badword(ConfigFile *conf, ConfigEntry *ce) { int errors = 0; ConfigEntry *word, *replace, *cep; + regex_t expr; if (!ce->ce_entries) { config_error("%s:%i: empty badword block", @@ -3863,7 +4026,44 @@ int _test_badword(ConfigFile *conf, ConfigEntry *ce) { config_error("%s:%i: badword::word without contents", word->ce_fileptr->cf_filename, word->ce_varlinenum); errors++; - } + } + else + { + + int errorcode, errorbufsize, regex=0; + char *errorbuf, *tmp, *tmpbuf=NULL; + for (tmp = word->ce_vardata; *tmp; tmp++) { + if ((int)*tmp < 65 || (int)*tmp > 123) { + regex = 1; + break; + } + } + if (regex) + errorcode = regcomp(&expr, word->ce_vardata, REG_ICASE); + else + { + tmpbuf = malloc(strlen(word->ce_vardata) + + strlen(PATTERN) -1); + ircsprintf(tmpbuf, PATTERN, word->ce_vardata); + errorcode = regcomp(&expr, tmpbuf, REG_ICASE); + } + if (errorcode > 0) + { + errorbufsize = regerror(errorcode, &expr, NULL, 0)+1; + errorbuf = malloc(errorbufsize); + regerror(errorcode, &expr, errorbuf, errorbufsize); + config_error("%s:%i: badword::%s contains an invalid regex: %s", + word->ce_fileptr->cf_filename, + word->ce_varlinenum, + word->ce_varname, errorbuf); + errors++; + free(errorbuf); + } + if (!regex) + free(tmpbuf); + regfree(&expr); + } + } if ((replace = config_find_entry(ce->ce_entries, "replace"))) { @@ -4043,6 +4243,7 @@ int _test_log(ConfigFile *conf, ConfigEntry *ce) { config_error("%s:%i: unknown log flag '%s'", cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum, cepp->ce_varname); + errors++; } } @@ -4180,6 +4381,15 @@ int _test_link(ConfigFile *conf, ConfigEntry *ce) if (Auth_CheckError(cep) < 0) errors++; } + if ((cep = config_find_entry(ce->ce_entries, "password-connect"))) + { + if (cep->ce_entries) + { + config_error("%s:%i: link::password-connect can not be encrypted", + ce->ce_fileptr->cf_filename, ce->ce_varlinenum); + errors++; + } + } if (errors > 0) return errors; for (cep = ce->ce_entries; cep; cep = cep->ce_next) @@ -4380,6 +4590,9 @@ int _conf_set(ConfigFile *conf, ConfigEntry *ce) else if (!strcmp(cep->ce_varname, "modes-on-oper")) { tempiConf.oper_modes = (long) set_usermode(cep->ce_vardata); } + else if (!strcmp(cep->ce_varname, "snomask-on-oper")) { + ircstrdup(tempiConf.oper_snomask, cep->ce_vardata); + } else if (!strcmp(cep->ce_varname, "static-quit")) { ircstrdup(tempiConf.static_quit, cep->ce_vardata); } @@ -4614,6 +4827,9 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce) CheckNull(cep); templong = (long) set_usermode(cep->ce_vardata); } + else if (!strcmp(cep->ce_varname, "snomask-on-oper")) { + CheckNull(cep); + } else if (!strcmp(cep->ce_varname, "static-quit")) { CheckNull(cep); } diff --git a/src/s_extra.c b/src/s_extra.c index e7e807be1..0d68fe54e 100644 --- a/src/s_extra.c +++ b/src/s_extra.c @@ -365,7 +365,7 @@ void ircd_log(int flags, char *format, ...) #endif if (fd == -1) continue; - write(fd, "Max file size reached, starting new log file\n", 46); + write(fd, "Max file size reached, starting new log file\n", 45); } else { #ifndef _WIN32 diff --git a/src/s_kline.c b/src/s_kline.c index a8e9c6a1c..eb694559c 100644 --- a/src/s_kline.c +++ b/src/s_kline.c @@ -361,7 +361,7 @@ int find_tkline_match_zap(aClient *cptr) inetntoa((char *)&cptr->ip), lp->reason); #else inet_ntop(AF_INET6, (char *)&cptr->ip, - mydummy, MYDUMMY_SIZE)); + mydummy, MYDUMMY_SIZE), lp->reason); #endif strlcpy(zlinebuf, msge, sizeof zlinebuf); return (1); diff --git a/src/s_serv.c b/src/s_serv.c index 29b34fe33..5d16e549e 100644 --- a/src/s_serv.c +++ b/src/s_serv.c @@ -1454,33 +1454,31 @@ void m_info_send(aClient *sptr) me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :| * codemastr ", me.name, RPL_INFO, sptr->name); - sendto_one(sptr, ":%s %d %s :| * Griever ", - me.name, RPL_INFO, sptr->name); - sendto_one(sptr, ":%s %d %s :| * nighthawk ", - me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :| * Luke ", me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :| * McSkaf ", me.name, RPL_INFO, sptr->name); - sendto_one(sptr, ":%s %d %s :|", me.name, RPL_INFO, sptr->name); - sendto_one(sptr, ":%s %d %s :| Coder team:", me.name, RPL_INFO, sptr->name); - sendto_one(sptr, ":%s %d %s :|", me.name, RPL_INFO, sptr->name); - sendto_one(sptr, ":%s %d %s :| * Zogg ", - me.name, RPL_INFO, sptr->name); - sendto_one(sptr, ":%s %d %s :| * NiQuiL ", - me.name, RPL_INFO, sptr->name); - sendto_one(sptr, ":%s %d %s :| * assyrian ", - me.name, RPL_INFO, sptr->name); - sendto_one(sptr, ":%s %d %s :| * chasm ", + sendto_one(sptr, ":%s %d %s :| * Syzop ", me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :|", me.name, RPL_INFO, sptr->name); - sendto_one(sptr, ":%s %d %s :| Previous versions:", - me.name, RPL_INFO, sptr->name); + sendto_one(sptr, ":%s %d %s :| Contributors:", me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :|", me.name, RPL_INFO, sptr->name); + sendto_one(sptr, ":%s %d %s :| * Zogg ", + me.name, RPL_INFO, sptr->name); + sendto_one(sptr, ":%s %d %s :| * NiQuiL ", + me.name, RPL_INFO, sptr->name); + sendto_one(sptr, ":%s %d %s :| * assyrian ", + me.name, RPL_INFO, sptr->name); + sendto_one(sptr, ":%s %d %s :| * chasm ", + me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :| * DrBin ", me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :| * llthangel ", me.name, RPL_INFO, sptr->name); + sendto_one(sptr, ":%s %d %s :| * Griever ", + me.name, RPL_INFO, sptr->name); + sendto_one(sptr, ":%s %d %s :| * nighthawk ", + me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :|", me.name, RPL_INFO, sptr->name); sendto_one(sptr, ":%s %d %s :| Credits - Type /Credits", me.name, RPL_INFO, sptr->name); @@ -2615,6 +2613,8 @@ CMD_FUNC(m_help) } if (message[0] == '!') message++; + if (BadPtr(message)) + return 0; sendto_serv_butone_token(IsServer(cptr) ? cptr : NULL, parv[0], MSG_HELP, TOK_HELP, "%s", message); sendto_umode(UMODE_HELPOP, "*** HelpOp -- from %s (HelpOp): %s", @@ -2638,6 +2638,8 @@ CMD_FUNC(m_help) if (parse_help(sptr, parv[0], message)) return 0; } + if (BadPtr(message)) + return 0; s = make_nick_user_host(cptr->name, cptr->user->username, cptr->user->realhost); for (tmpl = helpign; tmpl; tmpl = tmpl->next) @@ -2656,6 +2658,8 @@ CMD_FUNC(m_help) } else { + if (BadPtr(message)) + return 0; sendto_serv_butone_token(IsServer(cptr) ? cptr : NULL, parv[0], MSG_HELP, TOK_HELP, "%s", message); sendto_umode(UMODE_HELPOP, "*** HelpOp -- from %s: %s", parv[0], diff --git a/src/s_user.c b/src/s_user.c index 1a80e1757..f4abcc624 100644 --- a/src/s_user.c +++ b/src/s_user.c @@ -56,6 +56,7 @@ void send_umode_out(aClient *, aClient *, long); void send_umode_out_nickv2(aClient *, aClient *, long); void send_umode(aClient *, aClient *, long, long, char *); void set_snomask(aClient *, char *); +int create_snomask(char *, int); /* static Link *is_banned(aClient *, aChannel *); */ int dontspread = 0; extern char *me_hash; @@ -228,6 +229,54 @@ unsigned char *StripColors(unsigned char *text) { return new_str; } +/* strip color, bold, underline, and reverse codes from a string */ +const char *StripControlCodes(unsigned char *text) +{ + int nc = 0, col = 0, i = 0, len = strlen(text); + static unsigned char new_str[4096]; + while (len > 0) + { + if ( col && ((isdigit(*text) && nc < 2) || (*text == ',' && nc < 3))) + { + nc++; + if (*text == ',') + nc = 0; + } + else + { + if (col) + col = 0; + switch (*text) + { + case 3: + /* color */ + col = 1; + nc = 0; + break; + case 2: + /* bold */ + break; + case 31: + /* underline */ + break; + case 22: + /* reverse */ + break; + case 15: + /* plain */ + break; + default: + new_str[i] = *text; + i++; + break; + } + } + text++; + len--; + } + new_str[i] = 0; + return new_str; +} char umodestring[UMODETABLESZ+1]; @@ -1664,13 +1713,7 @@ CMD_FUNC(m_nick) * * Generate a random string for them to pong with. */ -#ifndef _WIN32 - sptr->nospoof = - 1 + (int)(9000000.0 * random() / (RAND_MAX + 80000000.0)); -#else - sptr->nospoof = - 1 + (int)(9000000.0 * rand() / (RAND_MAX + 80000000.0)); -#endif + sptr->nospoof = getrandom32(); sendto_one(sptr, ":%s NOTICE %s :*** If you are having problems" " connecting due to ping timeouts, please" " type /quote pong %X or /raw pong %X now.", @@ -1800,6 +1843,22 @@ char *get_modestr(long umodes) return buf; } +char *get_snostr(long sno) { + int flag; + int *s; + char *m; + + m = buf; + + *m++ = '+'; + for (s = sno_mask; (flag = *s) && (m - buf < BUFSIZE - 4); s += 2) + if (sno & flag) + *m++ = (char)(*(s + 1)); + *m = 0; + return buf; +} + + /* ** m_user ** parv[0] = sender prefix @@ -2111,6 +2170,39 @@ void set_snomask(aClient *sptr, char *snomask) { } } +int create_snomask(char *snomask, int oper) { + int what = MODE_ADD; + char *p; + int *s, flag, sno = 0; + + if (snomask == NULL) + return sno; + + for (p = snomask; p && *p; p++) { + switch (*p) { + case '+': + what = MODE_ADD; + break; + case '-': + what = MODE_DEL; + break; + default: + for (s = sno_mask; (flag = *s); s += 2) + if (*p == (char) (*(s + 1))) { + if (what == MODE_ADD) + sno |= flag; + else + sno &= ~flag; + } + + } + } + if (!oper) { + sno &= (SNO_NONOPERS); + } + return sno; +} + /* * m_umode() added 15/10/91 By Darren Reed. * parv[0] - sender @@ -2275,6 +2367,8 @@ CMD_FUNC(m_umode) ClearHideOper(sptr); if (IsCoAdmin(sptr)) ClearCoAdmin(sptr); + if (IsHelpOp(sptr)) + ClearHelpOp(sptr); if (sptr->user->snomask & SNO_CLIENT) sptr->user->snomask &= ~SNO_CLIENT; if (sptr->user->snomask & SNO_FCLIENT) diff --git a/src/win32/unrealinst.iss b/src/win32/unrealinst.iss index d9ef2cffd..4efcb1648 100644 --- a/src/win32/unrealinst.iss +++ b/src/win32/unrealinst.iss @@ -7,7 +7,7 @@ [Setup] AppName=UnrealIRCd -AppVerName=UnrealIRCd3.2-beta13 +AppVerName=UnrealIRCd3.2-beta14 AppPublisher=UnrealIRCd Team AppPublisherURL=http://www.unrealircd.com AppSupportURL=http://www.unrealircd.com