]> jfr.im git - irc/quakenet/newserv.git/blame - chanserv/chanserv_relay.c
LUA: port luadb to dbapi2 to drop postgres dependency
[irc/quakenet/newserv.git] / chanserv / chanserv_relay.c
CommitLineData
354b3c0a
CP
1#include "chanserv.h"
2#include "../control/control.h"
7f32dbdf 3#include "../lib/version.h"
07bed5f4 4#include "../lib/irc_string.h"
d96acfa8
CP
5#include "../core/config.h"
6#include "../lib/hmac.h"
7#include "../lib/strlfunc.h"
8#include "../lib/cbc.h"
07bed5f4
CP
9#include "authlib.h"
10
11#include <stdio.h>
12#include <string.h>
7f32dbdf 13
d96acfa8
CP
14#define KEY_BITS 256
15#define BLOCK_SIZE 16
16
7f32dbdf 17MODULE_VERSION(QVERSION);
354b3c0a
CP
18
19int csa_docheckhashpass(void *source, int cargc, char **cargv);
07bed5f4
CP
20int csa_docreateaccount(void *source, int cargc, char **cargv);
21int csa_dosettempemail(void *source, int cargc, char **cargv);
8f129eab 22int csa_dosetemail(void *source, int cargc, char **cargv);
07bed5f4
CP
23int csa_doresendemail(void *source, int cargc, char **cargv);
24int csa_doactivateuser(void *source, int cargc, char **cargv);
bdeb548f 25int csa_doaddchan(void *source, int argc, char **argv);
1b75afa4
CP
26int csa_doremoteauth(void *source, int argc, char **argv);
27
d96acfa8
CP
28static int decrypt_password(unsigned char *secret, int keybits, char *buf, int bufsize, char *encrypted);
29static int hex_to_int(char *input, unsigned char *buf, int buflen);
30
31static unsigned char createaccountsecret[KEY_BITS / 8];
32static int createaccountsecret_ok = 0;
33
34static unsigned char hexlookup[256] = {
35 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
36 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
37 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
38 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
39 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01,
40 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xff, 0xff,
41 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
42 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
43 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
44 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x0b, 0x0c,
45 0x0d, 0x0e, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
46 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
47 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
48 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
49 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
50 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
51 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
52 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
53 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
54 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
55 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
56 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
57 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
58 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
59 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
60 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
61 };
354b3c0a 62
7e032dc6
CP
63static void relayfinishinit(int, void *);
64
65void relayfinishinit(int hooknum, void *arg) {
d96acfa8
CP
66 sstring *s;
67
7e032dc6
CP
68 deregisterhook(HOOK_CHANSERV_DBLOADED, relayfinishinit);
69
354b3c0a 70 registercontrolhelpcmd("checkhashpass", NO_RELAY, 3, csa_docheckhashpass, "Usage: checkhashpass <username> <digest> ?junk?");
b86998d2 71 registercontrolhelpcmd("settempemail", NO_RELAY, 2, csa_dosettempemail, "Usage: settempemail <userid> <email address>");
8f129eab 72 registercontrolhelpcmd("setemail", NO_RELAY, 3, csa_dosetemail, "Usage: setmail <userid> <timestamp> <email address>");
b86998d2
CP
73 registercontrolhelpcmd("resendemail", NO_RELAY, 1, csa_doresendemail, "Usage: resendemail <userid>");
74 registercontrolhelpcmd("activateuser", NO_RELAY, 1, csa_doactivateuser, "Usage: activateuser <userid>");
bdeb548f 75 registercontrolhelpcmd("addchan", NO_RELAY, 3, csa_doaddchan, "Usage: addchan <channel> <userid> <channel type>");
1b75afa4 76 registercontrolhelpcmd("remoteauth", NO_RELAY, 6, csa_doremoteauth, "Usage: remoteauth <username> <digest> <junk> <nick> <ident> <host>");
d96acfa8
CP
77
78 s=getcopyconfigitem("chanserv","createaccountsecret","",128);
79 if(!s || !s->content || !s->content[0]) {
80 Error("chanserv_relay",ERR_WARNING,"createaccountsecret not set, createaccount disabled.");
81 } else if(s->length != KEY_BITS / 8 * 2 || !hex_to_int(s->content, createaccountsecret, sizeof(createaccountsecret))) {
82 Error("chanserv_relay",ERR_WARNING,"createaccountsecret must be a %d character hex string.", KEY_BITS / 8 * 2);
83 } else {
8f129eab 84 registercontrolhelpcmd("createaccount", NO_RELAY, 5, csa_docreateaccount, "Usage: createaccount <execute> <username> <email address> <encrypted password> <activate user>");
d96acfa8
CP
85 createaccountsecret_ok = 1;
86 }
87
88 freesstring(s);
354b3c0a
CP
89}
90
7e032dc6
CP
91void _init(void) {
92 registerhook(HOOK_CHANSERV_DBLOADED, relayfinishinit);
93
94 if(chanservdb_ready)
95 relayfinishinit(HOOK_CHANSERV_DBLOADED, NULL);
96}
97
354b3c0a
CP
98void _fini(void) {
99 deregistercontrolcmd("checkhashpass", csa_docheckhashpass);
07bed5f4 100 deregistercontrolcmd("settempemail", csa_dosettempemail);
8f129eab 101 deregistercontrolcmd("setemail", csa_dosetemail);
07bed5f4
CP
102 deregistercontrolcmd("resendemail", csa_doresendemail);
103 deregistercontrolcmd("activateuser", csa_doactivateuser);
bdeb548f 104 deregistercontrolcmd("addchan", csa_doaddchan);
d96acfa8
CP
105
106 if(createaccountsecret_ok)
107 deregistercontrolcmd("createaccount", csa_docreateaccount);
7e032dc6
CP
108
109 deregisterhook(HOOK_CHANSERV_DBLOADED, relayfinishinit);
354b3c0a
CP
110}
111
112int csa_docheckhashpass(void *source, int cargc, char **cargv) {
113 nick *sender=(nick *)source;
caee16ec 114 reguser *rup;
354b3c0a
CP
115 char *flags;
116
117 if(cargc<3) {
118 controlreply(sender, "CHECKHASHPASS FAIL args");
119 return CMD_ERROR;
120 }
121
122 if (!(rup=findreguserbynick(cargv[0]))) {
123 controlreply(sender, "CHECKHASHPASS FAIL user");
124 return CMD_OK;
125 }
126
127 flags = printflags(QUFLAG_ALL & rup->flags, ruflags);
128 if(UHasSuspension(rup)) {
129 controlreply(sender, "CHECKHASHPASS FAIL suspended %s %s %u", rup->username, flags, rup->ID);
caee16ec
CP
130 } else if(UIsInactive(rup)) {
131 controlreply(sender, "CHECKHASHPASS FAIL inactive %s %s %u", rup->username, flags, rup->ID);
354b3c0a
CP
132 } else if(!checkhashpass(rup, cargc<3?NULL:cargv[2], cargv[1])) {
133 controlreply(sender, "CHECKHASHPASS FAIL digest %s %s %u", rup->username, flags, rup->ID);
134 } else {
135 controlreply(sender, "CHECKHASHPASS OK %s %s %u %s", rup->username, flags, rup->ID, rup->email?rup->email->content:"-");
136 }
137
138 return CMD_OK;
139}
07bed5f4 140
1b75afa4 141static void controlremotereply(nick *target, char *message) {
7a82c606 142 controlreply(target, "REMOTEAUTH FAILTEXT %s", message);
1b75afa4
CP
143}
144
145static void remote_reply(nick *sender, int message_id, ...) {
146 va_list va;
147 va_start(va, message_id);
7a82c606 148 chanservstdvmessage(sender, NULL, message_id, -1 * (int)(strlen("REMOTEAUTH FAILTEXT ")), controlremotereply, va);
1b75afa4
CP
149 va_end(va);
150}
151
152int csa_doremoteauth(void *source, int cargc, char **cargv) {
153 nick *sender=(nick *)source;
154 reguser *rup;
155
156 if(cargc<6) {
7a82c606 157 controlreply(sender, "REMOTEAUTH FAILREASON args");
1b75afa4
CP
158 return CMD_ERROR;
159 }
160
161 char *account = cargv[0];
162 char *digest = cargv[1];
163 char *junk = cargv[2];
164 char *nick = cargv[3];
165 char *ident = cargv[4];
166 char *hostname = cargv[5];
167
168 if (!(rup=findreguserbynick(account))) {
7a82c606 169 controlreply(sender, "REMOTEAUTH FAILREASON user");
1b75afa4
CP
170 return CMD_ERROR;
171 }
172
173 if(!checkhashpass(rup, junk, digest)) {
7a82c606 174 controlreply(sender, "REMOTEAUTH FAILREASON digest");
1b75afa4
CP
175 return CMD_ERROR;
176 }
177
178 if (!csa_completeauth2(rup, nick, ident, hostname, "REMOTEAUTH", remote_reply, sender)) {
179 controlreply(sender, "REMOTEAUTH END");
180 return CMD_ERROR;
181 }
182
183 /* username:ts:authid */
184 controlreply(sender, "REMOTEAUTH OK %s %ld %ld", rup->username, rup->lastauth ? rup->lastauth : getnettime(), rup->ID);
185
186 /* note: NO HOOK_CHANSERV_AUTH */
187
188 return CMD_OK;
189}
190
07bed5f4
CP
191static char *email_to_error(char *email) {
192 maildomain *mdp, *smdp;
193 char *local;
194 char *dupemail;
195 int found = 0;
196 maillock *mlp;
197 reguser *ruh;
198
3cfa791f 199 switch(csa_checkeboy_r(email)) {
07bed5f4 200 case -1: break;
3cfa791f
CP
201 case QM_EMAILTOOSHORT: return "emailshort";
202 case QM_EMAILNOAT: return "emailinvalid";
203 case QM_EMAILATEND: return "emailinvalid";
204 case QM_EMAILINVCHR: return "emailinvalid";
205 case QM_NOTYOUREMAIL: return "emailnotyours";
206 case QM_INVALIDEMAIL: return "emailinvalid";
207 default: return "emailunknown";
07bed5f4
CP
208 }
209
210 /* maildomain BS... c&p from hello.c */
211 for(mlp=maillocks;mlp;mlp=mlp->next) {
212 if(!match(mlp->pattern->content, email)) {
3cfa791f 213 return "emaillocked";
07bed5f4
CP
214 }
215 }
216
217 dupemail = strdup(email);
218 local=strchr(dupemail, '@');
219 if(!local) {
220 free(dupemail);
3cfa791f 221 return "emailunknown";
07bed5f4
CP
222 }
223 *(local++)='\0';
224
225 mdp=findnearestmaildomain(local);
226 if(mdp) {
227 for(smdp=mdp; smdp; smdp=smdp->parent) {
228 if(MDIsBanned(smdp)) {
229 free(dupemail);
3cfa791f 230 return "emaillocked";
07bed5f4
CP
231 }
232 if((smdp->count >= smdp->limit) && (smdp->limit > 0)) {
233 free(dupemail);
3cfa791f 234 return "emaildomainlimit";
07bed5f4
CP
235 }
236 }
237 }
238
239 mdp=findmaildomainbydomain(local);
240 if(mdp) {
241 for (ruh=mdp->users; ruh; ruh=ruh->nextbydomain) {
242 if (ruh->localpart)
243 if (!strcasecmp(dupemail, ruh->localpart->content)) {
244 found++;
245 }
246 }
247
248 if((found >= mdp->actlimit) && (mdp->actlimit > 0)) {
249 free(dupemail);
3cfa791f 250 return "emailaddresslimit";
07bed5f4
CP
251 }
252 }
253
2fd779e3
GB
254 free(dupemail);
255
07bed5f4
CP
256 return NULL;
257}
258
259static void sendemail(reguser *rup) {
260 csdb_createmail(rup, QMAIL_ACTIVATEEMAIL);
261}
262
263int csa_docreateaccount(void *source, int cargc, char **cargv) {
264 nick *sender=(nick *)source;
265 int execute;
266 char *error_username = NULL, *error_password = NULL, *error_email = NULL;
267 char *username = NULL, *password = NULL, *email = NULL;
b86998d2 268 char account_info[512];
d96acfa8 269 char passbuf[512];
07bed5f4 270 int do_create;
8f129eab 271 int activate;
07bed5f4 272
8f129eab 273 if(cargc<5) {
07bed5f4
CP
274 controlreply(sender, "CREATEACCOUNT FALSE args");
275 return CMD_ERROR;
276 }
277
278 execute = cargv[0][0] == '1';
279 if(strcmp(cargv[1], "0"))
280 username = cargv[1];
281 if(strcmp(cargv[2], "0"))
282 email = cargv[2];
d96acfa8
CP
283 if(strcmp(cargv[3], "0")) {
284 int errorcode = decrypt_password(createaccountsecret, KEY_BITS, passbuf, sizeof(passbuf), cargv[3]);
285 if(errorcode) {
286 Error("chanserv_relay",ERR_WARNING,"createaccount unable to decrypt password, error code: %d", errorcode);
287 controlreply(sender, "CREATEACCOUNT FALSE args");
288 return CMD_ERROR;
289 }
290 password = passbuf;
291 }
8f129eab 292 activate = cargv[4][0] == '1';
07bed5f4
CP
293
294 if(username) {
295 if (findreguserbynick(username)) {
3cfa791f 296 error_username = "usernameinuse";
07bed5f4 297 } else if(csa_checkaccountname_r(username)) {
3cfa791f 298 error_username = "usernameinvalid";
07bed5f4
CP
299 }
300 }
301
302 if(email)
303 error_email = email_to_error(email);
304
305 if(password) {
306 int r = csa_checkpasswordquality(password);
307 if(r == QM_PWTOSHORT) {
3cfa791f 308 error_password = "passwordshort";
14dc6de9
CP
309 } else if(r == QM_PWTOLONG) {
310 error_password = "passwordlong";
07bed5f4 311 } else if(r == QM_PWTOWEAK) {
3cfa791f 312 error_password = "passwordweak";
fc03eb2d
CP
313 } else if(r == QM_PWINVALID) {
314 error_password = "passwordinvalid";
07bed5f4 315 } else if(r != -1) {
3cfa791f 316 error_password = "passwordunknown";
07bed5f4
CP
317 }
318 }
319
320 if(execute && email && password && username && !error_email && !error_password && !error_username) {
321 reguser *rup;
322 do_create = 1;
323
324 rup = csa_createaccount(username, password, email);
07bed5f4 325
8f129eab
CP
326 if(!activate)
327 USetInactive(rup);
328
329 cs_log(sender,"CREATEACCOUNT created auth %s (%s) %s",rup->username,rup->email->content,activate?"(active)": "(inactive)");
07bed5f4 330 csdb_createuser(rup);
8f129eab 331 snprintf(account_info, sizeof(account_info), " %u %lu", rup->ID, (unsigned long)rup->lastpasschange);
07bed5f4 332
46a359b5
CP
333 if(!activate)
334 sendemail(rup);
07bed5f4 335 } else {
b86998d2 336 account_info[0] = '\0';
07bed5f4
CP
337 do_create = 0;
338 }
339
b86998d2 340 controlreply(sender, "CREATEACCOUNT %s%s%s%s%s%s%s%s",
07bed5f4 341 do_create ? "TRUE" : "FALSE",
b86998d2 342 account_info,
3cfa791f
CP
343 email && error_email ? " " : "", email && error_email ? error_email : "",
344 password && error_password ? " " : "", password && error_password ? error_password : "",
345 username && error_username ? " " : "", username && error_username ? error_username : ""
07bed5f4
CP
346 );
347
348 return CMD_OK;
349}
350
351int csa_dosettempemail(void *source, int cargc, char **cargv) {
352 char *email;
353 char *error;
354 reguser *rup;
355 nick *sender=(nick *)source;
356
357 if(cargc<2) {
358 controlreply(sender, "SETTEMPEMAIL FALSE args");
359 return CMD_ERROR;
360 }
361
b86998d2 362 rup = findreguserbyID(atoi(cargv[0]));
07bed5f4 363 if(rup == NULL) {
b86998d2 364 controlreply(sender, "SETTEMPEMAIL FALSE useridnotexist");
07bed5f4
CP
365 return CMD_ERROR;
366 }
367
368 if(!UIsInactive(rup)) {
3cfa791f 369 controlreply(sender, "SETTEMPEMAIL FALSE accountactive");
07bed5f4
CP
370 return CMD_ERROR;
371 }
372
373 email = cargv[1];
374 error = email_to_error(email);
375 if(error) {
376 controlreply(sender, "SETTEMPEMAIL FALSE %s", error);
377 return CMD_ERROR;
378 }
379
380 freesstring(rup->email);
381 rup->email=getsstring(email,EMAILLEN);
382 cs_log(sender,"SETTEMPEMAIL OK username %s email %s",rup->username, rup->email->content);
383
384 csdb_updateuser(rup);
385 sendemail(rup);
386
387 controlreply(sender, "SETTEMPEMAIL TRUE");
388
389 return CMD_OK;
390}
391
8f129eab
CP
392int csa_dosetemail(void *source, int cargc, char **cargv) {
393 char *email;
394 char *error;
395 reguser *rup;
396 nick *sender=(nick *)source;
397
398 if(cargc<3) {
399 controlreply(sender, "SETEMAIL FALSE args");
400 return CMD_ERROR;
401 }
402
403 rup = findreguserbyID(atoi(cargv[0]));
404 if(rup == NULL) {
405 controlreply(sender, "SETEMAIL FALSE useridnotexist");
406 return CMD_ERROR;
407 }
408
409 if(UHasStaffPriv(rup)) {
410 controlreply(sender, "SETEMAIL FALSE privuser");
411 return CMD_ERROR;
412 }
413
414 if(UHasSuspension(rup)) {
415 controlreply(sender, "SETEMAIL FALSE suspended");
416 return CMD_ERROR;
417 }
418
419 if(rup->lastpasschange > atoi(cargv[1])) {
420 controlreply(sender, "SETEMAIL FALSE passwordchanged");
421 return CMD_ERROR;
422 }
423
424 email = cargv[2];
46a359b5
CP
425
426 if(!strcmp(email, rup->email->content)) {
427 /* setting to the same thing? fine! */
428 controlreply(sender, "SETEMAIL TRUE");
429 return CMD_OK;
430 }
431
8f129eab
CP
432 error = email_to_error(email);
433 if(error) {
434 controlreply(sender, "SETEMAIL FALSE %s", error);
435 return CMD_ERROR;
436 }
437
438 freesstring(rup->email);
439 rup->email=getsstring(email,EMAILLEN);
440 cs_log(sender,"SETEMAIL OK username %s email %s",rup->username, rup->email->content);
441
442 csdb_updateuser(rup);
8f129eab
CP
443
444 controlreply(sender, "SETEMAIL TRUE");
445
446 return CMD_OK;
447}
448
07bed5f4
CP
449int csa_doresendemail(void *source, int cargc, char **cargv) {
450 reguser *rup;
451 nick *sender=(nick *)source;
452
453 if(cargc<1) {
454 controlreply(sender, "RESENDEMAIL FALSE args");
455 return CMD_ERROR;
456 }
457
b86998d2 458 rup = findreguserbyID(atoi(cargv[0]));
07bed5f4 459 if(rup == NULL) {
b86998d2 460 controlreply(sender, "RESENDEMAIL FALSE useridnotexist");
07bed5f4
CP
461 return CMD_ERROR;
462 }
463
464 if(!UIsInactive(rup)) {
3cfa791f 465 controlreply(sender, "RESENDEMAIL FALSE accountactive");
07bed5f4
CP
466 return CMD_ERROR;
467 }
468
469 sendemail(rup);
470 controlreply(sender, "RESENDEMAIL TRUE");
471 cs_log(sender,"RESENDEMAIL OK username %s",rup->username);
472
473 return CMD_OK;
474}
475
476int csa_doactivateuser(void *source, int cargc, char **cargv) {
477 reguser *rup;
478 nick *sender=(nick *)source;
479
480 if(cargc<1) {
481 controlreply(sender, "ACTIVATEUSER FALSE args");
482 return CMD_ERROR;
483 }
484
b86998d2 485 rup = findreguserbyID(atoi(cargv[0]));
07bed5f4 486 if(rup == NULL) {
b86998d2 487 controlreply(sender, "ACTIVATEUSER FALSE useridnotexist");
07bed5f4
CP
488 return CMD_ERROR;
489 }
490
491 if(!UIsInactive(rup)) {
3cfa791f 492 controlreply(sender, "ACTIVATEUSER FALSE accountactive");
07bed5f4
CP
493 return CMD_ERROR;
494 }
495
496 UClearInactive(rup);
497 csdb_updateuser(rup);
498
499 cs_log(sender,"ACTIVATEUSER OK username %s",rup->username);
500 controlreply(sender, "ACTIVATEUSER TRUE");
501
502 return CMD_OK;
503}
d96acfa8 504
bdeb548f
CP
505int csa_doaddchan(void *source, int cargc, char **cargv) {
506 nick *sender=(nick *)source;
507 reguser *rup = getreguserfromnick(sender), *founder;
508 chanindex *cip;
509 short type;
510 regchan *rcp;
511
512 if(cargc<3) {
513 controlreply(sender, "ADDCHAN FALSE args");
514 return CMD_ERROR;
515 }
516
517 if (*cargv[0] != '#' || strlen(cargv[0]) > CHANNELLEN) {
518 controlreply(sender, "ADDCHAN FALSE invalidchannel");
519 return CMD_ERROR;
520 }
521
522 if (!(cip=findorcreatechanindex(cargv[0]))) {
523 controlreply(sender, "ADDCHAN FALSE invalidchannel");
524 return CMD_ERROR;
525 }
526
527 founder = findreguserbyID(atoi(cargv[1]));
528 if(founder == NULL) {
529 controlreply(sender, "ADDCHAN FALSE useridnotexist");
530 return CMD_ERROR;
531 }
532
533 if(UIsInactive(founder)) {
534 controlreply(sender, "ADDCHAN FALSE accountinactive");
535 return CMD_ERROR;
536 }
537
538 for(type=CHANTYPES-1;type;type--)
539 if(!ircd_strcmp(chantypes[type]->content, cargv[2]))
540 break;
541
542 if(!type) {
543 controlreply(sender, "ADDCHAN FALSE invalidchantype");
544 return CMD_ERROR;
545 }
546
08d06cd8 547 rcp = cs_addchan(cip, sender, rup, founder, QCFLAG_JOINED | QCFLAG_AUTOOP | QCFLAG_BITCH | QCFLAG_FORCETOPIC | QCFLAG_PROTECT | QCFLAG_TOPICSAVE, CHANMODE_NOCTCP | CHANMODE_DELJOINS | CHANMODE_MODNOAUTH | CHANMODE_NONOTICE | CHANMODE_NOEXTMSG | CHANMODE_SINGLETARG | CHANMODE_TOPICLIMIT | CHANMODE_NOQUITMSG, 0, type);
bdeb548f
CP
548 if(!rcp) {
549 controlreply(sender, "ADDCHAN FALSE alreadyregistered");
550 return CMD_ERROR;
551 }
552
553 cs_log(sender, "ADDCHAN %s #%s %s %s", cip->name->content, founder->username, printflags(rcp->flags, rcflags), chantypes[type]->content);
e67c3226 554 controlreply(sender, "ADDCHAN TRUE %u", rcp->ID);
bdeb548f
CP
555 return CMD_OK;
556}
557
d96acfa8
CP
558static int hex_to_int(char *input, unsigned char *buf, int buflen) {
559 int i;
560 for(i=0;i<buflen;i++) {
561 if((0xff == hexlookup[(int)input[i * 2]]) || (0xff == hexlookup[(int)input[i * 2 + 1]])) {
562 return 0;
563 } else {
564 buf[i] = (hexlookup[(int)input[i * 2]] << 4) | hexlookup[(int)input[i * 2 + 1]];
565 }
566 }
567 return 1;
568}
569
570static int decrypt_password(unsigned char *secret, int keybits, char *buf, int bufsize, char *encrypted) {
571 size_t ciphertextlen, datalen;
572 unsigned char iv[BLOCK_SIZE];
573 rijndaelcbc *c;
574 int i, j;
575
576 datalen = strlen(encrypted);
577 if(datalen % 2 != 0)
578 return 1;
579 if(datalen < BLOCK_SIZE * 2 * 2)
580 return 2;
581
582 if(!hex_to_int(encrypted, iv, BLOCK_SIZE))
583 return 3;
584
585 ciphertextlen = (datalen - (BLOCK_SIZE * 2)) / 2;
586 if(ciphertextlen > bufsize || ciphertextlen % BLOCK_SIZE != 0)
587 return 4;
588
589 if(!hex_to_int(encrypted + BLOCK_SIZE * 2, (unsigned char *)buf, ciphertextlen))
590 return 5;
591
592 c = rijndaelcbc_init(secret, keybits, iv, 1);
593
594 for(i=0;i<ciphertextlen;i+=BLOCK_SIZE) {
595 char *p = &buf[i];
596 unsigned char *r = rijndaelcbc_decrypt(c, (unsigned char *)p);
597 memcpy(p, r, BLOCK_SIZE);
598
599 for(j=0;j<BLOCK_SIZE;j++) {
600 if(*(p + j) == '\0') {
601 rijndaelcbc_free(c);
602 return 0;
603 }
604 }
605 }
606
607 rijndaelcbc_free(c);
608 return 6;
609}