]> jfr.im git - solanum.git/blobdiff - extensions/m_mkpasswd.c
m_shedding: user shedding module based on oftc-hybrid
[solanum.git] / extensions / m_mkpasswd.c
index b59997b097dcc616c8ba50797f8799207dbee8c4..66d7d6b080774f4996c538e909623e5aed476561 100644 (file)
 /*
- *  m_mkpasswd.c: Encrypts a password online, DES or MD5.
+ * m_mkpasswd.c: Encrypts a password online.
  *
- *  Copyright 2002 W. Campbell and the ircd-ratbox development team
- *  Based on mkpasswd.c, originally by Nelson Minar (minar@reed.edu)
- *
- *  You can use this code in any way as long as these names remain.
- *
- *  $Id: m_mkpasswd.c 3161 2007-01-25 07:23:01Z nenolod $
+ * Based on mkpasswd.c, originally by Nelson Minar (minar@reed.edu)
+ * You can use this code in any way as long as these names remain.
  */
 
-/* List of ircd includes from ../include/ */
 #include "stdinc.h"
 #include "client.h"
-#include "common.h"            /* FALSE bleah */
-#include "ircd.h"
-#include "match.h"
 #include "numeric.h"
-#include "s_newconf.h"
 #include "s_conf.h"
-#include "logger.h"
-#include "s_serv.h"
-#include "send.h"
-#include "msg.h"
-#include "parse.h"
 #include "modules.h"
+#include "messages.h"
+#include "send.h"
 
 #include <string.h>
 
