]>
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_doresendemail(void *source
, int cargc
, char **cargv
);
23 int csa_doactivateuser(void *source
, int cargc
, char **cargv
);
24 static int decrypt_password(unsigned char *secret
, int keybits
, char *buf
, int bufsize
, char *encrypted
);
25 static int hex_to_int(char *input
, unsigned char *buf
, int buflen
);
27 static unsigned char createaccountsecret
[KEY_BITS
/ 8];
28 static int createaccountsecret_ok
= 0;
30 static unsigned char hexlookup
[256] = {
31 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
32 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
33 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
34 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
35 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01,
36 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xff, 0xff,
37 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
38 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
39 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
40 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x0b, 0x0c,
41 0x0d, 0x0e, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
42 0xff, 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, 0xff, 0xff, 0xff,
45 0xff, 0xff, 0xff, 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
62 registercontrolhelpcmd("checkhashpass", NO_RELAY
, 3, csa_docheckhashpass
, "Usage: checkhashpass <username> <digest> ?junk?");
63 registercontrolhelpcmd("settempemail", NO_RELAY
, 2, csa_dosettempemail
, "Usage: settempemail <userid> <email address>");
64 registercontrolhelpcmd("resendemail", NO_RELAY
, 1, csa_doresendemail
, "Usage: resendemail <userid>");
65 registercontrolhelpcmd("activateuser", NO_RELAY
, 1, csa_doactivateuser
, "Usage: activateuser <userid>");
67 s
=getcopyconfigitem("chanserv","createaccountsecret","",128);
68 if(!s
|| !s
->content
|| !s
->content
[0]) {
69 Error("chanserv_relay",ERR_WARNING
,"createaccountsecret not set, createaccount disabled.");
70 } else if(s
->length
!= KEY_BITS
/ 8 * 2 || !hex_to_int(s
->content
, createaccountsecret
, sizeof(createaccountsecret
))) {
71 Error("chanserv_relay",ERR_WARNING
,"createaccountsecret must be a %d character hex string.", KEY_BITS
/ 8 * 2);
73 registercontrolhelpcmd("createaccount", NO_RELAY
, 4, csa_docreateaccount
, "Usage: createaccount <execute> <username> <email address> <encrypted password>");
74 createaccountsecret_ok
= 1;
81 deregistercontrolcmd("checkhashpass", csa_docheckhashpass
);
82 deregistercontrolcmd("settempemail", csa_dosettempemail
);
83 deregistercontrolcmd("resendemail", csa_doresendemail
);
84 deregistercontrolcmd("activateuser", csa_doactivateuser
);
86 if(createaccountsecret_ok
)
87 deregistercontrolcmd("createaccount", csa_docreateaccount
);
90 int csa_docheckhashpass(void *source
, int cargc
, char **cargv
) {
91 nick
*sender
=(nick
*)source
;
96 controlreply(sender
, "CHECKHASHPASS FAIL args");
100 if (!(rup
=findreguserbynick(cargv
[0]))) {
101 controlreply(sender
, "CHECKHASHPASS FAIL user");
105 flags
= printflags(QUFLAG_ALL
& rup
->flags
, ruflags
);
106 if(UHasSuspension(rup
)) {
107 controlreply(sender
, "CHECKHASHPASS FAIL suspended %s %s %u", rup
->username
, flags
, rup
->ID
);
108 } else if(UIsInactive(rup
)) {
109 controlreply(sender
, "CHECKHASHPASS FAIL inactive %s %s %u", rup
->username
, flags
, rup
->ID
);
110 } else if(!checkhashpass(rup
, cargc
<3?NULL
:cargv
[2], cargv
[1])) {
111 controlreply(sender
, "CHECKHASHPASS FAIL digest %s %s %u", rup
->username
, flags
, rup
->ID
);
113 controlreply(sender
, "CHECKHASHPASS OK %s %s %u %s", rup
->username
, flags
, rup
->ID
, rup
->email
?rup
->email
->content
:"-");
119 static char *email_to_error(char *email
) {
120 maildomain
*mdp
, *smdp
;
127 switch(csa_checkeboy_r(email
)) {
129 case QM_EMAILTOOSHORT
: return "emailshort";
130 case QM_EMAILNOAT
: return "emailinvalid";
131 case QM_EMAILATEND
: return "emailinvalid";
132 case QM_EMAILINVCHR
: return "emailinvalid";
133 case QM_NOTYOUREMAIL
: return "emailnotyours";
134 case QM_INVALIDEMAIL
: return "emailinvalid";
135 default: return "emailunknown";
138 /* maildomain BS... c&p from hello.c */
139 for(mlp
=maillocks
;mlp
;mlp
=mlp
->next
) {
140 if(!match(mlp
->pattern
->content
, email
)) {
141 return "emaillocked";
145 dupemail
= strdup(email
);
146 local
=strchr(dupemail
, '@');
149 return "emailunknown";
153 mdp
=findnearestmaildomain(local
);
155 for(smdp
=mdp
; smdp
; smdp
=smdp
->parent
) {
156 if(MDIsBanned(smdp
)) {
158 return "emaillocked";
160 if((smdp
->count
>= smdp
->limit
) && (smdp
->limit
> 0)) {
162 return "emaildomainlimit";
167 mdp
=findmaildomainbydomain(local
);
169 for (ruh
=mdp
->users
; ruh
; ruh
=ruh
->nextbydomain
) {
171 if (!strcasecmp(dupemail
, ruh
->localpart
->content
)) {
176 if((found
>= mdp
->actlimit
) && (mdp
->actlimit
> 0)) {
178 return "emailaddresslimit";
187 static void sendemail(reguser
*rup
) {
188 csdb_createmail(rup
, QMAIL_ACTIVATEEMAIL
);
191 int csa_docreateaccount(void *source
, int cargc
, char **cargv
) {
192 nick
*sender
=(nick
*)source
;
194 char *error_username
= NULL
, *error_password
= NULL
, *error_email
= NULL
;
195 char *username
= NULL
, *password
= NULL
, *email
= NULL
;
196 char account_info
[512];
201 controlreply(sender
, "CREATEACCOUNT FALSE args");
205 execute
= cargv
[0][0] == '1';
206 if(strcmp(cargv
[1], "0"))
208 if(strcmp(cargv
[2], "0"))
210 if(strcmp(cargv
[3], "0")) {
211 int errorcode
= decrypt_password(createaccountsecret
, KEY_BITS
, passbuf
, sizeof(passbuf
), cargv
[3]);
213 Error("chanserv_relay",ERR_WARNING
,"createaccount unable to decrypt password, error code: %d", errorcode
);
214 controlreply(sender
, "CREATEACCOUNT FALSE args");
221 if (findreguserbynick(username
)) {
222 error_username
= "usernameinuse";
223 } else if(csa_checkaccountname_r(username
)) {
224 error_username
= "usernameinvalid";
229 error_email
= email_to_error(email
);
232 int r
= csa_checkpasswordquality(password
);
233 if(r
== QM_PWTOSHORT
) {
234 error_password
= "passwordshort";
235 } else if(r
== QM_PWTOLONG
) {
236 error_password
= "passwordlong";
237 } else if(r
== QM_PWTOWEAK
) {
238 error_password
= "passwordweak";
240 error_password
= "passwordunknown";
244 if(execute
&& email
&& password
&& username
&& !error_email
&& !error_password
&& !error_username
) {
248 rup
= csa_createaccount(username
, password
, email
);
251 cs_log(sender
,"CREATEACCOUNT created auth %s (%s)",rup
->username
,rup
->email
->content
);
252 csdb_createuser(rup
);
253 snprintf(account_info
, sizeof(account_info
), " %u", rup
->ID
);
257 account_info
[0] = '\0';
261 controlreply(sender
, "CREATEACCOUNT %s%s%s%s%s%s%s%s",
262 do_create
? "TRUE" : "FALSE",
264 email
&& error_email
? " " : "", email
&& error_email
? error_email
: "",
265 password
&& error_password
? " " : "", password
&& error_password
? error_password
: "",
266 username
&& error_username
? " " : "", username
&& error_username
? error_username
: ""
272 int csa_dosettempemail(void *source
, int cargc
, char **cargv
) {
276 nick
*sender
=(nick
*)source
;
279 controlreply(sender
, "SETTEMPEMAIL FALSE args");
283 rup
= findreguserbyID(atoi(cargv
[0]));
285 controlreply(sender
, "SETTEMPEMAIL FALSE useridnotexist");
289 if(!UIsInactive(rup
)) {
290 controlreply(sender
, "SETTEMPEMAIL FALSE accountactive");
295 error
= email_to_error(email
);
297 controlreply(sender
, "SETTEMPEMAIL FALSE %s", error
);
301 freesstring(rup
->email
);
302 rup
->email
=getsstring(email
,EMAILLEN
);
303 cs_log(sender
,"SETTEMPEMAIL OK username %s email %s",rup
->username
, rup
->email
->content
);
305 csdb_updateuser(rup
);
308 controlreply(sender
, "SETTEMPEMAIL TRUE");
313 int csa_doresendemail(void *source
, int cargc
, char **cargv
) {
315 nick
*sender
=(nick
*)source
;
318 controlreply(sender
, "RESENDEMAIL FALSE args");
322 rup
= findreguserbyID(atoi(cargv
[0]));
324 controlreply(sender
, "RESENDEMAIL FALSE useridnotexist");
328 if(!UIsInactive(rup
)) {
329 controlreply(sender
, "RESENDEMAIL FALSE accountactive");
334 controlreply(sender
, "RESENDEMAIL TRUE");
335 cs_log(sender
,"RESENDEMAIL OK username %s",rup
->username
);
340 int csa_doactivateuser(void *source
, int cargc
, char **cargv
) {
342 nick
*sender
=(nick
*)source
;
345 controlreply(sender
, "ACTIVATEUSER FALSE args");
349 rup
= findreguserbyID(atoi(cargv
[0]));
351 controlreply(sender
, "ACTIVATEUSER FALSE useridnotexist");
355 if(!UIsInactive(rup
)) {
356 controlreply(sender
, "ACTIVATEUSER FALSE accountactive");
361 csdb_updateuser(rup
);
363 cs_log(sender
,"ACTIVATEUSER OK username %s",rup
->username
);
364 controlreply(sender
, "ACTIVATEUSER TRUE");
369 static int hex_to_int(char *input
, unsigned char *buf
, int buflen
) {
371 for(i
=0;i
<buflen
;i
++) {
372 if((0xff == hexlookup
[(int)input
[i
* 2]]) || (0xff == hexlookup
[(int)input
[i
* 2 + 1]])) {
375 buf
[i
] = (hexlookup
[(int)input
[i
* 2]] << 4) | hexlookup
[(int)input
[i
* 2 + 1]];
381 static int decrypt_password(unsigned char *secret
, int keybits
, char *buf
, int bufsize
, char *encrypted
) {
382 size_t ciphertextlen
, datalen
;
383 unsigned char iv
[BLOCK_SIZE
];
387 datalen
= strlen(encrypted
);
390 if(datalen
< BLOCK_SIZE
* 2 * 2)
393 if(!hex_to_int(encrypted
, iv
, BLOCK_SIZE
))
396 ciphertextlen
= (datalen
- (BLOCK_SIZE
* 2)) / 2;
397 if(ciphertextlen
> bufsize
|| ciphertextlen
% BLOCK_SIZE
!= 0)
400 if(!hex_to_int(encrypted
+ BLOCK_SIZE
* 2, (unsigned char *)buf
, ciphertextlen
))
403 c
= rijndaelcbc_init(secret
, keybits
, iv
, 1);
405 for(i
=0;i
<ciphertextlen
;i
+=BLOCK_SIZE
) {
407 unsigned char *r
= rijndaelcbc_decrypt(c
, (unsigned char *)p
);
408 memcpy(p
, r
, BLOCK_SIZE
);
410 for(j
=0;j
<BLOCK_SIZE
;j
++) {
411 if(*(p
+ j
) == '\0') {