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