Back to index

courier  0.68.2
uucpstub.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2000 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #if    HAVE_CONFIG_H
00007 #include      "config.h"
00008 #endif
00009 #include      "courier.h"
00010 #include      "rw.h"
00011 #include      "dbobj.h"
00012 #include      "rfc822/rfc822.h"
00013 #include      "sysconfdir.h"
00014 
00015 #include      <string.h>
00016 #if    HAVE_UNISTD_H
00017 #include      <unistd.h>
00018 #endif
00019 
00020 static void rw_uucp(struct rw_info *, void (*)(struct rw_info *));
00021 static void rw_del_uucp(struct rw_info *, void (*)(struct rw_info *),
00022               void (*)(struct rw_info *, const struct rfc822token *,
00023                      const struct rfc822token *));
00024 
00025 static const char *uucpme();
00026 
00027 struct rw_list *uucp_rw_install(const struct rw_install_info *p)
00028 {
00029 static struct rw_list uucp_info={0, "module.uucp - " COURIER_COPYRIGHT,
00030                             rw_uucp, rw_del_uucp, 0};
00031 
00032        return (&uucp_info);
00033 }
00034 
00035 const char *uucp_rw_init()
00036 {
00037        return (0);
00038 }
00039 
00040 static struct dbobj uucpneighbors;
00041 static int uucpneighbors_isopen=0;
00042 
00043 static void uucpneighbors_init()
00044 {
00045        if (uucpneighbors_isopen)   return;
00046 
00047        dbobj_init(&uucpneighbors);
00048        uucpneighbors_isopen=1;
00049        if (dbobj_open(&uucpneighbors, SYSCONFDIR "/uucpneighbors.dat", "R"))
00050               uucpneighbors_isopen= -1;
00051 }
00052 
00053 static const char *uucpme()
00054 {
00055 static const char *buf=0;
00056 
00057        if (buf == 0)
00058        {
00059        char   *f=config_localfilename("uucpme");
00060 
00061               buf=config_read1l(f);
00062               free(f);
00063               if (buf == 0)
00064               {
00065               const char *p=config_me();
00066 
00067                      buf=strcpy(courier_malloc(strlen(p)+1), p);
00068                      if ((f=strchr(buf, '.')) != 0)     *f=0;
00069               }
00070        }
00071        return (buf);
00072 }
00073 
00074 static int uucprw= -1;
00075 
00076 static void prepend_me(struct rw_info *p, void (*func)(struct rw_info *));
00077 
00078 static void rw_uucp(struct rw_info *p, void (*func)(struct rw_info *))
00079 {
00080 struct rfc822token **q;
00081 
00082        /* Only rewrite headers if uucprewriteheaders is set */
00083 
00084        if ((p->mode & RW_HEADER) != 0)
00085        {
00086               if (uucprw < 0)
00087               {
00088               char   *f=config_localfilename("uucprewriteheaders");
00089 
00090                      uucprw= access(f, 0) == 0 ? 1:0;
00091                      free(f);
00092               }
00093 
00094               if (!uucprw)
00095               {
00096                      (*func)(p);
00097                      return;
00098               }
00099        }
00100 
00101        if ((p->mode & RW_OUTPUT) == 0)
00102        {
00103        struct rfc822token *r, *r2;
00104        char   *s;
00105 
00106               /* Convert UUCP address to Internet address */
00107 
00108               /* First, remove me!foo!bar */
00109 
00110               for (q= &p->ptr; *q; q= & (*q)->next )
00111                      if ((*q)->token == '!')     break;
00112               r= *q;
00113               *q=0;
00114 
00115               s=rfc822_gettok(p->ptr);
00116 
00117               if (!s)       clog_msg_errno();
00118               if (r && strcmp(s, uucpme()) == 0)
00119               {
00120                      p->ptr=r->next;
00121               }
00122               else   *q=r;
00123               free(s);
00124 
00125               /*
00126               ** If address already contains an @, assume it's already an
00127               ** Internet address.
00128               */
00129 
00130               for (r= p->ptr; r; r= r->next )
00131                      if (r->token == '@')
00132                      {
00133                             (*func)(p);
00134                             return;
00135                      }
00136 
00137               for (q= &p->ptr; *q; q= & (*q)->next )
00138               {
00139                      if ((*q)->token == '!')
00140                             break;
00141               }
00142 
00143               if (*q)
00144               {
00145               char   *uun;
00146               size_t uunl;
00147               char   *addr;
00148 
00149                      uucpneighbors_init();
00150 
00151                      r=*q;
00152                      *q=0;
00153                      addr=rfc822_gettok(p->ptr);
00154                      *q=r;
00155 
00156                      if (!addr)    clog_msg_errno();
00157 
00158                      uun=0;
00159                      if (uucpneighbors_isopen)
00160                             uun=dbobj_fetch(&uucpneighbors, addr,
00161                                    strlen(addr), &uunl, "");
00162                      free(addr);
00163 
00164                      if (uun)      /* We will relay this via UUCP */
00165                      {
00166                             free(uun);
00167                             (*func)(p);
00168                             return;
00169                      }
00170               }
00171               else /* Only one node - must be a local address */
00172               {
00173                      rw_local_defaulthost(p, func);
00174                      return;
00175               }
00176 
00177               /* Rewrite domain.com!foo as foo@domain.com */
00178 
00179               r= *q;
00180 
00181               *q=0;
00182 
00183               for (q= &r->next; *q; q= & (*q)->next )
00184                      ;
00185 
00186               *q=r;
00187               r2=r->next;
00188               r->next=p->ptr;
00189               r->token='@';
00190               p->ptr=r2;
00191               (*func)(p);
00192               return;
00193        }
00194 
00195 /* From canonical to UUCP */
00196 
00197 /* Ok, if we have user@host, rewrite it either as user, if host is us, or
00198 ** host!user */
00199 
00200        for (q= &p->ptr; *q; q= & (*q)->next )
00201               if ( (*q)->token == '@' )
00202               {
00203               struct rfc822token *at, *host, **z;
00204               char   *hostdomain=0;
00205 
00206                      if (configt_islocal((*q)->next,
00207                             &hostdomain) && hostdomain == 0)
00208                      {
00209                             *q=0;
00210                             break;
00211                      }
00212                      if (hostdomain)      free(hostdomain);
00213 
00214                      at= *q;
00215                      at->token='!';
00216                      host=at->next;
00217                      *q=0;
00218                      at->next=p->ptr;
00219                      p->ptr=host;
00220 
00221                      for (z= &p->ptr; *z; z= & (*z)->next)
00222                             ;
00223 
00224                      *z=at;
00225 
00226                      prepend_me(p, func);
00227                      return;
00228               }
00229 
00230        prepend_me(p, func);
00231 }
00232 
00233 static void prepend_me(struct rw_info *p, void (*func)(struct rw_info *))
00234 {
00235 struct rfc822token metoken, bangtoken;
00236 
00237        if (p->ptr && p->ptr->token == 0 && p->ptr->len == 0)
00238               p->ptr=p->ptr->next;
00239 
00240        if (p->ptr == 0)
00241        {
00242               (*func)(p);
00243               return;
00244        }
00245 
00246        /* Before we prepend uucp! to an address, see if this address is
00247        ** "a!b!c!d...", and we are forwarding it to "a!b!rmail", in which
00248        ** case we'll rewrite it as "c!d!..."
00249        */
00250 
00251        if (p->host)
00252        {
00253        const struct rfc822token *q;
00254        struct rfc822token *r;
00255 
00256               for (q=p->host, r=p->ptr; q && r; q=q->next, r=r->next)
00257               {
00258                      if (q->token != r->token)   break;
00259                      if (!rfc822_is_atom(q->token))     continue;
00260                      if (q->len != r->len)       break;
00261                      if (memcmp(q->ptr, r->ptr, q->len))       break;
00262               }
00263 
00264               if (q == 0 && r && r->token == '!' && r->next)
00265               {
00266                      p->ptr=r->next;
00267                      (*func)(p);
00268                      return;
00269               }
00270        }
00271 
00272        metoken.token=0;
00273        metoken.ptr=uucpme();
00274        metoken.len=strlen(metoken.ptr);
00275        metoken.next= &bangtoken;
00276        bangtoken.token='!';
00277        bangtoken.ptr="!";
00278        bangtoken.len=1;
00279        bangtoken.next=p->ptr;
00280        p->ptr= &metoken;
00281        (*func)(p);
00282 }
00283 
00284 static void rw_del_uucp(struct rw_info *rwi,
00285                      void (*nextfunc)(struct rw_info *),
00286               void (*delfunc)(struct rw_info *, const struct rfc822token *,
00287                             const struct rfc822token *))
00288 {
00289 int    hasbang=0;
00290 struct rfc822token **prev, *p;
00291 struct rfc822token **uux_bang;
00292 
00293        for (prev=&rwi->ptr; *prev; prev=&(*prev)->next)
00294        {
00295               if ((*prev)->token == '!')
00296                      hasbang=1;
00297               if ((*prev)->token == '@')
00298                      break;
00299        }
00300 
00301        if (!hasbang)
00302        {
00303               (*nextfunc)(rwi);
00304               return;
00305        }
00306 
00307        if ( (p=*prev) != 0 && p->next)
00308        {
00309        char   *hostdomain=0;
00310 
00311               if (!configt_islocal(p->next, &hostdomain))
00312               {
00313                      (*nextfunc)(rwi);
00314                      return;
00315               }
00316               if (hostdomain)      free(hostdomain);
00317        }
00318 
00319        *prev=0;
00320 
00321        hasbang=1;
00322        for (p=rwi->ptr; p; p=p->next, hasbang=0)
00323        {
00324               if (p->token != '!') continue;
00325               if (hasbang || p->next == 0 || p->next->token == '!')
00326               {
00327                      (*rwi->err_func)(550, "Invalid UUCP bang path.", rwi);
00328                      return;
00329               }
00330        }
00331 
00332        uux_bang=0;
00333 
00334        uucpneighbors_init();
00335 
00336        for (prev=&rwi->ptr; *prev; prev=&(*prev)->next)
00337        {
00338        char   *addr;
00339        char   *uun;
00340        size_t uunl;
00341        size_t i;
00342 
00343               if ( (*prev)->token != '!') continue;
00344               p= *prev;
00345               *prev=0;
00346               addr=rfc822_gettok(rwi->ptr);
00347               *prev=p;
00348               if (!addr)    clog_msg_errno();
00349 
00350               uun=0;
00351               uunl=0;
00352 
00353               if (uucpneighbors_isopen)
00354                      uun=dbobj_fetch(&uucpneighbors, addr, strlen(addr),
00355                             &uunl, "");
00356               free(addr);
00357 
00358               if (uun == 0)
00359               {
00360                      prev=0;
00361                      break;
00362               }
00363 
00364               for (i=0; i<uunl; i++)
00365                      if (uun[i] == 'R')
00366                      {
00367                             /* Relay, run rmail here */
00368 
00369                             if (!uux_bang)
00370                                    uux_bang= prev;
00371                             break;
00372                      }
00373 
00374               for (i=0; i<uunl; i++)
00375                      if (uun[i] == 'G')
00376                             break;
00377 
00378               if (i < uunl)        /* Gateway, ignore rest of path */
00379               {
00380                      if (!uux_bang)
00381                             uux_bang= prev;
00382                      free(uun);
00383                      break;
00384               }
00385 
00386               p= (*prev)->next;
00387 
00388               if (p->next == 0)
00389               {
00390                      free(uun);
00391                      break;
00392               }
00393 
00394               /* This one must marked as F - OK to forward through here */
00395 
00396               for (i=0; i<uunl; i++)
00397                      if (uun[i] == 'F')
00398                             break;
00399               free(uun);
00400 
00401               if ( i < uunl)       break;
00402        }
00403 
00404        if (!prev || *prev == 0)
00405        {
00406               (*rwi->err_func)(550, "Unknown UUCP bang path.", rwi);
00407               return;
00408        }
00409 
00410        if (uux_bang == 0)
00411        {
00412               for (prev=&rwi->ptr; *prev; prev=&(*prev)->next)
00413                      if ( (*prev)->token == '!' )
00414                             uux_bang= prev;
00415        }
00416 
00417        p= (*uux_bang)->next;
00418        *uux_bang=0;
00419 
00420        if (rwi->mode & RW_VERIFY)
00421        {
00422               (*rwi->err_func)(550, "Remote address.", rwi);
00423               return;
00424        }
00425 
00426 #if 1
00427        (*delfunc)(rwi, rwi->ptr, p);
00428 #else
00429        {
00430        char *a=rfc822_gettok(rwi->ptr);
00431        char *b=rfc822_gettok(p);
00432        char *c;
00433 
00434               if (!a || !b || !(c=malloc(strlen(a)+strlen(b)+100)))
00435               {
00436                      clog_msg_errno();
00437                      return;
00438               }
00439 
00440               strcat(strcat(strcat(strcpy(c, "uux "), a), "!rmail "), b);
00441               (*rwi->err_func)(550, c, rwi);
00442               free(a);
00443               free(b);
00444               free(c);
00445        }
00446 #endif
00447 }