Back to index

courier  0.68.2
bofh.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2001-2002 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #include      "bofh.h"
00007 #include      "courier.h"
00008 #include      <stdio.h>
00009 #include      <string.h>
00010 #include      <unistd.h>
00011 #include      <stdlib.h>
00012 #include      <ctype.h>
00013 
00014 unsigned max_bofh=100;
00015 int max_bofh_ishard=0;
00016 
00017 
00018 static struct bofh_list *bofh_freemail, *bofh_spamtrap, *bofh_badmx,
00019        *bofh_badfrom;
00020 static struct bofh_list **freemailp, **spamtrapp, **badmxp, **badfromp;
00021 
00022 static void addbofh(struct bofh_list ***, void (*)(char *), int);
00023 
00024 static void strlower(char *p)
00025 {
00026        while (*p)
00027        {
00028               *p=tolower( (int)(unsigned char)*p );
00029               ++p;
00030        }
00031 }
00032 
00033 static void address_lower(char *p)
00034 {
00035        domainlower(p);
00036        locallower(p);
00037 }
00038 
00039 static void bofh_free(struct bofh_list *p)
00040 {
00041        struct bofh_list *q;
00042 
00043        while ((q=p->aliases) != NULL)
00044        {
00045               p->aliases=q->next;
00046               free(q->name);
00047               free(q);
00048        }
00049 
00050        free(p->name);
00051        free(p);
00052 }
00053 
00054 void bofh_init()
00055 {
00056        struct bofh_list *p;
00057        char buf[BUFSIZ];
00058 
00059        char *f=config_localfilename("bofh");
00060        FILE    *fp=fopen(f, "r");
00061 
00062        free(f);
00063 
00064        /* Just in case */
00065        while ((p=bofh_freemail) != 0)
00066        {
00067               bofh_freemail=p->next;
00068               bofh_free(p);
00069        }
00070        freemailp= &bofh_freemail;
00071 
00072        while ((p=bofh_spamtrap) != 0)
00073        {
00074               bofh_spamtrap=p->next;
00075               bofh_free(p);
00076        }
00077        spamtrapp= &bofh_spamtrap;
00078  
00079        while ((p=bofh_badmx) != 0)
00080        {
00081               bofh_badmx=p->next;
00082               bofh_free(p);
00083        }
00084        badmxp= &bofh_badmx;
00085 
00086        while ((p=bofh_badfrom) != 0)
00087        {
00088               bofh_badfrom=p->next;
00089               bofh_free(p);
00090        }
00091        badfromp= &bofh_badfrom;
00092 
00093        if (!fp)
00094               return;
00095 
00096        while (fgets(buf, sizeof(buf), fp))
00097        {
00098               char *p=strchr(buf, '\n');
00099 
00100               if (p) *p=0;
00101 
00102               p=strchr(buf, '#');
00103               if (p) *p=0;
00104 
00105               p=strtok(buf, " \t\r");
00106 
00107               if (!p)
00108                      continue;
00109 
00110               if (strcasecmp(p, "freemail") == 0)
00111               {
00112                      addbofh(&freemailp, &strlower, 1);
00113               }
00114               else if (strcasecmp(p, "spamtrap") == 0)
00115               {
00116                      addbofh(&spamtrapp, &address_lower, 0);
00117               }
00118               else if (strcasecmp(p, "badmx") == 0)
00119               {
00120                      addbofh(&badmxp, NULL, 0);
00121               }
00122               else if (strcasecmp(p, "badfrom") == 0)
00123               {
00124                      addbofh(&badfromp, &address_lower, 0);
00125               }
00126               else if (strcasecmp(p, "maxrcpts") == 0)
00127               {
00128                      char *q=strtok(NULL, " \t\r");
00129                      
00130                      if (q)
00131                      {
00132                             unsigned n=atoi(q);
00133 
00134                             if (n <= 0)
00135                                    n=max_bofh;
00136 
00137                             max_bofh=n;
00138                             q=strtok(NULL, " \t\r");
00139                      }
00140 
00141                      if (q)
00142                             max_bofh_ishard=strcasecmp(q, "hard") == 0;
00143               }
00144               else if (strcasecmp(p, "opt") == 0)
00145               {
00146                      char *env=strtok(NULL, " \t\r");
00147                      char *var;
00148 
00149                      if (!env)
00150                             continue;
00151 
00152                      var=courier_malloc(strlen(env)+1);
00153                      strcpy(var, env);
00154 
00155                      env=strchr(var, '=');
00156                      if (!env)
00157                      {
00158                             free(var);
00159                             continue;
00160                      }
00161 
00162                      *env=0;
00163 
00164                      if (getenv(var))     /* Variable already set */
00165                      {
00166                             free(var);
00167                             continue;
00168                      }
00169                      *env='=';
00170                      putenv(var);
00171               }
00172        }
00173        fclose(fp);
00174 }
00175 
00176 static void addbofh(struct bofh_list ***p, void (*func)(char *), int moreflag)
00177 {
00178        char *q=strtok(NULL, " \t\r");
00179        struct bofh_list *b;
00180 
00181        if (!q)
00182               return;
00183 
00184        b=(struct bofh_list *)courier_malloc(sizeof(struct bofh_list));
00185        b->name=courier_malloc(strlen(q)+1);
00186        strcpy(b->name, q);
00187        if (func)
00188               (*func)(b->name);
00189        b->next=NULL;
00190        b->aliases=NULL;
00191        **p=b;
00192        *p= &b->next;
00193 
00194        if (moreflag)
00195               while ((q=strtok(NULL, " \t\r")) != NULL)
00196               {
00197                      struct bofh_list *bb=(struct bofh_list *)
00198                             courier_malloc(sizeof(struct bofh_list));
00199 
00200                      bb->name=courier_malloc(strlen(q)+1);
00201                      strcpy(bb->name, q);
00202                      if (func)
00203                             (*func)(bb->name);
00204 
00205                      bb->next=b->aliases;
00206                      b->aliases=bb;
00207               }
00208 }
00209 
00210 static int chkbadlist(const char *, struct bofh_list *);
00211 
00212 int bofh_chkbadfrom(const char *pp)
00213 {
00214        return (chkbadlist(pp, bofh_badfrom));
00215 }
00216 
00217 int bofh_chkspamtrap(const char *pp)
00218 {
00219        return (chkbadlist(pp, bofh_spamtrap));
00220 }
00221 
00222 static int chkusersubdom(const char *p, const char *d, const char *name)
00223 {
00224        const char *dn, *dn1, *d1;
00225        int lp, ln, ldp, ldn;
00226        if (p == NULL || d == NULL || d <= p || d[1] != '.'
00227            || name == NULL || (dn = strrchr(name, '@')) == NULL)
00228        {
00229               return (0);
00230        }
00231        
00232        lp = d - p;
00233        ln = dn - name;
00234        if (lp != ln || strncmp(p, name, ln) != 0)
00235        {
00236               return (0);
00237        }
00238 
00239        return ((ldn = strlen(dn1 = dn + 1)) > 0
00240               && (ldp = strlen(d1 = d + 1)) <= ldn
00241               && strcmp(dn1 + (ldn - ldp), d1) == 0);
00242 }
00243 
00244 static int chkbadlist(const char *pp, struct bofh_list *b)
00245 {
00246        char *p=courier_malloc(strlen(pp)+1);
00247        const char *d;
00248        int l, ll;
00249 
00250        strcpy(p, pp);
00251        address_lower(p);
00252 
00253        d=strrchr(p, '@');
00254        l=d ? strlen(d):0;
00255 
00256        for (; b; b=b->next)
00257        {
00258               if ((d && strcmp(d, b->name) == 0)
00259                   || /* Entire domain with user ID */
00260                   chkusersubdom(p, d, b->name)
00261                   || /* Entire domain without user ID */
00262                   strcmp(p, b->name) == 0
00263                   || (d && strncmp(b->name, "@.", 2) == 0
00264                      && (ll=strlen(b->name+1)) < l
00265                      && strcmp(d+l - ll, b->name+1) == 0))
00266               {
00267                      free(p);
00268                      return (1);   /* Entire domain matches */
00269               }
00270        }
00271        free(p);
00272        return (0);
00273 }
00274 
00275 struct bofh_list *bofh_chkfreemail(const char *pp)
00276 {
00277        char *p;
00278        struct bofh_list *b;
00279 
00280        pp=strrchr(pp, '@');
00281        if (!pp)
00282               return (NULL);
00283        p=courier_malloc(strlen(pp));
00284        ++pp;
00285        strcpy(p, pp);
00286        address_lower(p);
00287 
00288        for (b=bofh_freemail; b; b=b->next)
00289        {
00290               if (strcmp(b->name, p) == 0)
00291               {
00292                      free(p);
00293                      return (b);
00294               }
00295        }
00296        free(p);
00297        return (NULL);
00298 }
00299 
00300 int bofh_chkbadmx(const char *p)
00301 {
00302        struct bofh_list *b;
00303 
00304        if (strncasecmp(p, "::ffff:", 7) == 0)
00305               p += 7;
00306 
00307        for (b=bofh_badmx; b; b=b->next)
00308        {
00309               if (strcmp(b->name, p) == 0)
00310                      return (1);
00311        }
00312        return (0);
00313 }
00314 
00315 /*
00316 ** Check if an SPF BOFH setting contains the keyword.
00317 */
00318 
00319 int bofh_checkspf(const char *envvarname,
00320                 const char *defaultValue, const char *keyword)
00321 {
00322        char buf[256];
00323        const char *p=getenv(envvarname);
00324        char *s;
00325 
00326        if (!p || !*p) p=defaultValue;
00327 
00328        buf[0]=0;
00329        strncat(buf, p, sizeof(buf)-1);
00330 
00331        for (s=buf; (s=strtok(s, ",")) != NULL; s=NULL)
00332               if (strcmp(s, keyword) == 0)
00333                      return 1;
00334        return 0;
00335 }
00336 
00337 /*
00338 ** "all" means any status.
00339 */
00340 
00341 int bofh_checkspf_status(const char *envvarname,
00342                       const char *defaultValue, const char *keyword)
00343 {
00344        if (bofh_checkspf(envvarname, defaultValue, "all") ||
00345            bofh_checkspf(envvarname, defaultValue, keyword))
00346               return 1;
00347        return 0;
00348 }