|
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 } |