]>
jfr.im git - irc/quakenet/newserv.git/blob - chanserv/chanserv_relay.c
2 #include "../control/control.h"
3 #include "../lib/version.h"
4 #include "../lib/irc_string.h"
5 #include "../core/config.h"
6 #include "../lib/hmac.h"
7 #include "../lib/strlfunc.h"
8 #include "../lib/cbc.h"
17 MODULE_VERSION(QVERSION
);
19 int csa_docheckhashpass(void *source
, int cargc
, char **cargv
);
20 int csa_docreateaccount(void *source
, int cargc
, char **cargv
);
21 int csa_dosettempemail(void *source
, int cargc
, char **cargv
);
22 int csa_dosetemail(void *source
, int cargc
, char **cargv
);
23 int csa_doresendemail(void *source
, int cargc
, char **cargv
);
24 int csa_doactivateuser(void *source
, int cargc
, char **cargv
);
25 int csa_doaddchan(void *source
, int argc
, char **argv
);
26 int csa_doremoteauth(void *source
, int argc
, char **argv
);
28 static int decrypt_password(unsigned char *secret
, int keybits
, char *buf
, int bufsize
, char *encrypted
);
29 static int hex_to_int(char *input
, unsigned char *buf
, int buflen
);
31 static unsigned char createaccountsecret
[KEY_BITS
/ 8];
32 static int createaccountsecret_ok
= 0;
34 static 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
63 static void relayfinishinit(int, void *);
65 void relayfinishinit(int hooknum
, void *arg
) {
68 deregisterhook(HOOK_CHANSERV_DBLOADED
, relayfinishinit
);
70 registercontrolhelpcmd("checkhashpass", NO_RELAY
, 3, csa_docheckhashpass
, "Usage: checkhashpass <username> <digest> ?junk?");
71 registercontrolhelpcmd("settempemail", NO_RELAY
, 2, csa_dosettempemail
, "Usage: settempemail <userid> <email address>");
72 registercontrolhelpcmd("setemail", NO_RELAY
, 3, csa_dosetemail
, "Usage: setmail <userid> <timestamp> <email address>");
73 registercontrolhelpcmd("resendemail", NO_RELAY
, 1, csa_doresendemail
, "Usage: resendemail <userid>");
74 registercontrolhelpcmd("activateuser", NO_RELAY
, 1, csa_doactivateuser
, "Usage: activateuser <userid>");
75 registercontrolhelpcmd("addchan", NO_RELAY
, 3, csa_doaddchan
, "Usage: addchan <channel> <userid> <channel type>");
76 registercontrolhelpcmd("remoteauth", NO_RELAY
, 6, csa_doremoteauth
, "Usage: remoteauth <username> <digest> <junk> <nick> <ident> <host>");
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);
84 registercontrolhelpcmd("createaccount", NO_RELAY
, 5, csa_docreateaccount
, "Usage: createaccount <execute> <username> <email address> <encrypted password> <activate user>");
85 createaccountsecret_ok
= 1;
92 registerhook(HOOK_CHANSERV_DBLOADED
, relayfinishinit
);
95 relayfinishinit(HOOK_CHANSERV_DBLOADED
, NULL
);
99 deregistercontrolcmd("checkhashpass", csa_docheckhashpass
);
100 deregistercontrolcmd("settempemail", csa_dosettempemail
);
101 deregistercontrolcmd("setemail", csa_dosetemail
);
102 deregistercontrolcmd("resendemail", csa_doresendemail
);
103 deregistercontrolcmd("activateuser", csa_doactivateuser
);
104 deregistercontrolcmd("addchan", csa_doaddchan
);
106 if(createaccountsecret_ok
)
107 deregistercontrolcmd("createaccount", csa_docreateaccount
);
109 deregisterhook(HOOK_CHANSERV_DBLOADED
, relayfinishinit
);
112 int csa_docheckhashpass(void *source
, int cargc
, char **cargv
) {
113 nick
*sender
=(nick
*)source
;
118 controlreply(sender
, "CHECKHASHPASS FAIL args");
122 if (!(rup
=findreguserbynick(cargv
[0]))) {
123 controlreply(sender
, "CHECKHASHPASS FAIL user");
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
);
130 } else if(UIsInactive(rup
)) {
131 controlreply(sender
, "CHECKHASHPASS FAIL inactive %s %s %u", rup
->username
, flags
, rup
->ID
);
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
);
135 controlreply(sender
, "CHECKHASHPASS OK %s %s %u %s", rup
->username
, flags
, rup
->ID
, rup
->email
?rup
->email
->content
:"-");
141 static void controlremotereply(nick
*target
, char *message
) {
142 controlreply(target
, "REMOTEAUTH FAILTEXT %s", message
);
145 static void remote_reply(nick
*sender
, int message_id
, ...) {
147 va_start(va
, message_id
);
148 chanservstdvmessage(sender
, NULL
, message_id
, -1 * (int)(strlen("REMOTEAUTH FAILTEXT ")), controlremotereply
, va
);
152 int csa_doremoteauth(void *source
, int cargc
, char **cargv
) {
153 nick
*sender
=(nick
*)source
;
157 controlreply(sender
, "REMOTEAUTH FAILREASON args");
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];
168 if (!(rup
=findreguserbynick(account
))) {
169 controlreply(sender
, "REMOTEAUTH FAILREASON user");
173 if(!checkhashpass(rup
, junk
, digest
)) {
174 controlreply(sender
, "REMOTEAUTH FAILREASON digest");
178 if (!csa_completeauth2(rup
, nick
, ident
, hostname
, "REMOTEAUTH", remote_reply
, sender
)) {
179 controlreply(sender
, "REMOTEAUTH END");
183 /* username:ts:authid */
184 controlreply(sender
, "REMOTEAUTH OK %s %ld %ld", rup
->username
, rup
->lastauth
? rup
->lastauth
: getnettime(), rup
->ID
);
186 /* note: NO HOOK_CHANSERV_AUTH */
191 static char *email_to_error(char *email
) {
192 maildomain
*mdp
, *smdp
;
199 switch(csa_checkeboy_r(email
)) {
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";
210 /* maildomain BS... c&p from hello.c */
211 for(mlp
=maillocks
;mlp
;mlp
=mlp
->next
) {
212 if(!match(mlp
->pattern
->content
, email
)) {
213 return "emaillocked";
217 dupemail
= strdup(email
);
218 local
=strchr(dupemail
, '@');
221 return "emailunknown";
225 mdp
=findnearestmaildomain(local
);
227 for(smdp
=mdp
; smdp
; smdp
=smdp
->parent
) {
228 if(MDIsBanned(smdp
)) {
230 return "emaillocked";
232 if((smdp
->count
>= smdp
->limit
) && (smdp
->limit
> 0)) {
234 return "emaildomainlimit";
239 mdp
=findmaildomainbydomain(local
);
241 for (ruh
=mdp
->users
; ruh
; ruh
=ruh
->nextbydomain
) {
243 if (!strcasecmp(dupemail
, ruh
->localpart
->content
)) {
248 if((found
>= mdp
->actlimit
) && (mdp
->actlimit
> 0)) {
250 return "emailaddresslimit";
259 static void sendemail(reguser
*rup
) {
260 csdb_createmail(rup
, QMAIL_ACTIVATEEMAIL
);
263 int csa_docreateaccount(void *source
, int cargc
, char **cargv
) {
264 nick
*sender
=(nick
*)source
;
266 char *error_username
= NULL
, *error_password
= NULL
, *error_email
= NULL
;
267 char *username
= NULL
, *password
= NULL
, *email
= NULL
;
268 char account_info
[512];
274 controlreply(sender
, "CREATEACCOUNT FALSE args");
278 execute
= cargv
[0][0] == '1';
279 if(strcmp(cargv
[1], "0"))
281 if(strcmp(cargv
[2], "0"))
283 if(strcmp(cargv
[3], "0")) {
284 int errorcode
= decrypt_password(createaccountsecret
, KEY_BITS
, passbuf
, sizeof(passbuf
), cargv
[3]);
286 Error("chanserv_relay",ERR_WARNING
,"createaccount unable to decrypt password, error code: %d", errorcode
);
287 controlreply(sender
, "CREATEACCOUNT FALSE args");
292 activate
= cargv
[4][0] == '1';
295 if (findreguserbynick(username
)) {
296 error_username
= "usernameinuse";
297 } else if(csa_checkaccountname_r(username
)) {
298 error_username
= "usernameinvalid";
303 error_email
= email_to_error(email
);
306 int r
= csa_checkpasswordquality(password
);
307 if(r
== QM_PWTOSHORT
) {
308 error_password
= "passwordshort";
309 } else if(r
== QM_PWTOLONG
) {
310 error_password
= "passwordlong";
311 } else if(r
== QM_PWTOWEAK
) {
312 error_password
= "passwordweak";
313 } else if(r
== QM_PWINVALID
) {
314 error_password
= "passwordinvalid";
316 error_password
= "passwordunknown";
320 if(execute
&& email
&& password
&& username
&& !error_email
&& !error_password
&& !error_username
) {
324 rup
= csa_createaccount(username
, password
, email
);
329 cs_log(sender
,"CREATEACCOUNT created auth %s (%s) %s",rup
->username
,rup
->email
->content
,activate
?"(active)": "(inactive)");
330 csdb_createuser(rup
);
331 snprintf(account_info
, sizeof(account_info
), " %u %lu", rup
->ID
, (unsigned long)rup
->lastpasschange
);
336 account_info
[0] = '\0';
340 controlreply(sender
, "CREATEACCOUNT %s%s%s%s%s%s%s%s",
341 do_create
? "TRUE" : "FALSE",
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
: ""
351 int csa_dosettempemail(void *source
, int cargc
, char **cargv
) {
355 nick
*sender
=(nick
*)source
;
358 controlreply(sender
, "SETTEMPEMAIL FALSE args");
362 rup
= findreguserbyID(atoi(cargv
[0]));
364 controlreply(sender
, "SETTEMPEMAIL FALSE useridnotexist");
368 if(!UIsInactive(rup
)) {
369 controlreply(sender
, "SETTEMPEMAIL FALSE accountactive");
374 error
= email_to_error(email
);
376 controlreply(sender
, "SETTEMPEMAIL FALSE %s", error
);
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
);
384 csdb_updateuser(rup
);
387 controlreply(sender
, "SETTEMPEMAIL TRUE");
392 int csa_dosetemail(void *source
, int cargc
, char **cargv
) {
396 nick
*sender
=(nick
*)source
;
399 controlreply(sender
, "SETEMAIL FALSE args");
403 rup
= findreguserbyID(atoi(cargv
[0]));
405 controlreply(sender
, "SETEMAIL FALSE useridnotexist");
409 if(UHasStaffPriv(rup
)) {
410 controlreply(sender
, "SETEMAIL FALSE privuser");
414 if(UHasSuspension(rup
)) {
415 controlreply(sender
, "SETEMAIL FALSE suspended");
419 if(rup
->lastpasschange
> atoi(cargv
[1])) {
420 controlreply(sender
, "SETEMAIL FALSE passwordchanged");
426 if(!strcmp(email
, rup
->email
->content
)) {
427 /* setting to the same thing? fine! */
428 controlreply(sender
, "SETEMAIL TRUE");
432 error
= email_to_error(email
);
434 controlreply(sender
, "SETEMAIL FALSE %s", error
);
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
);
442 csdb_updateuser(rup
);
444 controlreply(sender
, "SETEMAIL TRUE");
449 int csa_doresendemail(void *source
, int cargc
, char **cargv
) {
451 nick
*sender
=(nick
*)source
;
454 controlreply(sender
, "RESENDEMAIL FALSE args");
458 rup
= findreguserbyID(atoi(cargv
[0]));
460 controlreply(sender
, "RESENDEMAIL FALSE useridnotexist");
464 if(!UIsInactive(rup
)) {
465 controlreply(sender
, "RESENDEMAIL FALSE accountactive");
470 controlreply(sender
, "RESENDEMAIL TRUE");
471 cs_log(sender
,"RESENDEMAIL OK username %s",rup
->username
);
476 int csa_doactivateuser(void *source
, int cargc
, char **cargv
) {
478 nick
*sender
=(nick
*)source
;
481 controlreply(sender
, "ACTIVATEUSER FALSE args");
485 rup
= findreguserbyID(atoi(cargv
[0]));
487 controlreply(sender
, "ACTIVATEUSER FALSE useridnotexist");
491 if(!UIsInactive(rup
)) {
492 controlreply(sender
, "ACTIVATEUSER FALSE accountactive");
497 csdb_updateuser(rup
);
499 cs_log(sender
,"ACTIVATEUSER OK username %s",rup
->username
);
500 controlreply(sender
, "ACTIVATEUSER TRUE");
505 int csa_doaddchan(void *source
, int cargc
, char **cargv
) {
506 nick
*sender
=(nick
*)source
;
507 reguser
*rup
= getreguserfromnick(sender
), *founder
;
513 controlreply(sender
, "ADDCHAN FALSE args");
517 if (*cargv
[0] != '#' || strlen(cargv
[0]) > CHANNELLEN
) {
518 controlreply(sender
, "ADDCHAN FALSE invalidchannel");
522 if (!(cip
=findorcreatechanindex(cargv
[0]))) {
523 controlreply(sender
, "ADDCHAN FALSE invalidchannel");
527 founder
= findreguserbyID(atoi(cargv
[1]));
528 if(founder
== NULL
) {
529 controlreply(sender
, "ADDCHAN FALSE useridnotexist");
533 if(UIsInactive(founder
)) {
534 controlreply(sender
, "ADDCHAN FALSE accountinactive");
538 for(type
=CHANTYPES
-1;type
;type
--)
539 if(!ircd_strcmp(chantypes
[type
]->content
, cargv
[2]))
543 controlreply(sender
, "ADDCHAN FALSE invalidchantype");
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
);
549 controlreply(sender
, "ADDCHAN FALSE alreadyregistered");
553 cs_log(sender
, "ADDCHAN %s #%s %s %s", cip
->name
->content
, founder
->username
, printflags(rcp
->flags
, rcflags
), chantypes
[type
]->content
);
554 controlreply(sender
, "ADDCHAN TRUE %u", rcp
->ID
);
558 static int hex_to_int(char *input
, unsigned char *buf
, int buflen
) {
560 for(i
=0;i
<buflen
;i
++) {
561 if((0xff == hexlookup
[(int)input
[i
* 2]]) || (0xff == hexlookup
[(int)input
[i
* 2 + 1]])) {
564 buf
[i
] = (hexlookup
[(int)input
[i
* 2]] << 4) | hexlookup
[(int)input
[i
* 2 + 1]];
570 static 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
];
576 datalen
= strlen(encrypted
);
579 if(datalen
< BLOCK_SIZE
* 2 * 2)
582 if(!hex_to_int(encrypted
, iv
, BLOCK_SIZE
))
585 ciphertextlen
= (datalen
- (BLOCK_SIZE
* 2)) / 2;
586 if(ciphertextlen
> bufsize
|| ciphertextlen
% BLOCK_SIZE
!= 0)
589 if(!hex_to_int(encrypted
+ BLOCK_SIZE
* 2, (unsigned char *)buf
, ciphertextlen
))
592 c
= rijndaelcbc_init(secret
, keybits
, iv
, 1);
594 for(i
=0;i
<ciphertextlen
;i
+=BLOCK_SIZE
) {
596 unsigned char *r
= rijndaelcbc_decrypt(c
, (unsigned char *)p
);
597 memcpy(p
, r
, BLOCK_SIZE
);
599 for(j
=0;j
<BLOCK_SIZE
;j
++) {
600 if(*(p
+ j
) == '\0') {