/** * ircservices.C: IRCServices's weird password encryption thingy, taken from Anope 1.6.3. * * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team * Rights to this code are as documented in COPYING. * * * Portions of this file were derived from sources bearing the following license: * Copyright © 2005 Atheme Development Group * Rights to this code are as documented in doc/pod/license.pod. * * $Id: ircservices.C,v 1.6 2007/09/16 18:54:43 pippijn Exp $ */ /* Include file for high-level encryption routines. * * (C) 2003 Anope Team * Contact us at info@anope.org * * Please read doc/poddoc/license.pod and README for further details. * * Based on the original code of Epona by Lara. * Based on the original code of Services by Andy Church. */ #include "atheme.h" #include static char const rcsid[] = "$Id: ircservices.C,v 1.6 2007/09/16 18:54:43 pippijn Exp $"; /* necessary anope defines */ #define PASSMAX 32 #define ENCRYPT_MD5 1 /*************************************************************************/ /******** Our own high-level routines. ********/ #define XTOI(c) ((c)>9 ? (c)-'A'+10 : (c)-'0') /* Result of this: * c in [-128,9] => [-183,-46] * c in [10,127] => [-38,79] */ namespace crypto { namespace impl { /** * Encrypt `src' of length `len' and store the result in `dest'. If the * resulting string would be longer than `size', return -1 and leave `dest' * unchanged; else return 0. */ static int encrypt (char const * const src, int len, char *dest, int size) { #if ENCRYPT_MD5 MD5Context context; char digest[33]; char dest2[16]; int i; if (size < 32) return -1; memset (&context, 0, sizeof (context)); memset (&digest, 0, sizeof (digest)); MD5Init (&context); MD5Update (&context, (unsigned char const *) src, (size_t) len); MD5Final ((unsigned char *) digest, &context); for (i = 0; i < 32; i += 2) dest2[i / 2] = XTOI (digest[i]) << 4 | XTOI (digest[i + 1]); /* convert to hex, skipping last 8 bytes (constant) -- jilles */ strcpy (dest, "$ircservices$"); for (i = 0; i <= 7; i++) sprintf (dest + 13 + 2 * i, "%02x", 255 & dest2[i]); return 0; #endif return -1; /* unknown encryption algorithm */ } #if 0 /* unused */ /* Shortcut for encrypting a null-terminated string in place. */ static int encrypt_in_place (char *buf, int size) { return encrypt (buf, strlen (buf), buf, size); } #endif /** * Compare a plaintext string against an encrypted password. Return 1 if * they match, 0 if not, and -1 if something went wrong. */ static int check_password (char const * const plaintext, char const * const password) { char buf[BUFSIZE]; if (encrypt (plaintext, strlen (plaintext), buf, sizeof (buf)) < 0) return -1; #ifdef ENCRYPT_MD5 if (strcmp (buf, password) == 0) #else if (0) #endif return 1; else return 0; } } // namespace impl /*************************************************************************/ struct ircservices : handler { virtual char const *crypt (char const * const key, char const * const salt); }; char const * ircservices::crypt (char const * const key, char const * const salt) { static char output[PASSMAX]; if (salt[0] == '$' && salt[1] == '1') /* this is a new pw XXX */ { impl::encrypt (key, strlen (key), output, PASSMAX); return output; } else { if (impl::check_password (key, salt)) return salt; else return ""; } } } // namespace crypto #define FACREG_TYPE crypto::ircservices #define FACREG_TYPE_NAME "ircservices" #define FACREG_INTERFACE_TYPE crypto::handler #include