qmail-lspawn.c
changeset 0 068428edee47
equal deleted inserted replaced
-1:000000000000 0:068428edee47
       
     1 #include "fd.h"
       
     2 #include "wait.h"
       
     3 #include "prot.h"
       
     4 #include "substdio.h"
       
     5 #include "stralloc.h"
       
     6 #include "scan.h"
       
     7 #include "exit.h"
       
     8 #include "fork.h"
       
     9 #include "error.h"
       
    10 #include "cdb.h"
       
    11 #include "case.h"
       
    12 #include "slurpclose.h"
       
    13 #include "auto_qmail.h"
       
    14 #include "auto_uids.h"
       
    15 #include "qlx.h"
       
    16 
       
    17 char *aliasempty;
       
    18 
       
    19 void initialize(argc,argv)
       
    20 int argc;
       
    21 char **argv;
       
    22 {
       
    23   aliasempty = argv[1];
       
    24   if (!aliasempty) _exit(100);
       
    25 }
       
    26 
       
    27 int truncreport = 3000;
       
    28 
       
    29 void report(ss,wstat,s,len)
       
    30 substdio *ss;
       
    31 int wstat;
       
    32 char *s;
       
    33 int len;
       
    34 {
       
    35  int i;
       
    36  if (wait_crashed(wstat))
       
    37   { substdio_puts(ss,"Zqmail-local crashed.\n"); return; }
       
    38  switch(wait_exitcode(wstat))
       
    39   {
       
    40    case QLX_CDB:
       
    41      substdio_puts(ss,"ZTrouble reading users/cdb in qmail-lspawn.\n"); return;
       
    42    case QLX_NOMEM:
       
    43      substdio_puts(ss,"ZOut of memory in qmail-lspawn.\n"); return;
       
    44    case QLX_SYS:
       
    45      substdio_puts(ss,"ZTemporary failure in qmail-lspawn.\n"); return;
       
    46    case QLX_NOALIAS:
       
    47      substdio_puts(ss,"ZUnable to find alias user!\n"); return;
       
    48    case QLX_ROOT:
       
    49      substdio_puts(ss,"ZNot allowed to perform deliveries as root.\n"); return;
       
    50    case QLX_USAGE:
       
    51      substdio_puts(ss,"ZInternal qmail-lspawn bug.\n"); return;
       
    52    case QLX_NFS:
       
    53      substdio_puts(ss,"ZNFS failure in qmail-local.\n"); return;
       
    54    case QLX_EXECHARD:
       
    55      substdio_puts(ss,"DUnable to run qmail-local.\n"); return;
       
    56    case QLX_EXECSOFT:
       
    57      substdio_puts(ss,"ZUnable to run qmail-local.\n"); return;
       
    58    case QLX_EXECPW:
       
    59      substdio_puts(ss,"ZUnable to run qmail-getpw.\n"); return;
       
    60    case 111: case 71: case 74: case 75:
       
    61      substdio_put(ss,"Z",1); break;
       
    62    case 0:
       
    63      substdio_put(ss,"K",1); break;
       
    64    case 100:
       
    65    default:
       
    66      substdio_put(ss,"D",1); break;
       
    67   }
       
    68 
       
    69  for (i = 0;i < len;++i) if (!s[i]) break;
       
    70  substdio_put(ss,s,i);
       
    71 }
       
    72 
       
    73 stralloc lower = {0};
       
    74 stralloc nughde = {0};
       
    75 stralloc wildchars = {0};
       
    76 
       
    77 void nughde_get(local)
       
    78 char *local;
       
    79 {
       
    80  char *(args[3]);
       
    81  int pi[2];
       
    82  int gpwpid;
       
    83  int gpwstat;
       
    84  int r;
       
    85  int fd;
       
    86  int flagwild;
       
    87 
       
    88  if (!stralloc_copys(&lower,"!")) _exit(QLX_NOMEM);
       
    89  if (!stralloc_cats(&lower,local)) _exit(QLX_NOMEM);
       
    90  if (!stralloc_0(&lower)) _exit(QLX_NOMEM);
       
    91  case_lowerb(lower.s,lower.len);
       
    92 
       
    93  if (!stralloc_copys(&nughde,"")) _exit(QLX_NOMEM);
       
    94 
       
    95  fd = open_read("users/cdb");
       
    96  if (fd == -1)
       
    97    if (errno != error_noent)
       
    98      _exit(QLX_CDB);
       
    99 
       
   100  if (fd != -1)
       
   101   {
       
   102    uint32 dlen;
       
   103    unsigned int i;
       
   104 
       
   105    r = cdb_seek(fd,"",0,&dlen);
       
   106    if (r != 1) _exit(QLX_CDB);
       
   107    if (!stralloc_ready(&wildchars,(unsigned int) dlen)) _exit(QLX_NOMEM);
       
   108    wildchars.len = dlen;
       
   109    if (cdb_bread(fd,wildchars.s,wildchars.len) == -1) _exit(QLX_CDB);
       
   110 
       
   111    i = lower.len;
       
   112    flagwild = 0;
       
   113 
       
   114    do
       
   115     {
       
   116      /* i > 0 */
       
   117      if (!flagwild || (i == 1) || (byte_chr(wildchars.s,wildchars.len,lower.s[i - 1]) < wildchars.len))
       
   118       {
       
   119        r = cdb_seek(fd,lower.s,i,&dlen);
       
   120        if (r == -1) _exit(QLX_CDB);
       
   121        if (r == 1)
       
   122         {
       
   123          if (!stralloc_ready(&nughde,(unsigned int) dlen)) _exit(QLX_NOMEM);
       
   124          nughde.len = dlen;
       
   125          if (cdb_bread(fd,nughde.s,nughde.len) == -1) _exit(QLX_CDB);
       
   126          if (flagwild)
       
   127 	   if (!stralloc_cats(&nughde,local + i - 1)) _exit(QLX_NOMEM);
       
   128          if (!stralloc_0(&nughde)) _exit(QLX_NOMEM);
       
   129          close(fd);
       
   130          return;
       
   131         }
       
   132       }
       
   133      --i;
       
   134      flagwild = 1;
       
   135     }
       
   136    while (i);
       
   137 
       
   138    close(fd);
       
   139   }
       
   140 
       
   141  if (pipe(pi) == -1) _exit(QLX_SYS);
       
   142  args[0] = "bin/qmail-getpw";
       
   143  args[1] = local;
       
   144  args[2] = 0;
       
   145  switch(gpwpid = vfork())
       
   146   {
       
   147    case -1:
       
   148      _exit(QLX_SYS);
       
   149    case 0:
       
   150      if (prot_gid(auto_gidn) == -1) _exit(QLX_USAGE);
       
   151      if (prot_uid(auto_uidp) == -1) _exit(QLX_USAGE);
       
   152      close(pi[0]);
       
   153      if (fd_move(1,pi[1]) == -1) _exit(QLX_SYS);
       
   154      execv(*args,args);
       
   155      _exit(QLX_EXECPW);
       
   156   }
       
   157  close(pi[1]);
       
   158 
       
   159  if (slurpclose(pi[0],&nughde,128) == -1) _exit(QLX_SYS);
       
   160 
       
   161  if (wait_pid(&gpwstat,gpwpid) != -1)
       
   162   {
       
   163    if (wait_crashed(gpwstat)) _exit(QLX_SYS);
       
   164    if (wait_exitcode(gpwstat) != 0) _exit(wait_exitcode(gpwstat));
       
   165   }
       
   166 }
       
   167 
       
   168 int spawn(fdmess,fdout,s,r,at)
       
   169 int fdmess; int fdout;
       
   170 char *s; char *r; int at;
       
   171 {
       
   172  int f;
       
   173 
       
   174  if (!(f = fork()))
       
   175   {
       
   176    char *(args[11]);
       
   177    unsigned long u;
       
   178    int n;
       
   179    int uid;
       
   180    int gid;
       
   181    char *x;
       
   182    unsigned int xlen;
       
   183    
       
   184    r[at] = 0;
       
   185    if (!r[0]) _exit(0); /* <> */
       
   186 
       
   187    if (chdir(auto_qmail) == -1) _exit(QLX_USAGE);
       
   188 
       
   189    nughde_get(r);
       
   190 
       
   191    x = nughde.s;
       
   192    xlen = nughde.len;
       
   193 
       
   194    args[0] = "bin/qmail-local";
       
   195    args[1] = "--";
       
   196    args[2] = x;
       
   197    n = byte_chr(x,xlen,0); if (n++ == xlen) _exit(QLX_USAGE); x += n; xlen -= n;
       
   198 
       
   199    scan_ulong(x,&u);
       
   200    uid = u;
       
   201    n = byte_chr(x,xlen,0); if (n++ == xlen) _exit(QLX_USAGE); x += n; xlen -= n;
       
   202 
       
   203    scan_ulong(x,&u);
       
   204    gid = u;
       
   205    n = byte_chr(x,xlen,0); if (n++ == xlen) _exit(QLX_USAGE); x += n; xlen -= n;
       
   206 
       
   207    args[3] = x;
       
   208    n = byte_chr(x,xlen,0); if (n++ == xlen) _exit(QLX_USAGE); x += n; xlen -= n;
       
   209 
       
   210    args[4] = r;
       
   211    args[5] = x;
       
   212    n = byte_chr(x,xlen,0); if (n++ == xlen) _exit(QLX_USAGE); x += n; xlen -= n;
       
   213 
       
   214    args[6] = x;
       
   215    n = byte_chr(x,xlen,0); if (n++ == xlen) _exit(QLX_USAGE); x += n; xlen -= n;
       
   216 
       
   217    args[7] = r + at + 1;
       
   218    args[8] = s;
       
   219    args[9] = aliasempty;
       
   220    args[10] = 0;
       
   221 
       
   222    if (fd_move(0,fdmess) == -1) _exit(QLX_SYS);
       
   223    if (fd_move(1,fdout) == -1) _exit(QLX_SYS);
       
   224    if (fd_copy(2,1) == -1) _exit(QLX_SYS);
       
   225    if (prot_gid(gid) == -1) _exit(QLX_USAGE);
       
   226    if (prot_uid(uid) == -1) _exit(QLX_USAGE);
       
   227    if (!getuid()) _exit(QLX_ROOT);
       
   228 
       
   229    execv(*args,args);
       
   230    if (error_temp(errno)) _exit(QLX_EXECSOFT);
       
   231    _exit(QLX_EXECHARD);
       
   232   }
       
   233  return f;
       
   234 }