]> jfr.im git - irc/rqf/shadowircd.git/blob - extensions/m_mkpasswd.c
Overhaul extensions/m_mkpasswd. It now allows SHA256/SHA512 hashes. DES support is...
[irc/rqf/shadowircd.git] / extensions / m_mkpasswd.c
1 /*
2 * m_mkpasswd.c: Encrypts a password online.
3 *
4 * Based on mkpasswd.c, originally by Nelson Minar (minar@reed.edu)
5 * You can use this code in any way as long as these names remain.
6 *
7 */
8
9 #include "stdinc.h"
10 #include "client.h"
11 #include "numeric.h"
12 #include "s_conf.h"
13 #include "modules.h"
14
15 #include <string.h>
16
17 static int m_mkpasswd(struct Client *client_p, struct Client *source_p,
18 int parc, const char *parv[]);
19 static int mo_mkpasswd(struct Client *client_p, struct Client *source_p,
20 int parc, const char *parv[]);
21
22 static char *make_md5_salt(int);
23 static char *make_sha256_salt(int);
24 static char *make_sha512_salt(int);
25 static char *generate_random_salt(char *, int);
26 static char *generate_poor_salt(char *, int);
27
28 static char saltChars[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
29 /* 0 .. 63, ascii - 64 */
30
31 struct Message mkpasswd_msgtab = {
32 "MKPASSWD", 0, 0, 0, MFLG_SLOW,
33 {mg_unreg, {m_mkpasswd, 2}, mg_ignore, mg_ignore, mg_ignore, {mo_mkpasswd, 2}}
34 };
35
36 mapi_clist_av1 mkpasswd_clist[] = { &mkpasswd_msgtab, NULL };
37
38 DECLARE_MODULE_AV1(mkpasswd, NULL, NULL, mkpasswd_clist, NULL, NULL, "$Revision$");
39
40
41 /* m_mkpasswd - mkpasswd message handler
42 * parv[1] = password
43 * parv[2] = type
44 */
45 static int
46 m_mkpasswd(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
47 {
48 static time_t last_used = 0;
49 char *salt;
50 const char *hashtype;
51 const char hashdefault[] = "SHA512";
52
53 if(EmptyString(parv[1]))
54 {
55 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "MKPASSWD");
56 return 0;
57 }
58
59 if(parc < 3)
60 hashtype = hashdefault;
61 else
62 hashtype = parv[2];
63
64 if((last_used + ConfigFileEntry.pace_wait) > rb_current_time())
65 {
66 /* safe enough to give this on a local connect only */
67 sendto_one(source_p, form_str(RPL_LOAD2HI), me.name, source_p->name, "MKPASSWD");
68 return 0;
69 }
70 else
71 last_used = rb_current_time();
72
73 if(!irccmp(hashtype, "SHA256"))
74 salt = make_sha256_salt(16);
75 else if(!irccmp(hashtype, "SHA512"))
76 salt = make_sha512_salt(16);
77 else if(!irccmp(hashtype, "MD5"))
78 salt = make_md5_salt(8);
79 else
80 {
81 sendto_one_notice(source_p,
82 ":MKPASSWD syntax error: MKPASSWD pass [SHA256|SHA512|MD5]");
83 return 0;
84 }
85
86 sendto_one_notice(source_p, ":Hash [%s] for %s: %s", hashtype, parv[1], rb_crypt(parv[1], salt));
87 return 0;
88 }
89
90 /* mo_mkpasswd - mkpasswd message handler
91 * parv[1] = password
92 * parv[2] = type
93 */
94 static int
95 mo_mkpasswd(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
96 {
97 char *salt;
98 const char *hashtype;
99 const char hashdefault[] = "SHA512";
100
101 if(EmptyString(parv[1]))
102 {
103 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "MKPASSWD");
104 return 0;
105 }
106
107 if(parc < 3)
108 hashtype = hashdefault;
109 else
110 hashtype = parv[2];
111
112 if(!irccmp(hashtype, "SHA256"))
113 salt = make_sha256_salt(16);
114 else if(!irccmp(hashtype, "SHA512"))
115 salt = make_sha512_salt(16);
116 else if(!irccmp(hashtype, "MD5"))
117 salt = make_md5_salt(8);
118 else
119 {
120 sendto_one_notice(source_p,
121 ":MKPASSWD syntax error: MKPASSWD pass [SHA256|SHA512|MD5]");
122 return 0;
123 }
124
125 sendto_one_notice(source_p, ":Hash [%s] for %s: %s", hashtype, parv[1], rb_crypt(parv[1], salt));
126 return 0;
127 }
128
129 char *
130 make_md5_salt(int length)
131 {
132 static char salt[21];
133 if(length > 16)
134 {
135 printf("MD5 salt length too long\n");
136 exit(0);
137 }
138 salt[0] = '$';
139 salt[1] = '1';
140 salt[2] = '$';
141 generate_random_salt(&salt[3], length);
142 salt[length + 3] = '$';
143 salt[length + 4] = '\0';
144 return salt;
145 }
146
147 char *
148 make_sha256_salt(int length)
149 {
150 static char salt[21];
151 if(length > 16)
152 {
153 printf("SHA256 salt length too long\n");
154 exit(0);
155 }
156 salt[0] = '$';
157 salt[1] = '5';
158 salt[2] = '$';
159 generate_random_salt(&salt[3], length);
160 salt[length + 3] = '$';
161 salt[length + 4] = '\0';
162 return salt;
163 }
164
165 char *
166 make_sha512_salt(int length)
167 {
168 static char salt[21];
169 if(length > 16)
170 {
171 printf("SHA512 salt length too long\n");
172 exit(0);
173 }
174 salt[0] = '$';
175 salt[1] = '6';
176 salt[2] = '$';
177 generate_random_salt(&salt[3], length);
178 salt[length + 3] = '$';
179 salt[length + 4] = '\0';
180 return salt;
181 }
182
183 char *
184 generate_poor_salt(char *salt, int length)
185 {
186 int i;
187 srand(time(NULL));
188 for(i = 0; i < length; i++)
189 {
190 salt[i] = saltChars[rand() % 64];
191 }
192 return (salt);
193 }
194
195 char *
196 generate_random_salt(char *salt, int length)
197 {
198 char *buf;
199 int fd, i;
200 if((fd = open("/dev/random", O_RDONLY)) < 0)
201 {
202 return (generate_poor_salt(salt, length));
203 }
204 buf = calloc(1, length);
205 if(read(fd, buf, length) != length)
206 {
207 free(buf);
208 return (generate_poor_salt(salt, length));
209 }
210
211 for(i = 0; i < length; i++)
212 {
213 salt[i] = saltChars[abs(buf[i]) % 64];
214 }
215 free(buf);
216 return (salt);
217 }