]> jfr.im git - irc/quakenet/newserv.git/commitdiff
the maildomain implementation has been fixed.
authorChris Porter <redacted>
Sun, 9 Mar 2008 04:33:30 +0000 (04:33 +0000)
committerChris Porter <redacted>
Sun, 9 Mar 2008 04:33:30 +0000 (04:33 +0000)
stuff that was wrong that I can rememeber:
- it created a table that had one number of fields, select code expected another number, insert code expected another different number, and update code didn't update most of the fields, but did escape them (though it never used the value).
- lots of uninitalised variables, e.g. flags and account limits
- in the function that built up a tree of domains, the author didn't realise how recursion works, how it should work:
  address: blah@kings.cam.ac.uk, kings.cam.ac.uk, cam.ac.uk, ac.uk, uk, ending up with kings.cam.ac.uk->cam.ac.uk->ac.uk->uk
  how it was working:
  address: blah@kings.cam.ac.uk, kings.cam.ac.uk, cam.ac.uk, ac.uk, uk
  now when unwinding the stack, it keeps looking for dots, despite the fact we've recursed already and have the tree!
  now it continues in cam.ac.uk looking for dots, so that ends up looking like cam.ac.uk->uk, and the full domain tree ends up as kings.cam.ac.uk->uk
  W T F
- didn't check for banned addresses but had the flag defined
- didn't show banned flag in spewdomain code
- all 5 pieces of code that attempted to extract the local part of email address using the wrong half (i.e. the domain)
- hello attempted to check for too many accounts on one email address but got the code wrong, however email didn't check at all
- was using match to compare the local part of email addresses
- was using ircd_strcmp to compare domains
- in hello a user could use up an unlimited amount of memory by passing in new domain for each user, if HELLO failed a maildomain wasn't deallocated.

how did this get committed?
I need to look over this stuff again.

chanserv/authcmds/email.c
chanserv/authcmds/hello.c
chanserv/authcmds/setemail.c
chanserv/chanserv.h
chanserv/chanservdb_updates.c
chanserv/database/chanservdb.c
chanserv/database/chanservdb_hash.c
chanserv/database/chanservdb_messages.c
chanserv/usercmds/spewdomain.c

index 8eb3e311adda1f44388df9114e862b922e97d048..17656944266573de691d456bf7cb47ed661863f2 100644 (file)
 #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");
@@ -52,14 +53,46 @@ int csa_doemail(void *source, int cargc, char **cargv) {
   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);
@@ -68,10 +101,9 @@ int csa_doemail(void *source, int cargc, char **cargv) {
   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;
   }
index 40f5d16a74230bb586b852dbb2792bc7e7c39dc9..ea8054c26257c7fae55927977dc2c5d57d4246c7 100644 (file)
@@ -65,32 +65,48 @@ int csa_dohello(void *source, int cargc, char **cargv) {
   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;
@@ -104,7 +120,10 @@ int csa_dohello(void *source, int cargc, char **cargv) {
   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;
index eb4e125082db06cebab3d4cdcce1ad0731a17395..8dbf0d4544eba75b33e25978b4e2ef1dba64af6b 100644 (file)
@@ -42,7 +42,7 @@ int csa_dosetmail(void *source, int cargc, char **cargv) {
   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;
   }
index f16031a7bb615786593a267b599e55e26c41012f..fa19c7bd9570772295d83f891e2bc2bf10d1053f 100644 (file)
@@ -53,6 +53,9 @@
 /* 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 */
 
@@ -548,6 +553,8 @@ typedef struct maildomain {
 #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)
@@ -823,6 +830,7 @@ maildomain *findmaildomainbyID(unsigned int ID);
 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);
index a9ee240a4d611d58dafb01a87c61dbabf3e44ae9..3318e2b375b2f3cf1f3f269978776204ee94c25c 100644 (file)
@@ -359,14 +359,14 @@ void csdb_createmaildomain(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) {
index c9c5d11125b2a3de8c318c1ff67a29d52ba5e6af..6d897bf1ce70ab8d0e6d42a1b0eb41fc0c2aeef6 100644 (file)
@@ -377,7 +377,7 @@ void loadsomeusers(PGconn *dbconn, void *arg) {
       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;
       }
@@ -827,7 +827,7 @@ void loadsomemaildomains(PGconn *dbconn,void *arg) {
     return;
  }
 
-  if (PQnfields(pgres)!=4) {
+  if (PQnfields(pgres)!=5) {
     Error("chanserv",ERR_ERROR,"Mail Domain DB format error");
     return;
   }
index 99d332a6667d59937cefce0157f2a0425098842d..bbae18a6fcc0dc235abc90ebc2ab77378275ba88 100644 (file)
@@ -72,7 +72,7 @@ reguser *findreguserbyemail(const char *email) {
 
   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;
       }
     }
@@ -201,12 +201,20 @@ maildomain *findmaildomainbydomain(char *domain) {
 
   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;
 
@@ -222,7 +230,6 @@ maildomain *findorcreatemaildomain(char *email) {
   unsigned int hash;
   char *domain,*pdomain;
   maildomain *mdp, *pmdp;
-  char parent=0;
 
   if (!(domain=strchr(email, '@')))
     domain=email;
@@ -234,7 +241,7 @@ maildomain *findorcreatemaildomain(char *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();
@@ -242,19 +249,20 @@ maildomain *findorcreatemaildomain(char *email) {
   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;
 }
 
index 7e37b8fd2d57e144c33acaba6eb1267de36e13d0..a30e3081da1aefbee26901dd3d5a392b9d792d5a 100644 (file)
@@ -143,7 +143,7 @@ char *defaultmessages[MAXMESSAGES] = {
   /* 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.",
@@ -166,6 +166,8 @@ char *defaultmessages[MAXMESSAGES] = {
   /* 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() {
index 48d2be50f3d54b789b73b49c68abd0753fee0d86..d2c3567d949a27c3b75f55f3061f75b4167db6f6 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "../chanserv.h"
 #include "../../lib/irc_string.h"
+#include "../../lib/strlfunc.h"
 #include <stdio.h>
 #include <string.h>
 
@@ -21,6 +22,7 @@ int csu_dospewdomain(void *source, int cargc, char **cargv) {
   unsigned int count=0;
   maildomain *smdp;
   int limit=0, actlimit=0;
+  char flagbuf[100], smallbuf[20];
 
   if (!rup)
     return CMD_ERROR;
@@ -49,8 +51,20 @@ int csu_dospewdomain(void *source, int cargc, char **cargv) {
             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");