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