s/qmail 4.3.20
Next generation secure email transport
Loading...
Searching...
No Matches
newaliases.c
Go to the documentation of this file.
1#include <unistd.h>
2#include <sys/stat.h>
3#include "buffer.h"
4#include "logmsg.h"
5#include "genalloc.h"
6#include "stralloc.h"
7#include "getln.h"
8#include "open.h"
9#include "token822.h"
10#include "control.h"
11#include "auto_qmail.h"
12#include "case.h"
13#include "cdbmake.h"
14#include "byte.h"
15#include "qmail.h"
16
17#define WHO "newaliases"
18
19int rename(const char *,const char *); // stdio.h
20
21static void nomem()
22{
23 logmsg(WHO,111,FATAL,"out of memory");
24}
25/* static void nulbyte()
26{
27 logmsg(WHO,100,FATAL,"NUL bytes are not permitted");
28} */
29static void longaddress()
30{
31 logmsg(WHO,100,FATAL,"addresses over 800 bytes are not permitted");
32}
33static void writeerr()
34{
35 logmsg(WHO,111,FATAL,"unable to write to /etc/aliases.tmp");
36}
37static void readerr()
38{
39 logmsg(WHO,111,FATAL,"unable to read /etc/aliases");
40}
41static void die_control()
42{
43 logmsg(WHO,111,FATAL,"unable to read controls");
44}
45
46stralloc me = {0};
47stralloc defaulthost = {0};
48stralloc defaultdomain = {0};
49stralloc plusdomain = {0};
50
52{
53 int r;
54 int fddir;
55
56 fddir = open_read(".");
57 if (fddir == -1)
58 logmsg(WHO,111,FATAL,"unable to open current directory");
59
60 if (chdir(auto_qmail) == -1)
61 logmsg(WHO,111,FATAL,B("unable to chdir to: ",auto_qmail));
62
63 r = control_readline(&me,"control/me");
64 if (r == -1) die_control();
65 if (!r) if (!stralloc_copys(&me,"me")) nomem();
66
67 r = control_readline(&defaultdomain,"control/defaultdomain");
68 if (r == -1) die_control();
69 if (!r) if (!stralloc_copy(&defaultdomain,&me)) nomem();
70
71 r = control_readline(&defaulthost,"control/defaulthost");
72 if (r == -1) die_control();
73 if (!r) if (!stralloc_copy(&defaulthost,&me)) nomem();
74
75 r = control_readline(&plusdomain,"control/plusdomain");
76 if (r == -1) die_control();
77 if (!r) if (!stralloc_copy(&plusdomain,&me)) nomem();
78
79 if (fchdir(fddir) == -1)
80 logmsg(WHO,111,FATAL,"unable to set current directory");
81}
82
83stralloc target = {0};
84stralloc fulltarget = {0};
85stralloc instr = {0};
86
87stralloc cbuf = {0};
88token822_alloc toks = {0};
89token822_alloc tokaddr = {0};
90stralloc address = {0};
91
92static void gotincl()
93{
96 tokaddr.len = 0;
97
98 if (!address.len)
99 logmsg(WHO,111,FATAL,"empty :include: filenames not permitted");
100 if (byte_chr(address.s,address.len,'\0') < address.len)
101 logmsg(WHO,111,FATAL,"NUL not permitted in :include: filenames");
102
103 if ((address.s[0] != '.') && (address.s[0] != '/'))
104 if (!stralloc_cats(&instr,"./")) nomem();
105 if (!stralloc_cat(&instr,&address)) nomem();
106 if (!stralloc_cats(&instr,".bin")) nomem();
107 if (!stralloc_0(&instr)) nomem();
108}
109
110static void gotaddr()
111{
112 int i;
113 int j;
114 int flaghasat;
115
117 if (token822_unquote(&address,&tokaddr) != 1) nomem();
118
119 if (!address.len)
120 logmsg(WHO,111,FATAL,"empty recipient addresses not permitted");
121
122 flaghasat = 0;
123 for (i = 0; i < tokaddr.len; ++i)
124 if (tokaddr.t[i].type == TOKEN822_AT)
125 flaghasat = 1;
126
127 tokaddr.len = 0;
128
129 if (!address.len) return;
130
131 if (!flaghasat)
132 if (address.s[0] == '/') {
133 if (!stralloc_0(&address)) nomem();
134 logmsg(WHO,111,FATAL,B("file delivery for ",address.s," not supported"));
135 }
136 if (!flaghasat)
137 if (address.s[0] == '|') {
138 if (byte_chr(address.s,address.len,'\0') < address.len)
139 logmsg(WHO,111,FATAL,"NUL not permitted in program names");
140 if (!stralloc_cats(&instr,"!")) nomem();
141 if (!stralloc_catb(&instr,address.s + 1,address.len - 1)) nomem();
142 if (!stralloc_0(&instr)) nomem();
143 return;
144 }
145
146
147 if (target.len) {
148 if (!stralloc_cats(&instr,"&")) nomem();
149 if (!stralloc_cat(&instr,&fulltarget)) nomem();
150 if (!stralloc_0(&instr)) nomem();
151 }
152
153 if (!flaghasat)
154 if (!stralloc_cats(&address,"@")) nomem();
155
156 if (!stralloc_copy(&target,&address)) nomem();
157 if (!stralloc_copy(&fulltarget,&address)) nomem();
158
159 if (fulltarget.s[fulltarget.len - 1] == '@')
160 if (!stralloc_cat(&fulltarget,&defaulthost)) nomem();
161 if (fulltarget.s[fulltarget.len - 1] == '+') {
162 fulltarget.s[fulltarget.len - 1] = '.';
163 if (!stralloc_cat(&fulltarget,&plusdomain)) nomem();
164 }
165
166 j = 0;
167 for (i = 0;i < fulltarget.len;++i) if (fulltarget.s[i] == '@') j = i;
168 for (i = j;i < fulltarget.len;++i) if (fulltarget.s[i] == '.') break;
169 if (i == fulltarget.len) {
170 if (!stralloc_cats(&fulltarget,".")) nomem();
171 if (!stralloc_cat(&fulltarget,&defaultdomain)) nomem();
172 }
173
174 if (fulltarget.len > 800) longaddress();
175 if (byte_chr(fulltarget.s,fulltarget.len,'\0') < fulltarget.len)
176 logmsg(WHO,111,FATAL,"NUL not permitted in recipient addresses");
177}
178
179stralloc line = {0};
180stralloc newline = {0};
182
183static void parseerr()
184{
185 if (!stralloc_0(&line)) nomem();
186 logmsg(WHO,111,FATAL,B("unable to parse this line: ",line.s));
187}
188
189static void parseline()
190{
191 int wordok;
192 struct token822 *t;
193 struct token822 *beginning;
194
195 switch (token822_parse(&toks,&line,&cbuf)) {
196 case -1: nomem();
197 case 0: parseerr();
198 }
199
200 beginning = toks.t;
201 t = toks.t + toks.len;
202 wordok = 1;
203
204 if (!token822_readyplus(&tokaddr,1)) nomem();
205 tokaddr.len = 0;
206
207 while (t > beginning)
208 switch ((--t)->type) {
209 case TOKEN822_SEMI:
210 break; /*XXX*/
211 case TOKEN822_COLON:
212 if (t >= beginning + 2)
213 if (t[-2].type == TOKEN822_COLON)
214 if (t[-1].type == TOKEN822_ATOM)
215 if (t[-1].slen == 7)
216 if (!byte_diff(t[-1].s,7,"include")) {
217 gotincl();
218 t -= 2;
219 }
220 break; /*XXX*/
221 case TOKEN822_RIGHT:
222 if (tokaddr.len) gotaddr();
223 while ((t > beginning) && (t[-1].type != TOKEN822_LEFT))
224 if (!token822_append(&tokaddr,--t)) nomem();
225 gotaddr();
226 if (t <= beginning) parseerr();
227 --t;
228 while ((t > beginning) && ((t[-1].type == TOKEN822_COMMENT) || (t[-1].type == TOKEN822_ATOM) || (t[-1].type == TOKEN822_QUOTE) || (t[-1].type == TOKEN822_AT) || (t[-1].type == TOKEN822_DOT)))
229 --t;
230 wordok = 0;
231 continue;
233 if (!wordok) if (tokaddr.len) gotaddr();
234 wordok = 0;
235 if (!token822_append(&tokaddr,t)) nomem();
236 continue;
237 case TOKEN822_COMMENT:
238 /* comment is lexically a space; shouldn't affect wordok */
239 break;
240 case TOKEN822_COMMA:
241 if (tokaddr.len) gotaddr();
242 wordok = 1;
243 break;
244 default:
245 wordok = 1;
246 if (!token822_append(&tokaddr,t)) nomem();
247 continue;
248 }
249 if (tokaddr.len) gotaddr();
250}
251
253buffer bi;
254struct cdb_make cdb;
255stralloc key = {0};
256
257static void doit()
258{
259 if (!instr.len) {
260 if (target.len) parseerr();
261 return;
262 }
263
264 if (!target.len) parseerr();
265
266 if (stralloc_starts(&target,"owner-")) {
267 if (!stralloc_copys(&key,"?")) nomem();
268 if (!stralloc_catb(&key,target.s + 6,target.len - 6)) nomem();
269 case_lowerb(key.s,key.len);
270 if (cdb_make_add(&cdb,key.s,key.len,fulltarget.s,fulltarget.len) == -1) writeerr();
271 }
272
273 if (!stralloc_copys(&key,":")) nomem();
274 if (!stralloc_cat(&key,&target)) nomem();
275 case_lowerb(key.s,key.len);
276 if (cdb_make_add(&cdb,key.s,key.len,instr.s,instr.len) == -1) writeerr();
277}
278
279int main()
280{
281 int fd;
282
283 umask(033);
284 readcontrols();
285
286 fd = open_read("/etc/aliases");
287 if (fd == -1) readerr();
288 buffer_init(&bi,read,fd,inbuf,sizeof(inbuf));
289
290 fd = open_trunc("/etc/aliases.tmp");
291 if (fd == -1) logmsg(WHO,111,FATAL,"unable to create /etc/aliases.tmp");
292 if (cdb_make_start(&cdb,fd) == -1) writeerr();
293
294 if (!stralloc_copys(&line,"")) nomem();
295
296 for (;;) {
297 if (getln(&bi,&newline,&match,'\n') != 0) readerr();
298
299 if (match && (newline.s[0] == '\n')) continue;
300
301 if (match && ((newline.s[0] == ' ') || (newline.s[0] == '\t'))) {
302 if (!stralloc_cat(&line,&newline)) nomem();
303 continue;
304 }
305
306 if (line.len)
307 if (line.s[0] != '#') {
308 if (!stralloc_copys(&target,"")) nomem();
309 if (!stralloc_copys(&fulltarget,"")) nomem();
310 if (!stralloc_copys(&instr,"")) nomem();
311 parseline();
312 doit();
313 }
314
315 if (!match) break;
316 if (!stralloc_copy(&line,&newline)) nomem();
317 }
318
319 if (cdb_make_finish(&cdb) == -1) writeerr();
320 if (fsync(fd) == -1) writeerr();
321 if (close(fd) == -1) writeerr(); /* NFS stupidity */
322
323 if (rename("/etc/aliases.tmp","/etc/aliases.cdb") == -1)
324 logmsg(WHO,111,FATAL,"unable to move /etc/aliases.tmp to /etc/aliases.cdb");
325
326 _exit(0);
327}
char auto_qmail[]
void nomem()
Definition: columnt.c:15
int control_readline(stralloc *sa, char *fn)
Definition: control.c:53
int stralloc_copys(stralloc *, char const *)
void _exit(int)
stralloc me
Definition: newaliases.c:46
stralloc key
Definition: newaliases.c:255
stralloc defaulthost
Definition: newaliases.c:47
stralloc instr
Definition: newaliases.c:85
struct cdb_make cdb
Definition: newaliases.c:254
stralloc cbuf
Definition: newaliases.c:87
token822_alloc toks
Definition: newaliases.c:88
int rename(const char *, const char *)
stralloc address
Definition: newaliases.c:90
void readcontrols()
Definition: newaliases.c:51
stralloc newline
Definition: newaliases.c:180
stralloc line
Definition: newaliases.c:179
buffer bi
Definition: newaliases.c:253
token822_alloc tokaddr
Definition: newaliases.c:89
stralloc plusdomain
Definition: newaliases.c:49
stralloc target
Definition: newaliases.c:83
stralloc fulltarget
Definition: newaliases.c:84
int match
Definition: newaliases.c:181
stralloc defaultdomain
Definition: newaliases.c:48
#define WHO
Definition: newaliases.c:17
int main()
Definition: newaliases.c:279
char inbuf[BUFSIZE_LINE]
Definition: newaliases.c:252
int fd
int j
Definition: qmail-send.c:926
#define BUFSIZE_LINE
Definition: qmail.h:8
void die_control(void)
Definition: qmail-qmqpc.c:31
int slen
Definition: token822.h:9
char * s
Definition: token822.h:8
int type
Definition: token822.h:7
int token822_parse(token822_alloc *ta, stralloc *sa, stralloc *buf)
Definition: token822.c:220
#define TOKEN822_ATOM
Definition: token822.h:29
#define TOKEN822_COMMENT
Definition: token822.h:32
int token822_append(token822_alloc *, struct token822 *)
#define TOKEN822_RIGHT
Definition: token822.h:34
#define TOKEN822_LEFT
Definition: token822.h:33
#define TOKEN822_COMMA
Definition: token822.h:36
int token822_unquote(stralloc *, token822_alloc *)
Definition: token822.c:168
#define TOKEN822_AT
Definition: token822.h:35
#define TOKEN822_SEMI
Definition: token822.h:37
void token822_reverse(token822_alloc *)
Definition: token822.c:9
#define TOKEN822_DOT
Definition: token822.h:39
#define TOKEN822_COLON
Definition: token822.h:38
#define TOKEN822_LITERAL
Definition: token822.h:31
#define TOKEN822_QUOTE
Definition: token822.h:30
int token822_readyplus(token822_alloc *, unsigned int)