#include <string.h>
int csa_doemail(void *source, int cargc, char **cargv) {
- reguser *rup;
+ reguser *rup, *ruh;
nick *sender=source;
maildomain *mdp, *smdp;
char *local;
char *dupemail;
+ int found = 0;
if (cargc<3) {
chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "email");
if (csa_checkeboy(sender, cargv[1]))
return CMD_ERROR;
- mdp=findorcreatemaildomain(cargv[1]);
- for(smdp=mdp; smdp; smdp=smdp->parent) {
- if((smdp->count >= smdp->limit) && (smdp->limit > 0)) {
- chanservstdmessage(sender, QM_DOMAINLIMIT);
+ dupemail = strdup(cargv[1]);
+ local=strchr(dupemail, '@');
+ if(!local)
+ return CMD_ERROR;
+ *(local++)='\0';
+
+ mdp=findnearestmaildomain(local);
+ if(mdp) {
+ for(smdp=mdp; smdp; smdp=smdp->parent) {
+ if(MDIsBanned(smdp)) {
+ free(dupemail);
+ chanservstdmessage(sender, QM_DOMAINBANNED);
+ return CMD_ERROR;
+ }
+ if((smdp->count >= smdp->limit) && (smdp->limit > 0)) {
+ free(dupemail);
+ chanservstdmessage(sender, QM_DOMAINLIMIT);
+ return CMD_ERROR;
+ }
+ }
+ }
+
+ mdp=findmaildomainbydomain(local);
+ if(mdp) {
+ for (ruh=mdp->users; ruh; ruh=ruh->nextbydomain) {
+ if (ruh->localpart)
+ if (!strcasecmp(dupemail, ruh->localpart->content)) {
+ found++;
+ }
+ }
+
+ if((found >= mdp->actlimit) && (mdp->actlimit > 0)) {
+ free(dupemail);
+ chanservstdmessage(sender, QM_ADDRESSLIMIT);
return CMD_ERROR;
}
}
+ mdp=findorcreatemaildomain(cargv[1]);
+
csdb_createmail(rup, QMAIL_NEWEMAIL);
csdb_accounthistory_insert(sender, NULL, NULL, rup->email, getsstring(cargv[1], EMAILLEN));
delreguserfrommaildomain(rup,rup->domain);
rup->lastemailchange=time(NULL);
rup->domain=findorcreatemaildomain(rup->email->content);
addregusertomaildomain(rup, rup->domain);
- dupemail = strdup(rup->email->content);
- if((local=strchr(dupemail, '@'))) {
- *(local++)='\0';
- rup->localpart=getsstring(local,EMAILLEN);
+
+ if(local) {
+ rup->localpart=getsstring(dupemail,EMAILLEN);
} else {
rup->localpart=NULL;
}
if (csa_checkaccountname(sender, sender->nick))
return CMD_ERROR;
- mdp=findorcreatemaildomain(cargv[0]);
- for(smdp=mdp; smdp; smdp=smdp->parent) {
- if((smdp->count >= smdp->limit) && (smdp->limit > 0)) {
- chanservstdmessage(sender, QM_DOMAINLIMIT);
- return CMD_ERROR;
- }
- }
-
- aup->helloattempts++;
-
dupemail = strdup(cargv[0]);
local=strchr(dupemail, '@');
+ if(!local)
+ return CMD_ERROR;
*(local++)='\0';
- for (ruh=mdp->users; ruh; ruh=ruh->nextbydomain) {
- if (ruh->localpart)
- if (!match(local, ruh->localpart->content)) {
- found++;
+
+ mdp=findnearestmaildomain(local);
+ if(mdp) {
+ for(smdp=mdp; smdp; smdp=smdp->parent) {
+ if(MDIsBanned(smdp)) {
+ free(dupemail);
+ chanservstdmessage(sender, QM_DOMAINBANNED);
+ return CMD_ERROR;
}
+ if((smdp->count >= smdp->limit) && (smdp->limit > 0)) {
+ free(dupemail);
+ chanservstdmessage(sender, QM_DOMAINLIMIT);
+ return CMD_ERROR;
+ }
+ }
}
- free(dupemail);
- if((found > mdp->actlimit) && (mdp->actlimit > 0)) {
- chanservstdmessage(sender, QM_DOMAINLIMIT);
- return CMD_ERROR;
+ mdp=findmaildomainbydomain(local);
+ if(mdp) {
+ for (ruh=mdp->users; ruh; ruh=ruh->nextbydomain) {
+ if (ruh->localpart)
+ if (!strcasecmp(dupemail, ruh->localpart->content)) {
+ found++;
+ }
+ }
+
+ if((found >= mdp->actlimit) && (mdp->actlimit > 0)) {
+ free(dupemail);
+ chanservstdmessage(sender, QM_ADDRESSLIMIT);
+ return CMD_ERROR;
+ }
}
+ mdp=findorcreatemaildomain(cargv[0]);
+
+ aup->helloattempts++;
+
rup=getreguser();
rup->status=0;
rup->ID=++lastuserID;
rup->suspendexp=0;
rup->password[0]='\0';
rup->email=getsstring(cargv[0],EMAILLEN);
- rup->localpart=getsstring(local,EMAILLEN);
+
+ rup->localpart=getsstring(dupemail,EMAILLEN);
+ free(dupemail);
+
rup->domain=mdp;
addregusertomaildomain(rup, rup->domain);
rup->info=NULL;
dupemail = strdup(rup->email->content);
if((local=strchr(dupemail, '@'))) {
*(local++)='\0';
- rup->localpart=getsstring(local,EMAILLEN);
+ rup->localpart=getsstring(dupemail,EMAILLEN);
} else {
rup->localpart=NULL;
}
/* Maximum number of times a user may actually be authed */
#define MAXAUTHCOUNT 2
+/* Maximum number of accounts that may share an email address */
+#define MD_DEFAULTACTLIMIT 2
+
/* Sizes of the main hashes */
#define REGUSERHASHSIZE 60000
#define MAILDOMAINHASHSIZE 60000
#define QM_TOOMANYBANS 155
#define QM_WARNNOTREMOVEDPERMBAN 156
#define QM_MAXHELLOLIMIT 157
+#define QM_ADDRESSLIMIT 158
+#define QM_DOMAINBANNED 159
/* List of privileged operations */
#define MDFLAG_ACTLIMIT 0x0004 /* +u */
#define MDFLAG_ALL 0x0007
+#define MDFLAG_DEFAULT MDFLAG_ACTLIMIT
+
#define MDHasLimit(x) ((x)->flags & MDFLAG_LIMIT)
#define MDSetLimit(x) ((x)->flags |= MDFLAG_LIMIT)
#define MDClearLimit(x) ((x)->flags &= ~MDFLAG_LIMIT)
maildomain *findmaildomainbydomain(char *domain);
maildomain *findmaildomainbyemail(char *email);
maildomain *findorcreatemaildomain(char *email);
+maildomain *findnearestmaildomain(char *domain);
void removemaildomainfromhash(maildomain *mdp);
void addregusertomaildomain(reguser *rup, maildomain *mdp);
void delreguserfrommaildomain(reguser *rup, maildomain *mdp);
char escdomain[210];
PQescapeString(escdomain, mdp->name->content, mdp->name->length);
- pqquery("INSERT INTO maildomain (id, name, domainlimit) VALUES(%u, '%s', %u)", mdp->ID,escdomain,mdp->limit);
+ pqquery("INSERT INTO maildomain (id, name, domainlimit, actlimit, flags) VALUES(%u, '%s', %u, %u, %u)", mdp->ID,escdomain,mdp->limit,mdp->actlimit,mdp->flags);
}
void csdb_updatemaildomain(maildomain *mdp) {
char escdomain[210];
PQescapeString(escdomain, mdp->name->content, mdp->name->length);
- pqquery("UPDATE maildomain SET domainlimit=%u WHERE ID=%u", mdp->limit,mdp->ID);
+ pqquery("UPDATE maildomain SET domainlimit=%u, actlimit=%u, flags=%u, name='%s' WHERE ID=%u", mdp->limit,mdp->actlimit,mdp->flags,escdomain,mdp->ID);
}
void csdb_chanlevhistory_insert(regchan *rcp, nick *np, reguser *trup, flag_t oldflags, flag_t newflags) {
char *dupemail = strdup(rup->email->content);
if((local=strchr(dupemail, '@'))) {
*(local++)='\0';
- rup->localpart=getsstring(local,EMAILLEN);
+ rup->localpart=getsstring(dupemail,EMAILLEN);
} else {
rup->localpart=NULL;
}
return;
}
- if (PQnfields(pgres)!=4) {
+ if (PQnfields(pgres)!=5) {
Error("chanserv",ERR_ERROR,"Mail Domain DB format error");
return;
}
for (i=0;i<REGUSERHASHSIZE;i++) {
for (rup=regusernicktable[i];rup;rup=rup->nextbyname) {
- if (!ircd_strcmp(email,rup->email->content)) {
+ if (!strcasecmp(email,rup->email->content)) {
return rup;
}
}
hash=maildomainnamehash(domain);
for (mdp=maildomainnametable[hash]; mdp; mdp=mdp->nextbyname)
- if (!ircd_strcmp(mdp->name->content, domain))
+ if (!strcasecmp(mdp->name->content, domain))
return mdp;
return NULL;
}
+maildomain *findnearestmaildomain(char *domain) {
+ maildomain *m = findmaildomainbydomain(domain);
+ char *p;
+
+ if(!m && (p=strchr(domain, '.')))
+ return findnearestmaildomain(++p);
+}
+
maildomain *findmaildomainbyemail(char *email) {
char *domain;
unsigned int hash;
char *domain,*pdomain;
maildomain *mdp, *pmdp;
- char parent=0;
if (!(domain=strchr(email, '@')))
domain=email;
hash=maildomainnamehash(domain);
for (mdp=maildomainnametable[hash]; mdp; mdp=mdp->nextbyname)
- if (!ircd_strcmp(mdp->name->content, domain))
+ if (!strcasecmp(mdp->name->content, domain))
return mdp;
mdp=getmaildomain();
mdp->name=getsstring(domain, EMAILLEN);
mdp->count=0;
mdp->limit=0;
+ mdp->actlimit=MD_DEFAULTACTLIMIT;
+ mdp->flags=MDFLAG_DEFAULT;
mdp->users=NULL;
addmaildomaintohash(mdp);
- pdomain=domain;
- while((pdomain=strchr(pdomain, '.'))) {
- parent = 1;
+ pdomain=strchr(domain, '.');
+
+ if(pdomain) {
pdomain++;
- pmdp = findorcreatemaildomain(pdomain);
- mdp->parent = pmdp;
- }
- if(!parent) {
+ mdp->parent = findorcreatemaildomain(pdomain);
+ } else {
mdp->parent = NULL;
}
+
return mdp;
}
/* 132*/ "You have been granted ownership of %s.",
/* 133*/ "#: User: Authed: Disconnected: Reason:",
/* 134*/ "Current modes on %s: %s",
- /* 135*/ "Domain: Users: Limit:",
+ /* 135*/ "Domain: Users: Flags:",
/* 136*/ "Too many accounts exist from this email domain",
/* 137*/ "Password too weak - You need to avoid repeating characters, and have different character types (e.g. 1 number and 1 letter)",
/* 138*/ "User %s is not a master on %s - you must promote user to master status first.",
/* 155*/ "Channel has too many bans set, aborting.",
/* 156*/ "Warning: not removing registered ban %s from %s.",
/* 157*/ "Sorry, the registration service is unavailable to you at this time. Please try again later.", /* a deliberately vague message */
+ /* 158*/ "Too many accounts exist from this email address.",
+ /* 159*/ "That email address has been blocked.",
};
void initmessages() {
#include "../chanserv.h"
#include "../../lib/irc_string.h"
+#include "../../lib/strlfunc.h"
#include <stdio.h>
#include <string.h>
unsigned int count=0;
maildomain *smdp;
int limit=0, actlimit=0;
+ char flagbuf[100], smallbuf[20];
if (!rup)
return CMD_ERROR;
break;
}
}
+
+ snprintf(flagbuf, sizeof(flagbuf), "%s",printflags(mdp->flags, mdflags));
+ if(MDHasLimit(mdp)) {
+ snprintf(smallbuf, sizeof(smallbuf), " %d", limit);
+ strlcat(flagbuf, smallbuf, sizeof(flagbuf));
+ }
+
+ if(MDHasActLimit(mdp)) {
+ snprintf(smallbuf, sizeof(smallbuf), " %d", actlimit);
+ strlcat(flagbuf, smallbuf, sizeof(flagbuf));
+ }
+
/***@@@ bug here? i.e. we recurse up to find limit, then check MDHaslimit for current domain only?*/
- chanservsendmessage(sender, "%-19s %-7d %d%s %d%s", mdp->name->content, mdp->count, limit,MDHasLimit(mdp) ? "*":"", actlimit,MDHasActLimit(mdp) ? "*":"");
+ chanservsendmessage(sender, "%-19s %-7d %s", mdp->name->content, mdp->count, flagbuf);
count++;
if (count >= 2000) {
chanservstdmessage(sender, QM_TOOMANYRESULTS, 2000, "domains");