From 9170762c2e7dc3c06729f6d3c87d7087c7cde0b4 Mon Sep 17 00:00:00 2001 From: Michael Poole Date: Tue, 15 Jun 2004 01:20:36 +0000 Subject: [PATCH] Apply hikari's pluggable crypt mechanism patch git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@1077 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- ChangeLog | 42 ++++ include/ircd_crypt.h | 68 ++++++ include/ircd_crypt_native.h | 11 + include/ircd_crypt_plain.h | 29 +++ include/ircd_crypt_smd5.h | 27 +++ include/ircd_features.h | 1 + include/ircd_md5.h | 49 +++++ include/numeric.h | 2 +- include/umkpasswd.h | 44 ++++ ircd/Makefile.in | 48 +++-- ircd/ircd.c | 5 + ircd/ircd_crypt.c | 223 +++++++++++++++++++ ircd/ircd_crypt_native.c | 66 ++++++ ircd/ircd_crypt_plain.c | 65 ++++++ ircd/ircd_crypt_smd5.c | 207 ++++++++++++++++++ ircd/ircd_features.c | 1 + ircd/ircd_md5.c | 259 ++++++++++++++++++++++ ircd/m_info.c | 2 +- ircd/m_oper.c | 13 +- ircd/s_serv.c | 2 +- ircd/s_stats.c | 41 +++- ircd/umkpasswd.c | 417 ++++++++++++++++++++++++++++++++++++ ircd/version.c.SH | 55 +++-- 23 files changed, 1628 insertions(+), 49 deletions(-) create mode 100644 include/ircd_crypt.h create mode 100644 include/ircd_crypt_native.h create mode 100644 include/ircd_crypt_plain.h create mode 100644 include/ircd_crypt_smd5.h create mode 100644 include/ircd_md5.h create mode 100644 include/umkpasswd.h create mode 100644 ircd/ircd_crypt.c create mode 100644 ircd/ircd_crypt_native.c create mode 100644 ircd/ircd_crypt_plain.c create mode 100644 ircd/ircd_crypt_smd5.c create mode 100644 ircd/ircd_md5.c create mode 100644 ircd/umkpasswd.c diff --git a/ChangeLog b/ChangeLog index 2087ce6..3ad5b62 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,45 @@ +2002-11-11 hikari + * ircd/ircd.c: added call to irc_crypt_init() - someone hurry up and + modularise :P + + * ircd/ircd_xopen.c: removed, superseded by new crypto system. + + * ircd/ircd_crypt.c: wrote scary ircd_crypt() interface function, + wrote ircd_crypt_mech_register() function, various other bits + designed to create a near-pluggable crypto system for ircu. currently + this code also loads the various mechanisms i've written code for. + + * ircd/ircd_crypt_smd5.c: imported the crypt_md5 function from + elsewhere, manipulated to suit ircu, returns a salted MD5 password. + + * ircd/ircd_crypt_native.c: replaces the old ircd_xopen.c file, + generate a crypted password using the systems native crypt() function. + + * ircd/ircd_crypt_plain.c: plain text crypt mechanism, should really + only be used for testing purposes. + + * ircd/ircd_md5.c: main gubbins of the MD5 hashing code, lifted from + elsewhere, ircuified. + + * ircd/umkpasswd.c: mkpasswd program for ircu. + + * include/ircd_xopen.h: removed, superseded by new crypto system. + + * include/ircd_crypt.h: external definitions for the new ircd_crypt() + function and definition of the ircd_crypt_mech structure for containing + crypto mechanism data. + + * include/ircd_crypt_smd5.h: sundary definitions for the salted MD5 + mechanism. + + * include/ircd_crypt_native.h: sundary definitions for the native + crypt() mechanism. + + * include/ircd_crypt_plain.h: sundary definitions for the plain text + mechanism. + + * include/umkpasswd.h: fluff for umkpasswd. + 2003-03-11 Landon Fuller (landonf) * configure.in: allow ircu to build on OS X. diff --git a/include/ircd_crypt.h b/include/ircd_crypt.h new file mode 100644 index 0000000..f4c2fb6 --- /dev/null +++ b/include/ircd_crypt.h @@ -0,0 +1,68 @@ +/* + * IRC - Internet Relay Chat, include/ircd_crypt.h + * Copyright (C) 2002 hikari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ +#ifndef INCLUDED_ircd_crypt_h +#define INCLUDED_ircd_crypt_h + +/* forward planning for modularisation */ +struct crypt_mech_s { + char* mechname; /* name of the mechanism */ + char* shortname; /* short name of the module */ + char* description; /* description of the mechanism */ + + const char* (*crypt_function)(const char *, const char *); + /* pointer to the crypt function */ + + char* crypt_token; /* what identifies a password string + as belonging to this mechanism */ + + int crypt_token_size; /* how long is the token */ +}; + +typedef struct crypt_mech_s crypt_mech_t; + +struct crypt_mechs_s; +typedef struct crypt_mechs_s crypt_mechs_t; + +struct crypt_mechs_s { + crypt_mech_t* mech; + crypt_mechs_t* next; + crypt_mechs_t* prev; +}; + +/* access macros */ +#define MechName(x) x->mechname +#define ShortName(x) x->shortname +#define Description(x) x->description +#define CryptFunc(x) x->crypt_function +#define CryptTok(x) x->crypt_token +#define CryptTokSize(x) x->crypt_token_size + +/* exported functions */ +extern void ircd_crypt_init(void); +extern const char* ircd_crypt(const char* key, const char* salt); +extern int ircd_crypt_register_mech(crypt_mech_t* mechanism); +extern int ircd_crypt_unregister_mech(crypt_mech_t* mechanism); + +/* exported variables */ +extern crypt_mechs_t* crypt_mechs_root; + +#endif /* INCLUDED_ircd_crypt_h */ + diff --git a/include/ircd_crypt_native.h b/include/ircd_crypt_native.h new file mode 100644 index 0000000..8001b78 --- /dev/null +++ b/include/ircd_crypt_native.h @@ -0,0 +1,11 @@ +/* + * $Id$ + */ +#ifndef INCLUDED_ircd_crypt_native_h +#define INCLUDED_ircd_crypt_native_h + +extern const char* ircd_crypt_native(const char* key, const char* salt); +extern void ircd_register_crypt_native(void); + +#endif /* INCLUDED_ircd_crypt_native_h */ + diff --git a/include/ircd_crypt_plain.h b/include/ircd_crypt_plain.h new file mode 100644 index 0000000..6b9d580 --- /dev/null +++ b/include/ircd_crypt_plain.h @@ -0,0 +1,29 @@ +/* + * IRC - Internet Relay Chat, include/ircd_crypt_plain.h + * Copyright (C) 2002 hikari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ +#ifndef INCLUDED_ircd_crypt_plain_h +#define INCLUDED_ircd_crypt_plain_h + +extern const char* ircd_crypt_plain(const char* key, const char* salt); +extern void ircd_register_crypt_plain(void); + + +#endif /* INCLUDED_ircd_crypt_plain_h */ + diff --git a/include/ircd_crypt_smd5.h b/include/ircd_crypt_smd5.h new file mode 100644 index 0000000..9680f12 --- /dev/null +++ b/include/ircd_crypt_smd5.h @@ -0,0 +1,27 @@ +/* + * IRC - Internet Relay Chat, include/ircd_crypt_smd5.h + * Copyright (C) 2002 hikari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ +#ifndef INCLUDED_ircd_crypt_smd5_h +#define INCLUDED_ircd_crypt_smd5_h + +extern void ircd_register_crypt_smd5(void); + +#endif /* INCLUDED_ircd_crypt_smd5_h */ + diff --git a/include/ircd_features.h b/include/ircd_features.h index d6671ae..50ac4c4 100644 --- a/include/ircd_features.h +++ b/include/ircd_features.h @@ -104,6 +104,7 @@ enum Feature { FEAT_HIS_LINKS, FEAT_HIS_TRACE, FEAT_HIS_STATS_l, + FEAT_HIS_STATS_L, FEAT_HIS_STATS_c, FEAT_HIS_STATS_g, FEAT_HIS_STATS_h, diff --git a/include/ircd_md5.h b/include/ircd_md5.h new file mode 100644 index 0000000..69332dd --- /dev/null +++ b/include/ircd_md5.h @@ -0,0 +1,49 @@ +/* + * IRC - Internet Relay Chat, include/ircd_md5.h + * + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * ircuified 2002 by hikari + * + * $Id$ +*/ +#ifndef ircd_md5_h +#define ircd_md5_h + +#define MD5Name(x) Good##x + +typedef unsigned int uint32; + +struct MD5Context { + uint32 buf[4]; + uint32 bits[2]; + unsigned char in[64]; +}; + +void GoodMD5Init(struct MD5Context *); +void GoodMD5Update(struct MD5Context *, unsigned const char *, unsigned); +void GoodMD5Final(unsigned char digest[16], struct MD5Context *); +void GoodMD5Transform(uint32 buf[4], uint32 const in[16]); +void BrokenMD5Init(struct MD5Context *); +void BrokenMD5Update(struct MD5Context *, unsigned const char *, unsigned); +void BrokenMD5Final(unsigned char digest[16], struct MD5Context *); +void BrokenMD5Transform(uint32 buf[4], uint32 const in[16]); + +char *Goodcrypt_md5(const char *pw, const char *salt); +char *Brokencrypt_md5(const char *pw, const char *salt); + +/* + * This is needed to make RSAREF happy on some MS-DOS compilers. + */ + +typedef struct MD5Context MD5_CTX; + +#endif /* ircd_md5_h */ diff --git a/include/numeric.h b/include/numeric.h index 24ef24b..c2f8d44 100644 --- a/include/numeric.h +++ b/include/numeric.h @@ -127,7 +127,7 @@ extern const struct Numeric* get_error_numeric(int err); /* RPL_STATSIAUTH 239 IRCnet extension */ /* RPL_STATSVLINE 240 IRCnet extension */ /* RPL_STATSXLINE 240 austnet */ -#define RPL_STATSLLINE 241 +#define RPL_STATSLLINE 241 /* Undernet dynamicly loaded modules */ #define RPL_STATSUPTIME 242 #define RPL_STATSOLINE 243 #define RPL_STATSHLINE 244 diff --git a/include/umkpasswd.h b/include/umkpasswd.h new file mode 100644 index 0000000..6faaa56 --- /dev/null +++ b/include/umkpasswd.h @@ -0,0 +1,44 @@ +/* + * IRC - Internet Relay Chat, include/umkpasswd.h + * Copyright (C) 2002 hikari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ +#ifndef INCLUDED_umkpasswd_h +#define INCLUDED_umkpasswd_h + +struct umkpasswd_conf_s { + int debuglevel; /* you really need me to comment this? */ + char* mech; /* mechanism we want to use */ + char* conf; /* conf file, otherwise DPATH/CPATH */ + int flags; /* to add or not to add (or maybe to update) */ + char* user; /* username */ + int operclass; /* connection class to use */ +}; + +typedef struct umkpasswd_conf_s umkpasswd_conf_t; + +/* values for flags */ +#define ACT_ADDOPER 0x1 +#define ACT_UPDOPER 0x2 +#define ACT_ADDSERV 0x4 /* not implemented yet */ +#define ACT_UPDSRRV 0x8 /* not implemented yet */ + +const char* default_salts = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./"; + +#endif /* INCLUDED_umkpasswd_h */ + diff --git a/ircd/Makefile.in b/ircd/Makefile.in index 713c7dc..03d23d4 100644 --- a/ircd/Makefile.in +++ b/ircd/Makefile.in @@ -83,6 +83,17 @@ RES_SRC = \ res_adns.c \ res_libresolv.c +CRYPTO_SRC = \ + ircd_md5.c \ + ircd_crypt_plain.c \ + ircd_crypt_smd5.c \ + ircd_crypt_native.c + +UMKPASSWD_SRC = ${CRYPTO_SRC} \ + ircd_alloc.c \ + ircd_string.c \ + umkpasswd.c + IRCD_SRC = \ IPcheck.c \ channel.c \ @@ -96,6 +107,7 @@ IRCD_SRC = \ hash.c \ ircd.c \ ircd_alloc.c \ + ircd_crypt.c \ ircd_events.c \ ircd_features.c \ ircd_log.c \ @@ -104,7 +116,6 @@ IRCD_SRC = \ ircd_signal.c \ ircd_snprintf.c \ ircd_string.c \ - ircd_xopen.c \ jupe.c \ lex.yy.c \ list.c \ @@ -210,12 +221,13 @@ IRCD_SRC = \ whowas.c \ y.tab.c - -SRC = ${IRCD_SRC} ${OSDEP_C} ${ENGINE_C} ${RES_C} +SRC = ${IRCD_SRC} ${OSDEP_C} ${ENGINE_C} ${RES_C} ${CRYPTO_SRC} OBJS = ${SRC:%.c=%.o} -DEP_SRC = ${IRCD_SRC} ${OSDEP_SRC} ${ENGINE_SRC} +UMKPASSWD_OBJS = ${UMKPASSWD_SRC:%.c=%.o} + +DEP_SRC = ${IRCD_SRC} ${OSDEP_SRC} ${ENGINE_SRC} ${CRYPTO_SRC} all: ( cd ..; make -f Makefile ) @@ -242,9 +254,8 @@ ircd: ${OBJS} ../include/patchlevel.h version.o # must be a better solution...perhaps sum all of the .c files and include # only that one sum? # -version.c: version.c.SH s_serv.c s_user.c channel.c s_bsd.c s_misc.c ircd.c \ - ../include/version.h ../include/patchlevel.h ../include/patchlist.h - ${SHELL} ${srcdir}/version.c.SH ${srcdir} +version.c: version.c.SH umkpasswd + ${SHELL} ${srcdir}/version.c.SH ${top_srcdir} ../include/patchlist.h: (cd ${top_srcdir} ; ./ircd-patch update) @@ -263,6 +274,9 @@ lex.yy.c: ircd_lexer.l y.tab.h y.tab.c y.tab.h: ircd_parser.y ${YACC} -d ${srcdir}/ircd_parser.y +umkpasswd: ${UMKPASSWD_OBJS} + ${CC} ${LDFLAGS} ${UMKPASSWD_OBJS} ${LIBS} -o $@ + mkbindir: @test -d ${BINDIR} || mkdir ${BINDIR} @@ -284,6 +298,7 @@ install-with-symlink: build mkbindir ${LN_S} ircd.`cat /tmp/ircd.tag` ${SYMLINK}; ) @${RM} /tmp/ircd.tag # ${INSTALL} -s -m 700 -o ${IRCDOWN} -g ${IRCDGRP} chkconf ${BINDIR} + ${INSTALL} -s -m 700 -o ${IRCDOWN} -g ${IRCDGRP} umkpasswd ${BINDIR} ${INSTALL} -m 600 -o ${IRCDOWN} -g ${IRCDGRP} ${top_srcdir}/doc/example.conf ${DPATH} # ( cd ${DPATH}; \ # ${TOUCH} ${MPATH}; \ @@ -317,7 +332,7 @@ uninstall: @echo "Please remove the contents of ${DPATH} manually" clean: - ${RM} -f *.o *.bak ircd version.c chkconf ircd_osdep.c chattr.tab.c table_gen y.tab.* lex.yy.* + ${RM} -f *.o *.bak ircd version.c chkconf umkpasswd ircd_osdep.c chattr.tab.c table_gen y.tab.* lex.yy.* distclean: clean ${RM} -f Makefile stamp-m @@ -433,7 +448,7 @@ ircd.o: ircd.c ../config.h ../include/ircd.h ../include/struct.h \ ../include/s_bsd.h ../include/s_conf.h ../include/s_debug.h \ ../include/s_misc.h ../include/s_stats.h ../include/send.h \ ../include/sys.h ../include/uping.h ../include/userload.h \ - ../include/version.h ../include/whowas.h + ../include/version.h ../include/whowas.h ../include/ircd_crypt.h ircd_alloc.o: ircd_alloc.c ../config.h ../include/ircd_alloc.h \ ../include/ircd_string.h ../include/ircd_chattr.h ../include/s_debug.h \ ../include/ircd_defs.h @@ -485,7 +500,16 @@ ircd_snprintf.o: ircd_snprintf.c ../config.h ../include/client.h \ ircd_string.o: ircd_string.c ../config.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/ircd_defs.h ../include/ircd_log.h \ chattr.tab.c -ircd_xopen.o: ircd_xopen.c ../config.h ../include/ircd_xopen.h +ircd_md5.o: ircd_md5.c ../config.h ../include/ircd_md5.h +ircd_crypt.o: ircd_crypt.c ../config.h ../include/ircd_crypt.h \ + ../include/ircd_alloc.h ../include/s_debug.h +ircd_crypt_native.o: ircd_crypt_native.c ../config.h \ + ../include/ircd_crypt_native.h ../include/ircd_crypt.h \ + ../include/s_debug.h +ircd_crypt_plain.o: ircd_crypt_plain.c ../config.h ../include/ircd_crypt.h \ + ../include/ircd_crypt_plain.h ../include/s_debug.h +ircd_crypt_smd5.o: ircd_crypt_smd5.c ../config.h ../include/ircd_crypt.h \ + ../include/s_debug.h ../include/ircd_crypt_smd5.h jupe.o: jupe.c ../config.h ../include/jupe.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ @@ -776,7 +800,7 @@ m_oper.o: m_oper.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ ../include/struct.h ../include/ircd_features.h ../include/ircd_log.h \ ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/ircd_xopen.h ../include/msg.h \ + ../include/ircd_chattr.h ../include/ircd_crypt.h ../include/msg.h \ ../include/numeric.h ../include/numnicks.h ../include/querycmds.h \ ../include/s_conf.h ../include/s_debug.h ../include/s_user.h \ ../include/s_misc.h ../include/send.h ../include/support.h @@ -1181,7 +1205,7 @@ s_serv.o: s_serv.c ../config.h ../include/s_serv.h ../include/IPcheck.h \ ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/ircd_snprintf.h \ - ../include/ircd_xopen.h ../include/jupe.h ../include/list.h \ + ../include/ircd_crypt.h ../include/jupe.h ../include/list.h \ ../include/match.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/parse.h ../include/querycmds.h \ ../include/ircd_features.h ../include/s_bsd.h ../include/s_conf.h \ diff --git a/ircd/ircd.c b/ircd/ircd.c index 4e1364b..33dbfaf 100644 --- a/ircd/ircd.c +++ b/ircd/ircd.c @@ -35,6 +35,7 @@ #include "ircd_reply.h" #include "ircd_signal.h" #include "ircd_string.h" +#include "ircd_crypt.h" #include "jupe.h" #include "list.h" #include "match.h" @@ -664,6 +665,10 @@ int main(int argc, char **argv) { init_resolver(); + /* we need this for now, when we're modular this + should be removed -- hikari */ + ircd_crypt_init(); + motd_init(); if (!init_conf()) { diff --git a/ircd/ircd_crypt.c b/ircd/ircd_crypt.c new file mode 100644 index 0000000..3f222bc --- /dev/null +++ b/ircd/ircd_crypt.c @@ -0,0 +1,223 @@ +/* + * IRC - Internet Relay Chat, ircd/ircd_crypt.c + * Copyright (C) 2002 hikari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ + +/* + * This is a new look crypto API for ircu, it can handle different + * password formats by the grace of the standard magic tokens at the + * begining of the password e.g. $1 for MD5, $2 for Blowfish, etc. + * + * Currently crypt routines are implemented for: the native crypt() + * function, Salted MD5 and a plain text mechanism which should only + * be used for testing. I intend to add Blowish, 3DES and possibly + * SHA1 support as well at some point, but I'll need to check the + * possible problems that'll cause with stupid crypto laws. + * + * It's also designed to be "ready" for the modularisation of ircu, so + * someone get round to doing it, because I'm not doing it ;) + * + * The plan for Stage B is to semi-modularise the authentication + * mechanism to allow authentication against some other sources than + * the conf file (whatever takes someones fancy, kerberos, ldap, sql, etc). + * + * -- blessed be, hikari. + */ + +#include "config.h" +#include "ircd_crypt.h" +#include "ircd_alloc.h" +#include "ircd_features.h" +#include "ircd_string.h" +#include "s_debug.h" + +/* while we're not modular, we need their init functions */ +#include "ircd_crypt_native.h" +#include "ircd_crypt_plain.h" +#include "ircd_crypt_smd5.h" + +#include +#include +#include + +/* evil global */ +crypt_mechs_t* crypt_mechs_root; + +/* + * add a crypt mechanism to the list +*/ +int ircd_crypt_register_mech(crypt_mech_t* mechanism) +{ +crypt_mechs_t* crypt_mech; + + Debug((DEBUG_INFO, "ircd_crypt_register_mech: resistering mechanism: %s", mechanism->shortname)); + + /* try to allocate some memory for the new mechanism */ + if ((crypt_mech = (crypt_mechs_t*)MyMalloc(sizeof(crypt_mechs_t))) == NULL) + { + /* aww poot, we couldn't get any memory, scream a little then back out */ + Debug((DEBUG_MALLOC, "ircd_crypt_register_mech: could not allocate memory for %s", mechanism->shortname)); + return -1; + } + + /* ok, we have memory, initialise it */ + memset(crypt_mech, 0, sizeof(crypt_mechs_t)); + + /* assign the data */ + crypt_mech->mech = mechanism; + crypt_mech->next = crypt_mech->prev = NULL; + + /* first of all, is there anything there already? */ + if(crypt_mechs_root->next == NULL) + { + /* nope, just add ourself */ + crypt_mechs_root->next = crypt_mechs_root->prev = crypt_mech; + } else { + /* nice and simple, put ourself at the end */ + crypt_mech->prev = crypt_mechs_root->prev; + crypt_mech->next = NULL; + crypt_mechs_root->prev = crypt_mech->prev->next = crypt_mech; + } + + /* we're done */ + Debug((DEBUG_INFO, "ircd_crypt_register_mech: resistered mechanism: %s, crypt_function is at 0x%X.", crypt_mech->mech->shortname, &crypt_mech->mech->crypt_function)); + Debug((DEBUG_INFO, "ircd_crypt_register_mech: %s: %s", crypt_mech->mech->shortname, crypt_mech->mech->description)); + return 0; +} + +/* + * remove a crypt mechanism from the list +*/ +int ircd_crypt_unregister_mech(crypt_mech_t* mechanism) +{ + +return 0; +} + +/* + * this is now a wrapper function which attempts to establish the password + * format and funnel it off to the correct handler function. +*/ +const char* ircd_crypt(const char* key, const char* salt) +{ +char *hashed_pass = NULL; +const char *temp_hashed_pass, *mysalt; +crypt_mechs_t* crypt_mech; + + assert(NULL != key); + assert(NULL != salt); + + Debug((DEBUG_DEBUG, "ircd_crypt: key is %s", key)); + Debug((DEBUG_DEBUG, "ircd_crypt: salt is %s", salt)); + + crypt_mech = crypt_mechs_root->next; + + /* by examining the first n characters of a password string we + * can discover what kind of password it is. hopefully. */ + for (;crypt_mech;) + { + if (strlen(salt) < crypt_mech->mech->crypt_token_size) + { + /* try the next mechanism instead */ + Debug((DEBUG_DEBUG, "ircd_crypt: salt is too short, will try next mech at 0x%X", crypt_mech->next)); + crypt_mech = crypt_mech->next; + continue; + } + + Debug((DEBUG_DEBUG, "ircd_crypt: comparing %s with %s", + salt, crypt_mech->mech->crypt_token)); + + if(0 == ircd_strncmp(crypt_mech->mech->crypt_token, salt, crypt_mech->mech->crypt_token_size)) + { + Debug((DEBUG_DEBUG, "ircd_crypt: type is %s", + crypt_mech->mech->shortname)); + + /* before we send this all off to the crypt_function, we need to remove + the tag from it */ + + /* make sure we won't end up with a password comprised entirely of + a single \0 */ + if(strlen(salt) < crypt_mech->mech->crypt_token_size + 1) + return NULL; + + mysalt = salt + crypt_mech->mech->crypt_token_size; + + if(NULL == (temp_hashed_pass = crypt_mech->mech->crypt_function(key, mysalt))) + return NULL; + + Debug((DEBUG_DEBUG, "ircd_crypt: untagged pass is %s", temp_hashed_pass)); + + /* ok, now we need to prefix the password we just got back + with the right tag */ + if(NULL == (hashed_pass = (char *)MyMalloc(sizeof(char)*strlen(temp_hashed_pass) + crypt_mech->mech->crypt_token_size + 1))) + { + Debug((DEBUG_MALLOC, "ircd_crypt: unable to allocate memory for temp_hashed_pass")); + return NULL; + } + memset(hashed_pass, 0, sizeof(char)*strlen(temp_hashed_pass) + +crypt_mech->mech->crypt_token_size + 1); + ircd_strncpy(hashed_pass, crypt_mech->mech->crypt_token, + crypt_mech->mech->crypt_token_size); + ircd_strncpy(hashed_pass + crypt_mech->mech->crypt_token_size, temp_hashed_pass, strlen(temp_hashed_pass)); + Debug((DEBUG_DEBUG, "ircd_crypt: tagged pass is %s", hashed_pass)); + } else { + Debug((DEBUG_DEBUG, "ircd_crypt: will try next mechansim at 0x%X", + crypt_mech->next)); + crypt_mech = crypt_mech->next; + continue; + } + return hashed_pass; + } + + /* try to use native crypt for an old-style (untagged) password */ + if (strlen(salt) > 2) + { + temp_hashed_pass = (char*)ircd_crypt_native(key, salt); + if (!ircd_strcmp(temp_hashed_pass, salt)) + return strdup(temp_hashed_pass); + } + + return NULL; +} + +/* + * some basic init, when we're modular this will be our entry + * function. +*/ +void ircd_crypt_init(void) +{ + + if((crypt_mechs_root = MyMalloc(sizeof(crypt_mechs_t))) == NULL) + { + /* awooga - can't allocate memory for the root structure */ + Debug((DEBUG_MALLOC, "init_crypt: Could not allocate memory for crypt_mechs_root")); + return; + } + + crypt_mechs_root->mech = NULL; + crypt_mechs_root->next = crypt_mechs_root->prev = NULL; + +/* temporary kludge until we're modular. manualy call the + register funtions for crypt mechanisms */ + ircd_register_crypt_smd5(); + ircd_register_crypt_plain(); + ircd_register_crypt_native(); + +return; +} diff --git a/ircd/ircd_crypt_native.c b/ircd/ircd_crypt_native.c new file mode 100644 index 0000000..5fa2afc --- /dev/null +++ b/ircd/ircd_crypt_native.c @@ -0,0 +1,66 @@ +/* + * IRC - Internet Relay Chat, ircd/ircd_xopen.c + * Copyright (C) 1990, 1991 Armin Gruner + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ +#include "config.h" +#include "ircd_crypt.h" +#include "ircd_crypt_native.h" +#include "s_debug.h" +#include "ircd_alloc.h" + +#define _XOPEN_SOURCE +#define _XOPEN_VERSION 4 + +#include +#include + +/* well this bit is (kinda) intact :) -- hikari */ +const char* ircd_crypt_native(const char* key, const char* salt) +{ + assert(NULL != key); + assert(NULL != salt); + + Debug((DEBUG_DEBUG, "ircd_crypt_native: key is %s", key)); + Debug((DEBUG_DEBUG, "ircd_crypt_native: salt is %s", salt)); + + return (const char*)crypt(key, salt); +} + +/* register ourself with the list of crypt mechanisms -- hikari */ +void ircd_register_crypt_native(void) +{ +crypt_mech_t* crypt_mech; + + if ((crypt_mech = (crypt_mech_t*)MyMalloc(sizeof(crypt_mech_t))) == NULL) + { + Debug((DEBUG_MALLOC, "Could not allocate space for crypt_native")); + return; + } + + crypt_mech->mechname = "native"; + crypt_mech->shortname = "crypt_native"; + crypt_mech->description = "System native crypt() function mechanism."; + crypt_mech->crypt_function = &ircd_crypt_native; + crypt_mech->crypt_token = "$CRYPT$"; + crypt_mech->crypt_token_size = 7; + + ircd_crypt_register_mech(crypt_mech); + +return; +} diff --git a/ircd/ircd_crypt_plain.c b/ircd/ircd_crypt_plain.c new file mode 100644 index 0000000..5cb5965 --- /dev/null +++ b/ircd/ircd_crypt_plain.c @@ -0,0 +1,65 @@ +/* + * IRC - Internet Relay Chat, ircd/ircd_crypt_plain.c + * Copyright (C) 2002 hikari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ +#include "config.h" +#include "ircd_crypt.h" +#include "ircd_crypt_plain.h" +#include "s_debug.h" +#include "ircd_alloc.h" + +#include +#include + +/* yes I know it's an oxymoron, but still, it's handy for testing */ +const char* ircd_crypt_plain(const char* key, const char* salt) +{ + assert(NULL != salt); + assert(NULL != key); + + Debug((DEBUG_DEBUG, "ircd_crypt_plain: key is %s", key)); + Debug((DEBUG_DEBUG, "ircd_crypt_plain: salt is %s", salt)); + + /* yes, that's it. we just send key back out again, + pointless I know */ + return key; +} + +/* register ourself with the list of crypt mechanisms -- hikari */ +void ircd_register_crypt_plain(void) +{ +crypt_mech_t* crypt_mech; + + if ((crypt_mech = (crypt_mech_t*)MyMalloc(sizeof(crypt_mech_t))) == NULL) + { + Debug((DEBUG_MALLOC, "Could not allocate space for crypt_plain")); + return; + } + + crypt_mech->mechname = "plain"; + crypt_mech->shortname = "crypt_plain"; + crypt_mech->description = "Plain text \"crypt\" mechanism."; + crypt_mech->crypt_function = &ircd_crypt_plain; + crypt_mech->crypt_token = "$PLAIN$"; + crypt_mech->crypt_token_size = 7; + + ircd_crypt_register_mech(crypt_mech); + +return; +} diff --git a/ircd/ircd_crypt_smd5.c b/ircd/ircd_crypt_smd5.c new file mode 100644 index 0000000..423710f --- /dev/null +++ b/ircd/ircd_crypt_smd5.c @@ -0,0 +1,207 @@ +/* + * IRC - Internet Relay Chat, ircd/ircd_crypt_smd5.c + * Copyright (C) 2002 hikari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ +#include "config.h" +#include "ircd_crypt.h" +#include "ircd_crypt_smd5.h" +#include "ircd_md5.h" +#include "s_debug.h" +#include "ircd_alloc.h" + +#include +#include +#include + +/* + * ircd_crypt_smd5 is largely taken from md5_crypt.c from the Linux PAM + * source code. it's been modified to fit in with ircu and some of the + * undeeded code has been removed. the source file md5_crypt.c has the + * following licence, so if any of our opers or admins are in Denmark + * they better go buy them a drink ;) -- hikari + * + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + * + */ + +static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ +"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static void to64(char *s, unsigned long v, int n) +{ + while (--n >= 0) { + *s++ = itoa64[v & 0x3f]; + v >>= 6; + } +} + +const char* ircd_crypt_smd5(const char* key, const char* salt) +{ +const char *magic = "$1$"; +char *passwd, *p; +const char *sp, *ep; +unsigned char final[16]; +int sl, pl, i, j; +MD5_CTX ctx, ctx1; +unsigned long l; + + assert(NULL != key); + assert(NULL != salt); + + Debug((DEBUG_DEBUG, "ircd_crypt_smd5: key = %s", key)); + Debug((DEBUG_DEBUG, "ircd_crypt_smd5: salt = %s", salt)); + + /* Refine the Salt first */ + ep = sp = salt; + + if(NULL == (passwd = (char *)MyMalloc(120))) + return NULL; + + memset(passwd, 0, 120); + + for (ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++) + continue; + + /* get the length of the true salt */ + sl = ep - sp; + + MD5Name(MD5Init)(&ctx); + + /* The password first, since that is what is most unknown */ + MD5Name(MD5Update)(&ctx,(unsigned const char *)key,strlen(key)); + + /* Then our magic string */ + MD5Name(MD5Update)(&ctx,(unsigned const char *)magic,strlen(magic)); + + /* Then the raw salt */ + MD5Name(MD5Update)(&ctx,(unsigned const char *)sp,sl); + + /* Then just as many characters of the MD5(key,salt,key) */ + MD5Name(MD5Init)(&ctx1); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)key,strlen(key)); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)sp,sl); + MD5Name(MD5Update)(&ctx1,(unsigned const char *)key,strlen(key)); + MD5Name(MD5Final)(final,&ctx1); + for (pl = strlen(key); pl > 0; pl -= 16) + MD5Name(MD5Update)(&ctx,(unsigned const char *)final,pl>16 ? 16 : pl); + + /* Don't leave anything around in vm they could use. */ + memset(final, 0, sizeof final); + + /* Then something really weird... */ + for (j = 0, i = strlen(key); i; i >>= 1) + if (i & 1) + MD5Name(MD5Update)(&ctx, (unsigned const char *)final+j, 1); + else + MD5Name(MD5Update)(&ctx, (unsigned const char *)key+j, 1); + + /* Now make the output string */ +// strcpy(passwd, magic); +// strncat(passwd, sp, sl); + strncpy(passwd, sp, sl); + strcat(passwd, "$"); + + MD5Name(MD5Final)(final,&ctx); + + /* + * and now, just to make sure things don't run too fast + * On a 60 Mhz Pentium this takes 34 msec, so you would + * need 30 seconds to build a 1000 entry dictionary... + */ + for (i = 0; i < 1000; i++) { + MD5Name(MD5Init)(&ctx1); + + if (i & 1) + MD5Name(MD5Update)(&ctx1,(unsigned const char *)key,strlen(key)); + else + MD5Name(MD5Update)(&ctx1,(unsigned const char *)final,16); + + if (i % 3) + MD5Name(MD5Update)(&ctx1,(unsigned const char *)sp,sl); + + if (i % 7) + MD5Name(MD5Update)(&ctx1,(unsigned const char *)key,strlen(key)); + + if (i & 1) + MD5Name(MD5Update)(&ctx1,(unsigned const char *)final,16); + else + MD5Name(MD5Update)(&ctx1,(unsigned const char *)key,strlen(key)); + + MD5Name(MD5Final)(final,&ctx1); + } + + p = passwd + strlen(passwd); + + Debug((DEBUG_DEBUG, "passwd = %s", passwd)); + + l = (final[0] << 16) | (final[6] << 8) | final[12]; + to64(p, l, 4); + p += 4; + l = (final[1] << 16) | (final[7] << 8) | final[13]; + to64(p, l, 4); + p += 4; + l = (final[2] << 16) | (final[8] << 8) | final[14]; + to64(p, l, 4); + p += 4; + l = (final[3] << 16) | (final[9] << 8) | final[15]; + to64(p, l, 4); + p += 4; + l = (final[4] << 16) | (final[10] << 8) | final[5]; + to64(p, l, 4); + p += 4; + l = final[11]; + to64(p, l, 2); + p += 2; + *p = '\0'; + + /* Don't leave anything around in vm they could use. */ + memset(final, 0, sizeof final); + +return passwd; +} + +/* end borrowed code */ + +/* register ourself with the list of crypt mechanisms */ +void ircd_register_crypt_smd5(void) +{ +crypt_mech_t* crypt_mech; + + if ((crypt_mech = (crypt_mech_t*)MyMalloc(sizeof(crypt_mech_t))) == NULL) + { + Debug((DEBUG_MALLOC, "Could not allocate space for crypt_smd5")); + return; + } + + crypt_mech->mechname = "smd5"; + crypt_mech->shortname = "crypt_smd5"; + crypt_mech->description = "Salted MD5 password hash mechanism."; + crypt_mech->crypt_function = &ircd_crypt_smd5; + crypt_mech->crypt_token = "$SMD5$"; + crypt_mech->crypt_token_size = 6 ; + + ircd_crypt_register_mech(crypt_mech); + +return; +} diff --git a/ircd/ircd_features.c b/ircd/ircd_features.c index 0d22f6d..1fb6e44 100644 --- a/ircd/ircd_features.c +++ b/ircd/ircd_features.c @@ -310,6 +310,7 @@ static struct FeatureDesc { F_B(HIS_LINKS, 0, 1, 0), F_B(HIS_TRACE, 0, 1, 0), F_B(HIS_STATS_l, 0, 1, 0), + F_B(HIS_STATS_L, 0, 1, 0), F_B(HIS_STATS_c, 0, 1, 0), F_B(HIS_STATS_g, 0, 1, 0), F_B(HIS_STATS_h, 0, 1, 0), diff --git a/ircd/ircd_md5.c b/ircd/ircd_md5.c new file mode 100644 index 0000000..b5b15d4 --- /dev/null +++ b/ircd/ircd_md5.c @@ -0,0 +1,259 @@ +/* + * IRC - Internet Relay Chat, ircd/ircd_md5.h + * + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + * + * ircuified 2002 by hikari + * + * $Id$ +*/ + +#include +#include "ircd_md5.h" + +#ifndef HIGHFIRST +#define byteReverse(buf, len) /* Nothing */ +#else +static void byteReverse(unsigned char *buf, unsigned longs); + +#ifndef ASM_MD5 +/* + * Note: this code is harmless on little-endian machines. + */ +static void byteReverse(unsigned char *buf, unsigned longs) +{ + uint32 t; + do { + t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32 *) buf = t; + buf += 4; + } while (--longs); +} +#endif +#endif + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void MD5Name(MD5Init)(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301U; + ctx->buf[1] = 0xefcdab89U; + ctx->buf[2] = 0x98badcfeU; + ctx->buf[3] = 0x10325476U; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void MD5Name(MD5Update)(struct MD5Context *ctx, unsigned const char *buf, unsigned len) +{ + uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void MD5Name(MD5Final)(unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((uint32 *) ctx->in)[14] = ctx->bits[0]; + ((uint32 *) ctx->in)[15] = ctx->bits[1]; + + MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +#ifndef ASM_MD5 + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +void MD5Name(MD5Transform)(uint32 buf[4], uint32 const in[16]) +{ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478U, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756U, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070dbU, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceeeU, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0fafU, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62aU, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613U, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501U, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8U, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7afU, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1U, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7beU, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122U, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193U, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438eU, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821U, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562U, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340U, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51U, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aaU, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105dU, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453U, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681U, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8U, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6U, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6U, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87U, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14edU, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905U, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8U, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9U, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8aU, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942U, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681U, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122U, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380cU, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44U, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9U, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60U, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70U, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6U, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127faU, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085U, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05U, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039U, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5U, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8U, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665U, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244U, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97U, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7U, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039U, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3U, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92U, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47dU, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1U, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4fU, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0U, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314U, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1U, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82U, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235U, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bbU, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391U, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#endif diff --git a/ircd/m_info.c b/ircd/m_info.c index 952e1c3..ec298d3 100644 --- a/ircd/m_info.c +++ b/ircd/m_info.c @@ -179,7 +179,7 @@ int mo_info(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) send_reply(sptr, RPL_INFO, *text); text++; } - if (IsOper(sptr)) + if (IsOper(sptr) && (NULL != parv[1])) { while (*text) send_reply(sptr, RPL_INFO, *text++); diff --git a/ircd/m_oper.c b/ircd/m_oper.c index 002b36d..a180c05 100644 --- a/ircd/m_oper.c +++ b/ircd/m_oper.c @@ -88,7 +88,7 @@ #include "ircd_log.h" #include "ircd_reply.h" #include "ircd_string.h" -#include "ircd_xopen.h" +#include "ircd_crypt.h" #include "msg.h" #include "numeric.h" #include "numnicks.h" @@ -114,10 +114,15 @@ int oper_password_match(const char* to_match, const char* passwd) if (!to_match || !passwd) return 0; - if (feature_bool(FEAT_CRYPT_OPER_PASSWORD)) - to_match = ircd_crypt(to_match, passwd); + /* we no longer do a CRYPT_OPER_PASSWORD check because a clear + text passwords just handled by a fallback mechanism called + crypt_clear if it's enabled -- hikari */ + to_match = ircd_crypt(to_match, passwd); - return (0 == strcmp(to_match, passwd)); + if (to_match == NULL) + return 0; + else + return (0 == strcmp(to_match, passwd)); } /* diff --git a/ircd/s_serv.c b/ircd/s_serv.c index c8b76a1..29da252 100644 --- a/ircd/s_serv.c +++ b/ircd/s_serv.c @@ -35,7 +35,7 @@ #include "ircd_reply.h" #include "ircd_string.h" #include "ircd_snprintf.h" -#include "ircd_xopen.h" +#include "ircd_crypt.h" #include "jupe.h" #include "list.h" #include "match.h" diff --git a/ircd/s_stats.c b/ircd/s_stats.c index 7de3d5d..56c224b 100644 --- a/ircd/s_stats.c +++ b/ircd/s_stats.c @@ -30,6 +30,7 @@ #include "ircd_chattr.h" #include "ircd_events.h" #include "ircd_features.h" +#include "ircd_crypt.h" #include "ircd_log.h" #include "ircd_reply.h" #include "ircd_string.h" @@ -297,6 +298,39 @@ stats_links(struct Client* sptr, struct StatDesc* sd, int stat, char* name) } } +/* hopefuly this will be where we'll spit out info about loaded modules */ +static void +stats_modules(struct Client* to, struct StatDesc* sd, int stat, char* param) +{ +crypt_mechs_t* mechs; + + send_reply(to, SND_EXPLICIT | RPL_STATSLLINE, + "Module Description Entry Point"); + + /* atm the only "modules" we have are the crypto mechanisms, + eventualy they'll be part of a global dl module list, for now + i'll just output data about them -- hikari */ + + if(crypt_mechs_root == NULL) + return; + + mechs = crypt_mechs_root->next; + + for(;;) + { + if(mechs == NULL) + return; + + send_reply(to, SND_EXPLICIT | RPL_STATSLLINE, + "%s %s 0x%X", + mechs->mech->shortname, mechs->mech->description, + mechs->mech->crypt_function); + + mechs = mechs->next; + } + +} + static void stats_commands(struct Client* to, struct StatDesc* sd, int stat, char* param) { @@ -447,9 +481,14 @@ struct StatDesc statsinfo[] = { { 'k', (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_k, stats_klines, 0, "Local bans (K-Lines)." }, - { 'l', (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_l, + { 'l', (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM | STAT_FLAG_CASESENS), + FEAT_HIS_STATS_l, stats_links, 0, "Current connections information." }, + { 'L', (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM | STAT_FLAG_CASESENS), + FEAT_HIS_STATS_L, + stats_modules, 0, + "Dynamicly loaded modules." }, #if 0 { 'M', (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_M, stats_memtotal, 0, diff --git a/ircd/umkpasswd.c b/ircd/umkpasswd.c new file mode 100644 index 0000000..8ad0e1f --- /dev/null +++ b/ircd/umkpasswd.c @@ -0,0 +1,417 @@ +/* + * IRC - Internet Relay Chat, ircd/umkpasswd.c + * Copyright (C) 2002 hikari + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ +*/ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* ircu headers */ +#include "ircd_alloc.h" +#include "ircd_string.h" +#include "umkpasswd.h" +#include "s_debug.h" +#include "ircd_md5.h" + +/* crypto mech headers */ +#include "ircd_crypt.h" +#include "ircd_crypt_smd5.h" +#include "ircd_crypt_native.h" +#include "ircd_crypt_plain.h" + +/* bleah, evil globals */ +umkpasswd_conf_t* umkpasswd_conf; +crypt_mechs_t* crypt_mechs_root; + +void copyright(void) +{ + fprintf(stderr, "umkpasswd - Copyright (c) 2002 hikari\n"); +return; +} + +void show_help(void) +{ +#ifdef DEBUGMODE + char *debughelp = "[-d ] "; +#else + char *debughelp = ""; +#endif + + copyright(); + /*fprintf(stderr, "umkpasswd [-l] [[[-a]||[-u]] ] [-y ] %s[-c ] -m [password]\n\n", debughelp);*/ + fprintf(stderr, "umkpasswd [-l] %s-m [password]\n\n", debughelp); + fprintf(stderr, " -l List mechanisms available.\n"); +#if 0 + fprintf(stderr, " -a Add user to conf file.\n"); + fprintf(stderr, " -u Update user's password field.\n"); + fprintf(stderr, " -y Class to place oper in.\n"); +#endif + fprintf(stderr, " -m Mechanism to use [MANDATORY].\n"); +#ifdef DEBUGMODE + fprintf(stderr, " -d Debug level to run at.\n"); +#endif +/* + fprintf(stderr, " -c Conf file to use, default is DPATH/CPATH.\n\n"); +*/ +return; +} + +/* our implementation of debug() */ +void debug(int level, const char *form, ...) +{ +va_list vl; +int err = errno; + + if (level <= (umkpasswd_conf->debuglevel)) + { + va_start(vl, form); + vfprintf(stderr, form, vl); + fprintf(stderr, "\n"); + va_end(vl); + } + errno = err; +} + +/* quick and dirty salt generator */ +char *make_salt(const char *salts) +{ +char *tmp = NULL; +long int n = 0; + + /* try and get around them running this time after time in quick sucession */ + sleep(1); + srandom((unsigned int)time(NULL)); + + if((tmp = calloc(3, sizeof(char))) != NULL) + { + /* can't optimize this much more than just doing it twice */ + n = ((float)(strlen(salts))*random()/(RAND_MAX+1.0)); + memcpy(tmp, (salts+n), 1); + sleep(2); + n = ((float)(strlen(salts))*random()/(RAND_MAX+1.0)); + memcpy((tmp+1), (salts+n), 1); + + Debug((DEBUG_DEBUG, "salts = %s", salts)); + Debug((DEBUG_DEBUG, "strlen(salts) = %d", strlen(salts))); + } + +return tmp; +} + +/* our implemenation of ircd_crypt_register_mech() */ +int ircd_crypt_register_mech(crypt_mech_t* mechanism) +{ +crypt_mechs_t* crypt_mech; + + Debug((DEBUG_INFO, "ircd_crypt_register_mech: resistering mechanism: %s", mechanism->shortname)); + + /* try to allocate some memory for the new mechanism */ + if ((crypt_mech = (crypt_mechs_t*)MyMalloc(sizeof(crypt_mechs_t))) == NULL) + { + /* aww poot, we couldn't get any memory, scream a little then back out */ + Debug((DEBUG_MALLOC, "ircd_crypt_register_mech: could not allocate memory for %s", mechanism->shortname)); + return -1; + } + + /* ok, we have memory, initialise it */ + memset(crypt_mech, 0, sizeof(crypt_mechs_t)); + + /* assign the data */ + crypt_mech->mech = mechanism; + crypt_mech->next = crypt_mech->prev = NULL; + + /* first of all, is there anything there already? */ + if(crypt_mechs_root->next == NULL) + { + /* nope, just add ourself */ + crypt_mechs_root->next = crypt_mechs_root->prev = crypt_mech; + } else { + /* nice and simple, put ourself at the end */ + crypt_mech->prev = crypt_mechs_root->prev; + crypt_mech->next = NULL; + crypt_mechs_root->prev = crypt_mech->prev->next = crypt_mech; + } + + /* we're done */ + Debug((DEBUG_INFO, "ircd_crypt_register_mech: resistered mechanism: %s, crypt_function is at 0x%X.", crypt_mech->mech->shortname, &crypt_mech->mech->crypt_function)); + Debug((DEBUG_INFO, "ircd_crypt_register_mech: %s: %s", crypt_mech->mech->shortname, crypt_mech->mech->description)); + +return 0; +} + +void sum(char* tmp) +{ +FILE* file; +MD5_CTX context; +int len; +unsigned char buffer[1024], digest[16]; + + if (NULL == (file = fopen(tmp, "r"))) + exit(0); + MD5Name(MD5Init)(&context); + while (len = fread (buffer, 1, 1024, file)) + MD5Name(MD5Update)(&context, buffer, len); + MD5Name(MD5Final)(digest, &context); + fclose(file); + + printf("%s: ", basename(tmp)); + for (len = 0; len < 16; len++) + printf ("%02x", digest[len]); + printf("\n"); + exit(0); +} + +/* dump the loaded mechs list */ +void show_mechs(void) +{ +crypt_mechs_t* mechs; + + copyright(); + printf("\nAvailable mechanisms:\n"); + + if(crypt_mechs_root == NULL) + return; + + mechs = crypt_mechs_root->next; + + for(;;) + { + if(mechs == NULL) + return; + + printf(" %s\t\t%s\n", mechs->mech->mechname, mechs->mech->description); + + mechs = mechs->next; + } +} + +/* load in the mech "modules" */ +void load_mechs(void) +{ + /* we need these loaded by hand for now */ + + ircd_register_crypt_native(); + ircd_register_crypt_smd5(); + ircd_register_crypt_plain(); /* yes I know it's slightly pointless */ + +return; +} + +crypt_mechs_t* hunt_mech(const char* mechname) +{ +crypt_mechs_t* mech; + + assert(NULL != mechname); + + if(crypt_mechs_root == NULL) + return NULL; + + mech = crypt_mechs_root->next; + + for(;;) + { + if(mech == NULL) + return NULL; + + if(0 == (ircd_strcmp(mech->mech->mechname, mechname))) + return mech; + + mech = mech->next; + } +} + +char* crypt_pass(const char* pw, const char* mech) +{ +crypt_mechs_t* crypt_mech; +char* salt, *untagged, *tagged; + + assert(NULL != pw); + assert(NULL != mech); + + Debug((DEBUG_DEBUG, "pw = %s\n", pw)); + Debug((DEBUG_DEBUG, "mech = %s\n", mech)); + + if (NULL == (crypt_mech = hunt_mech(mech))) + { + printf("Unable to find mechanism %s\n", mech); + return NULL; + } + + salt = make_salt(default_salts); + + untagged = (char *)CryptFunc(crypt_mech->mech)(pw, salt); + tagged = (char *)MyMalloc(strlen(salt)+CryptTokSize(crypt_mech->mech)+1); + memset(tagged, 0, strlen(untagged)+CryptTokSize(crypt_mech->mech)+1); + strncpy(tagged, CryptTok(crypt_mech->mech), CryptTokSize(crypt_mech->mech)); + strncpy(tagged+CryptTokSize(crypt_mech->mech), untagged, strlen(untagged)); + +return tagged; +} + +char* parse_arguments(int argc, char **argv) +{ +int len = 0, c = 0; +const char* options = "a:d:lm:u:y:5:"; + + umkpasswd_conf = (umkpasswd_conf_t*)MyMalloc(sizeof(umkpasswd_conf_t)); + + umkpasswd_conf->flags = 0; + umkpasswd_conf->debuglevel = 0; + umkpasswd_conf->operclass = 0; + umkpasswd_conf->user = NULL; + umkpasswd_conf->mech = NULL; + + + len = strlen(DPATH) + strlen(CPATH) + 2; + umkpasswd_conf->conf = (char *)MyMalloc(len*sizeof(char)); + memset(umkpasswd_conf->conf, 0, len*sizeof(char)); + ircd_strncpy(umkpasswd_conf->conf, DPATH, strlen(DPATH)); + *((umkpasswd_conf->conf) + strlen(DPATH)) = '/'; + ircd_strncpy((umkpasswd_conf->conf) + strlen(DPATH) + 1, CPATH, strlen(CPATH)); + + len = 0; + + while ((EOF != (c = getopt(argc, argv, options))) && !len) + { + switch (c) + { + case '5': + sum(optarg); + break; + + case 'y': + umkpasswd_conf->operclass = atoi(optarg); + if (umkpasswd_conf->operclass < 0) + umkpasswd_conf->operclass = 0; + break; + + case 'u': + if(umkpasswd_conf->flags && ACT_UPDOPER) + { + fprintf(stderr, "-a and -u are mutually exclussive. Use either or neither.\n"); + abort(); /* b0rk b0rk b0rk */ + } + + umkpasswd_conf->flags |= ACT_UPDOPER; + umkpasswd_conf->user = optarg; + break; + + case 'm': + umkpasswd_conf->mech = optarg; + break; + + case 'l': + load_mechs(); + show_mechs(); + exit(0); + break; + + case 'd': + umkpasswd_conf->debuglevel = atoi(optarg); + if (umkpasswd_conf->debuglevel < 0) + umkpasswd_conf->debuglevel = 0; + break; + + case 'c': + umkpasswd_conf->conf = optarg; + break; + + case 'a': + if(umkpasswd_conf->flags && ACT_UPDOPER) + { + fprintf(stderr, "-a and -u are mutually exclussive. Use either or neither.\n"); + abort(); /* b0rk b0rk b0rk */ + } + + umkpasswd_conf->flags |= ACT_ADDOPER; + umkpasswd_conf->user = optarg; + break; + + default: + /* unknown option - spit out syntax and b0rk */ + show_help(); + abort(); + break; + } + } + + Debug((DEBUG_DEBUG, "flags = %d", umkpasswd_conf->flags)); + Debug((DEBUG_DEBUG, "operclass = %d", umkpasswd_conf->operclass)); + Debug((DEBUG_DEBUG, "debug = %d", umkpasswd_conf->debuglevel)); + + if (NULL != umkpasswd_conf->mech) + Debug((DEBUG_DEBUG, "mech = %s", umkpasswd_conf->mech)); + else + Debug((DEBUG_DEBUG, "mech is unset")); + + if (NULL != umkpasswd_conf->conf) + Debug((DEBUG_DEBUG, "conf = %s", umkpasswd_conf->conf)); + else + Debug((DEBUG_DEBUG, "conf is unset")); + + if (NULL != umkpasswd_conf->user) + Debug((DEBUG_DEBUG, "user = %s", umkpasswd_conf->user)); + else + Debug((DEBUG_DEBUG, "user is unset")); + +/* anything left over should be password */ +return argv[optind]; +} + +int main(int argc, char **argv) +{ +char* pw, *crypted_pw; + + crypt_mechs_root = (crypt_mechs_t*)MyMalloc(sizeof(crypt_mechs_t)); + crypt_mechs_root->mech = NULL; + crypt_mechs_root->next = crypt_mechs_root->prev = NULL; + + if (argc < 2) + { + show_help(); + exit(0); + } + + pw = parse_arguments(argc, argv); + load_mechs(); + + if (NULL == umkpasswd_conf->mech) + { + fprintf(stderr, "No mechanism specified.\n"); + abort(); + } + + if (NULL == pw) + { + pw = getpass("Password: "); + } + crypted_pw = crypt_pass(pw, umkpasswd_conf->mech); + + printf("Crypted Pass: %s\n", crypted_pw); + memset(pw, 0, strlen(pw)); + +return 0; +} diff --git a/ircd/version.c.SH b/ircd/version.c.SH index 2b65dc8..b66cf12 100644 --- a/ircd/version.c.SH +++ b/ircd/version.c.SH @@ -1,3 +1,5 @@ +#! /bin/sh + echo "Extracting ircd/version.c ..." srcdir=$1 @@ -12,33 +14,11 @@ fi generation=`expr $generation + 1` -sum=sum -if $sum ${srcdir}/s_serv.c 1> /dev/null 2>&1; then -: -else - sum=cksum -fi -sumsserv=`$sum ${srcdir}/s_serv.c 2> /dev/null`; -sumsuser=`$sum ${srcdir}/s_user.c 2> /dev/null`; -sumchan=`$sum ${srcdir}/channel.c 2> /dev/null`; -sumsbsd=`$sum ${srcdir}/s_bsd.c 2> /dev/null`; -sumhash=`$sum ${srcdir}/hash.c 2> /dev/null`; -sumsmisc=`$sum ${srcdir}/s_misc.c 2> /dev/null`; -sumircd=`$sum ${srcdir}/ircd.c 2> /dev/null`; - creation=`date | \ awk '{if (NF == 6) \ - { print $1 " " $2 " " $3 " " $6 " at " $4 " " $5 } \ + { print $1 " " $2 " " $3 " " $6 " at " $4 " " $5 } \ else \ - { print $1 " " $2 " " $3 " " $7 " at " $4 " " $5 " " $6 }}'` - -# cvsversion=`cat ../.patches | \ -# awk -F. '{ \ -# if ($(NF)~/\+$/) \ -# printf(".0"); \ -# else \ -# printf(".%s", $(NF)); \ -# }'` + { print $1 " " $2 " " $3 " " $7 " at " $4 " " $5 " " $6 }}'` /bin/cat >version.c <", + "Wiz Jarkko Oikarinen ", "", "The main developer of version u2.9 and u2.10 was:", - "Run Carlo Wood ", + "Run Carlo Wood ", "", - "The current head developer of the u2.10 source tree is:", + "The head developer of the u2.10 source tree was:", "Bleep Thomas Helvey ", "", + "The current maintainors of the u2.10 source tree are:", + "Isomer Perry Lorier ", + "Kev Kevin Mitchell ", + "", "Contributors to this release:", "Kev, Isomer, Gte, Ghostwolf, Bleep", "Debugging and support:", @@ -96,8 +80,21 @@ const char *infotext[] = { "A full listing of all coders can be found in doc/Authors in the", "source.", "", - "[$sumsserv] [$sumchan] [$sumsbsd] [$sumsuser]", - "[$sumhash] [$sumsmisc] [$sumircd]", + "Sources:", +!SUB!THIS! + +for file in ${srcdir}/ircd/*.c ; do + echo " \"[" `./umkpasswd -5 $file` " ]\"," >> version.c +done; + +echo " \"\"," >> version.c +echo " \"Headers:\"," >> version.c + +for file in ${srcdir}/include/*.h ; do + echo " \"[" `./umkpasswd -5 $file` " ]\"," >> version.c +done; + +/bin/cat >>version.c <