added gnutls backend and moved backend code into new files
[ircu2.10.12-pk.git] / ircd / ircd_crypt_smd5.c
index 423710fde1d28d1f36db558730033c52db2d2a8c..439c08988de0f71a1f500267ffe07e01f69d0270 100644 (file)
  * 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 <assert.h>
-#include <string.h>
-#include <unistd.h>
-
-/*
+/** 
+ * @file
+ * @brief Routines for Salted MD5 passwords
+ * @version $Id$
+ * 
  * 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
+ * unneeded code has been removed.  the source file md5_crypt.c has the 
+ * following license, so if any of our opers or admins are in Denmark
  * they better go buy them a drink ;) -- hikari
  *
  * ----------------------------------------------------------------------------
  * ----------------------------------------------------------------------------
  *
  */
+#include "config.h"
+#include "ircd_crypt.h"
+#include "ircd_crypt_smd5.h"
+#include "ircd_log.h"
+#include "ircd_md5.h"
+#include "s_debug.h"
+#include "ircd_alloc.h"
+
+/* #include <assert.h> -- Now using assert in ircd_log.h */
+#include <string.h>
+#include <unistd.h>
 
 static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
 
+/** Converts a binary value into a BASE64 encoded string.
+ * @param s Pointer to the output string
+ * @param v The unsigned long we're working on
+ * @param n The number of bytes we're working with
+ *  
+ * This is used to produce the normal MD5 hash everyone is familiar with.  
+ * It takes the value v and converts n bytes of it it into an ASCII string in 
+ * 6-bit chunks, the resulting string is put at the address pointed to by s.
+ * 
+ */
 static void to64(char *s, unsigned long v, int n)
 {
  while (--n >= 0) {
@@ -56,10 +69,23 @@ static void to64(char *s, unsigned long v, int n)
  }
 }
 
+/** Produces a Salted MD5 crypt of a password using the supplied salt
+ * @param key The password we're encrypting
+ * @param salt The salt we're using to encrypt it
+ * @return The Salted MD5 password of key and salt
+ * 
+ * Erm does exactly what the brief comment says.  If you think I'm writing a 
+ * description of how MD5 works, you have another think coming.  Go and read
+ * Applied Cryptography by Bruce Schneier.  The only difference is we use a 
+ * salt at the beginning of the password to perturb it so that the same password
+ * doesn't always produce the same hash.
+ * 
+ */ 
 const char* ircd_crypt_smd5(const char* key, const char* salt)
 {
 const char *magic = "$1$";
-char *passwd, *p;
+static char passwd[120];
+char *p;
 const char *sp, *ep;
 unsigned char final[16];
 int sl, pl, i, j;
@@ -75,36 +101,31 @@ unsigned long l;
  /* 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);
+ MD5Init(&ctx);
 
  /* The password first, since that is what is most unknown */
- MD5Name(MD5Update)(&ctx,(unsigned const char *)key,strlen(key));
+ MD5Update(&ctx,(unsigned const char *)key,strlen(key));
 
  /* Then our magic string */
- MD5Name(MD5Update)(&ctx,(unsigned const char *)magic,strlen(magic));
+ MD5Update(&ctx,(unsigned const char *)magic,strlen(magic));
 
  /* Then the raw salt */
- MD5Name(MD5Update)(&ctx,(unsigned const char *)sp,sl);
+ 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);
+ MD5Init(&ctx1);
+ MD5Update(&ctx1,(unsigned const char *)key,strlen(key));
+ MD5Update(&ctx1,(unsigned const char *)sp,sl);
+ MD5Update(&ctx1,(unsigned const char *)key,strlen(key));
+ MD5Final(final,&ctx1);
  for (pl = strlen(key); pl > 0; pl -= 16)
-  MD5Name(MD5Update)(&ctx,(unsigned const char *)final,pl>16 ? 16 : pl);
+  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);
@@ -112,17 +133,16 @@ unsigned long l;
  /* 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);
+   MD5Update(&ctx, (unsigned const char *)final+j, 1);
   else
-   MD5Name(MD5Update)(&ctx, (unsigned const char *)key+j, 1);
+   MD5Update(&ctx, (unsigned const char *)key+j, 1);
 
- /* Now make the output string */
-// strcpy(passwd, magic);
-// strncat(passwd, sp, sl);
+ /* Now make the output string. */
+ memset(passwd, 0, 120);
  strncpy(passwd, sp, sl);
  strcat(passwd, "$");
 
- MD5Name(MD5Final)(final,&ctx);
+ MD5Final(final,&ctx);
 
  /*
   * and now, just to make sure things don't run too fast
@@ -130,31 +150,33 @@ unsigned long l;
   * need 30 seconds to build a 1000 entry dictionary...
   */
  for (i = 0; i < 1000; i++) {
-  MD5Name(MD5Init)(&ctx1);
+  MD5Init(&ctx1);
 
   if (i & 1)
-   MD5Name(MD5Update)(&ctx1,(unsigned const char *)key,strlen(key));
+   MD5Update(&ctx1,(unsigned const char *)key,strlen(key));
   else
-   MD5Name(MD5Update)(&ctx1,(unsigned const char *)final,16);
+   MD5Update(&ctx1,(unsigned const char *)final,16);
 
   if (i % 3)
-   MD5Name(MD5Update)(&ctx1,(unsigned const char *)sp,sl);
+   MD5Update(&ctx1,(unsigned const char *)sp,sl);
 
   if (i % 7)
-   MD5Name(MD5Update)(&ctx1,(unsigned const char *)key,strlen(key));
+   MD5Update(&ctx1,(unsigned const char *)key,strlen(key));
 
   if (i & 1)
-   MD5Name(MD5Update)(&ctx1,(unsigned const char *)final,16);
+   MD5Update(&ctx1,(unsigned const char *)final,16);
   else
-   MD5Name(MD5Update)(&ctx1,(unsigned const char *)key,strlen(key));
+   MD5Update(&ctx1,(unsigned const char *)key,strlen(key));
 
-  MD5Name(MD5Final)(final,&ctx1);
+  MD5Final(final,&ctx1);
  }
 
  p = passwd + strlen(passwd);
 
  Debug((DEBUG_DEBUG, "passwd = %s", passwd));
 
+ /* Turn the encrypted binary data into a BASE64 encoded string we can read
+  * and display -- hikari */
  l = (final[0] << 16) | (final[6] << 8) | final[12];
  to64(p, l, 4);
  p += 4;
@@ -183,7 +205,11 @@ return passwd;
 
 /* end borrowed code */
 
-/* register ourself with the list of crypt mechanisms */
+/** Register ourself with the list of crypt mechanisms 
+ * Registers the SMD5 mechanism in the list of available crypt mechanisms.  When 
+ * we're modular this will be the entry function for the module.
+ * 
+ */
 void ircd_register_crypt_smd5(void)
 {
 crypt_mech_t* crypt_mech;