-static int m_mkpasswd(struct Client *client_p, struct Client *source_p,
+const char mkpasswd_desc[] = "Hash a password for use in ircd.conf";
+
+static void m_mkpasswd(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p,
                      int parc, const char *parv[]);
-static int mo_mkpasswd(struct Client *client_p, struct Client *source_p,
+static void mo_mkpasswd(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p,
                       int parc, const char *parv[]);
-static char *make_salt(void);
-static char *make_md5_salt(void);
 
-static char saltChars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
+static char *make_md5_salt(int);
+static char *make_sha256_salt(int);
+static char *make_sha512_salt(int);
+static char *generate_random_salt(char *, int);
+static char *generate_poor_salt(char *, int);
 
+static char saltChars[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+       /* 0 .. 63, ascii - 64 */
 
 struct Message mkpasswd_msgtab = {
-       "MKPASSWD", 0, 0, 0, MFLG_SLOW,
+       "MKPASSWD", 0, 0, 0, 0,
        {mg_unreg, {m_mkpasswd, 2}, mg_ignore, mg_ignore, mg_ignore, {mo_mkpasswd, 2}}
 };
 
 mapi_clist_av1 mkpasswd_clist[] = { &mkpasswd_msgtab, NULL };
 
-DECLARE_MODULE_AV1(mkpasswd, NULL, NULL, mkpasswd_clist, NULL, NULL, "$Revision: 3161 $");
+DECLARE_MODULE_AV2(mkpasswd, NULL, NULL, mkpasswd_clist, NULL, NULL, NULL, NULL, mkpasswd_desc);
 
 
-static int
-m_mkpasswd(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
+/* m_mkpasswd - mkpasswd message handler
+ *     parv[1] = password
+ *     parv[2] = type
+ */
+static void
+m_mkpasswd(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
 {
        static time_t last_used = 0;
-       int is_md5 = 0;
+       char *salt;
+       const char *crypted;
+       const char *hashtype;
+       const char hashdefault[] = "SHA512";
+
+       if(EmptyString(parv[1]))
+       {
+               sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "MKPASSWD");
+               return;
+       }
+
+       if(parc < 3)
+               hashtype = hashdefault;
+       else
+               hashtype = parv[2];
 
        if((last_used + ConfigFileEntry.pace_wait) > rb_current_time())
        {
                /* safe enough to give this on a local connect only */
-               sendto_one(source_p, form_str(RPL_LOAD2HI), me.name, parv[0]);
-               return 0;
+               sendto_one(source_p, form_str(RPL_LOAD2HI), me.name, source_p->name, "MKPASSWD");
+               return;
        }
        else
-       {
                last_used = rb_current_time();
-       }
 
-       if(parc == 3)
+       if(!irccmp(hashtype, "SHA256"))
+               salt = make_sha256_salt(16);
+       else if(!irccmp(hashtype, "SHA512"))
+               salt = make_sha512_salt(16);
+       else if(!irccmp(hashtype, "MD5"))
+               salt = make_md5_salt(8);
+       else
        {
-               if(!irccmp(parv[2], "MD5"))
-               {
-                       is_md5 = 1;
-               }
-               else if(!irccmp(parv[2], "DES"))
-               {
-                       /* Not really needed, but we may want to have a default encryption
-                        * setting somewhere down the road
-                        */
-                       is_md5 = 0;
-               }
-               else
-               {
-                       sendto_one_notice(source_p, ":MKPASSWD syntax error:  MKPASSWD pass [DES|MD5]");
-                       return 0;
-               }
+               sendto_one_notice(source_p,
+                                 ":MKPASSWD syntax error:  MKPASSWD pass [SHA256|SHA512|MD5]");
+               return;
        }
 
-       if(parc == 1)
-               sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "MKPASSWD");
-       else
-               sendto_one_notice(source_p, ":Encryption for [%s]:  %s",
-                          parv[1], rb_crypt(parv[1],
-                                                           is_md5 ? make_md5_salt() :
-                                                           make_salt()));
-
-       return 0;
+       crypted = rb_crypt(parv[1], salt);
+       sendto_one_notice(source_p, ":Hash [%s] for %s: %s", hashtype, parv[1], crypted ? crypted : "???");
 }
 
-/*
-** mo_test
-**      parv[0] = sender prefix
-**      parv[1] = parameter
-*/
-static int
-mo_mkpasswd(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
+/* mo_mkpasswd - mkpasswd message handler
+ *     parv[1] = password
+ *     parv[2] = type
+ */
+static void
+mo_mkpasswd(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
 {
-       int is_md5 = 0;
+       char *salt;
+       const char *crypted;
+       const char *hashtype;
+       const char hashdefault[] = "SHA512";
 
-       if(parc == 3)
+       if(EmptyString(parv[1]))
        {
-               if(!irccmp(parv[2], "MD5"))
-               {
-                       is_md5 = 1;
-               }
-               else if(!irccmp(parv[2], "DES"))
-               {
-                       /* Not really needed, but we may want to have a default encryption
-                        * setting somewhere down the road
-                        */
-                       is_md5 = 0;
-               }
-               else
-               {
-                       sendto_one_notice(source_p,
-                                  ":MKPASSWD syntax error:  MKPASSWD pass [DES|MD5]");
-                       return 0;
-               }
+               sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "MKPASSWD");
+               return;
        }
 
-       if(parc == 1)
-               sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "MKPASSWD");
+       if(parc < 3)
+               hashtype = hashdefault;
        else
-               sendto_one_notice(source_p, ":Encryption for [%s]:  %s",
-                          parv[1], rb_crypt(parv[1], is_md5 ? make_md5_salt() : make_salt()));
+               hashtype = parv[2];
+
+       if(!irccmp(hashtype, "SHA256"))
+               salt = make_sha256_salt(16);
+       else if(!irccmp(hashtype, "SHA512"))
+               salt = make_sha512_salt(16);
+       else if(!irccmp(hashtype, "MD5"))
+               salt = make_md5_salt(8);
+       else
+       {
+               sendto_one_notice(source_p,
+                                 ":MKPASSWD syntax error:  MKPASSWD pass [SHA256|SHA512|MD5]");
+               return;
+       }
 
-       return 0;
+       crypted = rb_crypt(parv[1], salt);
+       sendto_one_notice(source_p, ":Hash [%s] for %s: %s", hashtype, parv[1], crypted ? crypted : "???");
 }
 
-static char *
-make_salt(void)
+char *
+make_md5_salt(int length)
 {
-       static char salt[3];
-       salt[0] = saltChars[random() % 64];
-       salt[1] = saltChars[random() % 64];
-       salt[2] = '\0';
+       static char salt[21];
+       if(length > 16)
+       {
+               printf("MD5 salt length too long\n");
+               exit(0);
+       }
+       salt[0] = '$';
+       salt[1] = '1';
+       salt[2] = '$';
+       generate_random_salt(&salt[3], length);
+       salt[length + 3] = '$';
+       salt[length + 4] = '\0';
        return salt;
 }
 
-static char *
-make_md5_salt(void)
+char *
+make_sha256_salt(int length)
 {
-       static char salt[13];
-       int i;
+       static char salt[21];
+       if(length > 16)
+       {
+               printf("SHA256 salt length too long\n");
+               exit(0);
+       }
        salt[0] = '$';
-       salt[1] = '1';
+       salt[1] = '5';
        salt[2] = '$';
-       for(i = 3; i < 11; i++)
-               salt[i] = saltChars[random() % 64];
-       salt[11] = '$';
-       salt[12] = '\0';
+       generate_random_salt(&salt[3], length);
+       salt[length + 3] = '$';
+       salt[length + 4] = '\0';
        return salt;
 }
+
+char *
+make_sha512_salt(int length)
+{
+       static char salt[21];
+       if(length > 16)
+       {
+               printf("SHA512 salt length too long\n");
+               exit(0);
+       }
+       salt[0] = '$';
+       salt[1] = '6';
+       salt[2] = '$';
+       generate_random_salt(&salt[3], length);
+       salt[length + 3] = '$';
+       salt[length + 4] = '\0';
+       return salt;
+}
+
+char *
+generate_poor_salt(char *salt, int length)
+{
+       int i;
+
+       srand(time(NULL));
+       for(i = 0; i < length; i++)
+               salt[i] = saltChars[rand() % 64];
+
+       return (salt);
+}
+
+char *
+generate_random_salt(char *salt, int length)
+{
+       int fd, i;
+
+       if((fd = open("/dev/urandom", O_RDONLY)) < 0)
+               return (generate_poor_salt(salt, length));
+
+       if(read(fd, salt, (size_t)length) != length)
+       {
+               close(fd);
+               return (generate_poor_salt(salt, length));
+       }
+
+       for(i = 0; i < length; i++)
+               salt[i] = saltChars[abs(salt[i]) % 64];
+
+       close(fd);
+       return (salt);
+}