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