s/qmail 4.3.20
Next generation secure email transport
Loading...
Searching...
No Matches
qmail-pw2u.c
Go to the documentation of this file.
1#include <unistd.h>
2#include <sys/types.h>
3#include <sys/stat.h>
4#include "buffer.h"
5#include "getoptb.h"
6#include "control.h"
7#include "constmap.h"
8#include "stralloc.h"
9#include "fmt.h"
10#include "str.h"
11#include "scan.h"
12#include "open.h"
13#include "logmsg.h"
14#include "exit.h"
15#include "getln.h"
16#include "byte.h"
17#include "auto_break.h"
18#include "auto_qmail.h"
19#include "auto_usera.h"
20#include "qmail.h"
21
22#define WHO "qmail-pw2u"
23
24static void die_chdir()
25{
26 buffer_putsflush(buffer_2,"qmail-pw2u: fatal: unable to chdir\n");
27 _exit(111);
28}
29
30static void die_nomem()
31{
32 buffer_putsflush(buffer_2,"qmail-pw2u: fatal: out of memory\n");
33 _exit(111);
34}
35
36static void die_read()
37{
38 buffer_putsflush(buffer_2,"qmail-pw2u: fatal: unable to read input\n");
39 _exit(111);
40}
41
42static void die_write()
43{
44 buffer_putsflush(buffer_2,"qmail-pw2u: fatal: unable to write output\n");
45 _exit(111);
46}
47
48static void die_control()
49{
50 buffer_putsflush(buffer_2,"qmail-pw2u: fatal: unable to read controls\n");
51 _exit(111);
52}
53
54static void die_alias()
55{
56 buffer_puts(buffer_2,"qmail-pw2u: fatal: unable to find ");
57 buffer_puts(buffer_2,auto_usera);
58 buffer_puts(buffer_2," user\n");
59 buffer_flush(buffer_2);
60 _exit(111);
61}
62
63static void die_home(char *fn)
64{
65 buffer_puts(buffer_2,"qmail-pw2u: fatal: unable to stat ");
66 buffer_puts(buffer_2,fn);
67 buffer_puts(buffer_2,"\n");
68 buffer_flush(buffer_2);
69 _exit(111);
70}
71
72static void die_user(char *s,unsigned int len)
73{
74 buffer_puts(buffer_2,"qmail-pw2u: fatal: unable to find ");
75 buffer_put(buffer_2,s,len);
76 buffer_puts(buffer_2," user for subuser\n");
77 buffer_flush(buffer_2);
78 _exit(111);
79}
80
81char *dashcolon = "-:";
82int flagalias = 0;
85/* 2: skip if home does not exist; skip if home is not owned by user */
86/* 1: stop if home does not exist; skip if home is not owned by user */
87/* 0: don't worry about home */
88
89int okincl; stralloc incl = {0}; struct constmap mapincl;
90int okexcl; stralloc excl = {0}; struct constmap mapexcl;
91int okmana; stralloc mana = {0}; struct constmap mapmana;
92
93stralloc allusers = {0}; struct constmap mapuser;
94
95stralloc uugh = {0};
96stralloc user = {0};
97stralloc uidstr = {0};
98stralloc gidstr = {0};
99stralloc home = {0};
100unsigned long uid;
101
102stralloc line = {0};
103
104static void doaccount()
105{
106 struct stat st;
107 int i;
108 char *mailnames;
109 char *x;
110 unsigned int xlen;
111
112 if (byte_chr(line.s,line.len,'\0') < line.len) return;
113
114 x = line.s; xlen = line.len; i = byte_chr(x,xlen,':'); if (i == xlen) return;
115 if (!stralloc_copyb(&user,x,i)) die_nomem();
116 if (!stralloc_0(&user)) die_nomem();
117 ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return;
118 ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return;
119 if (!stralloc_copyb(&uidstr,x,i)) die_nomem();
120 if (!stralloc_0(&uidstr)) die_nomem();
121 scan_ulong(uidstr.s,&uid);
122 ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return;
123 if (!stralloc_copyb(&gidstr,x,i)) die_nomem();
124 if (!stralloc_0(&gidstr)) die_nomem();
125 ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return;
126 ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return;
127 if (!stralloc_copyb(&home,x,i)) die_nomem();
128 if (!stralloc_0(&home)) die_nomem();
129
130 if (!uid) return;
131 if (flagnoupper)
132 for (i = 0; i < user.len; ++i)
133 if ((user.s[i] >= 'A') && (user.s[i] <= 'Z'))
134 return;
135 if (okincl)
136 if (!constmap(&mapincl,user.s,user.len - 1))
137 return;
138 if (okexcl)
139 if (constmap(&mapexcl,user.s,user.len - 1))
140 return;
141 if (homestrategy) {
142 if (stat(home.s,&st) == -1) {
143 if (errno != ENOENT) die_home(home.s);
144 if (homestrategy == 1) die_home(home.s);
145 return;
146 }
147 if (st.st_uid != uid) return;
148 }
149
150 if (!stralloc_copys(&uugh,":")) die_nomem();
151 if (!stralloc_cats(&uugh,user.s)) die_nomem();
152 if (!stralloc_cats(&uugh,":")) die_nomem();
153 if (!stralloc_cats(&uugh,uidstr.s)) die_nomem();
154 if (!stralloc_cats(&uugh,":")) die_nomem();
155 if (!stralloc_cats(&uugh,gidstr.s)) die_nomem();
156 if (!stralloc_cats(&uugh,":")) die_nomem();
157 if (!stralloc_cats(&uugh,home.s)) die_nomem();
158 if (!stralloc_cats(&uugh,":")) die_nomem();
159
160 /* XXX: avoid recording in allusers unlein sub actually needs it */
161 if (!stralloc_cats(&allusers,user.s)) die_nomem();
162 if (!stralloc_cats(&allusers,":")) die_nomem();
163 if (!stralloc_catb(&allusers,uugh.s,uugh.len)) die_nomem();
164 if (!stralloc_0(&allusers)) die_nomem();
165
166 if (str_equal(user.s,auto_usera)) {
167 if (buffer_puts(buffer_1,"+") == -1) die_write();
168 if (buffer_put(buffer_1,uugh.s,uugh.len) == -1) die_write();
169 if (buffer_puts(buffer_1,dashcolon) == -1) die_write();
170 if (buffer_puts(buffer_1,":\n") == -1) die_write();
171 flagalias = 1;
172 }
173
174 mailnames = 0;
175 if (okmana)
176 mailnames = constmap(&mapmana,user.s,user.len - 1);
177 if (!mailnames)
178 mailnames = user.s;
179
180 for (;;) {
181 while (*mailnames == ':') ++mailnames;
182 if (!*mailnames) break;
183
184 i = str_chr(mailnames,':');
185
186 if (buffer_puts(buffer_1,"=") == -1) die_write();
187 if (buffer_put(buffer_1,mailnames,i) == -1) die_write();
188 if (buffer_put(buffer_1,uugh.s,uugh.len) == -1) die_write();
189 if (buffer_puts(buffer_1,"::\n") == -1) die_write();
190
191 if (*auto_break) {
192 if (buffer_puts(buffer_1,"+") == -1) die_write();
193 if (buffer_put(buffer_1,mailnames,i) == -1) die_write();
194 if (buffer_put(buffer_1,auto_break,1) == -1) die_write();
195 if (buffer_put(buffer_1,uugh.s,uugh.len) == -1) die_write();
196 if (buffer_puts(buffer_1,dashcolon) == -1) die_write();
197 if (buffer_puts(buffer_1,":\n") == -1) die_write();
198 }
199
200 mailnames += i;
201 }
202}
203
204stralloc sub = {0};
205
206static void dosubuser()
207{
208 int i;
209 char *x;
210 unsigned int xlen;
211 char *uugh;
212
213 x = line.s; xlen = line.len; i = byte_chr(x,xlen,':'); if (i == xlen) return;
214 if (!stralloc_copyb(&sub,x,i)) die_nomem();
215 ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return;
216 uugh = constmap(&mapuser,x,i);
217 if (!uugh) die_user(x,i);
218 ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return;
219
220 if (buffer_puts(buffer_1,"=") == -1) die_write();
221 if (buffer_put(buffer_1,sub.s,sub.len) == -1) die_write();
222 if (buffer_puts(buffer_1,uugh) == -1) die_write();
223 if (buffer_puts(buffer_1,dashcolon) == -1) die_write();
224 if (buffer_put(buffer_1,x,i) == -1) die_write();
225 if (buffer_puts(buffer_1,":\n") == -1) die_write();
226
227 if (*auto_break) {
228 if (buffer_puts(buffer_1,"+") == -1) die_write();
229 if (buffer_put(buffer_1,sub.s,sub.len) == -1) die_write();
230 if (buffer_put(buffer_1,auto_break,1) == -1) die_write();
231 if (buffer_puts(buffer_1,uugh) == -1) die_write();
232 if (buffer_puts(buffer_1,dashcolon) == -1) die_write();
233 if (buffer_put(buffer_1,x,i) == -1) die_write();
234 if (buffer_puts(buffer_1,"-:\n") == -1) die_write();
235 }
236}
237
238int fd;
240buffer in;
241
242int main(int argc,char * const *argv)
243{
244 int opt;
245 int match;
246
247 while ((opt = getoptb(argc,(char **)argv,"/ohHuUc:C")) != opteof)
248 switch (opt) {
249 case '/': dashcolon = "-/:"; break;
250 case 'o': homestrategy = 2; break;
251 case 'h': homestrategy = 1; break;
252 case 'H': homestrategy = 0; break;
253 case 'u': flagnoupper = 0; break;
254 case 'U': flagnoupper = 1; break;
255 case 'c': *auto_break = *optarg; break;
256 case 'C': *auto_break = 0; break;
257 case '?':
258 default : _exit(100);
259 }
260
261 if (chdir(auto_qmail) == -1) die_chdir();
262
263 /* no need for control_init() */
264
265 okincl = control_readfile(&incl,"users/include",0);
266 if (okincl == -1) die_control();
267 if (okincl) if (!constmap_init(&mapincl,incl.s,incl.len,0)) die_nomem();
268
269 okexcl = control_readfile(&excl,"users/exclude",0);
270 if (okexcl == -1) die_control();
271 if (okexcl) if (!constmap_init(&mapexcl,excl.s,excl.len,0)) die_nomem();
272
273 okmana = control_readfile(&mana,"users/mailnames",0);
274 if (okmana == -1) die_control();
275 if (okmana) if (!constmap_init(&mapmana,mana.s,mana.len,1)) die_nomem();
276
277 if (!stralloc_copys(&allusers,"")) die_nomem();
278
279 for (;;) {
280 if (getln(buffer_0,&line,&match,'\n') == -1) die_read();
281 doaccount();
282 if (!match) break;
283 }
284 if (!flagalias) die_alias();
285
286 fd = open_read("users/subusers");
287 if (fd == -1) {
288 if (errno != ENOENT) die_control();
289 }
290 else {
291 buffer_init(&in,buffer_unixread,fd,inbuf,sizeof(inbuf));
292
294
295 for (;;) {
296 if (getln(&in,&line,&match,'\n') == -1) die_read();
297 dosubuser();
298 if (!match) break;
299 }
300
301 close(fd);
302 }
303
304 fd = open_read("users/append");
305 if (fd == -1) {
306 if (errno != ENOENT) die_control();
307 }
308 else {
309 buffer_init(&in,buffer_unixread,fd,inbuf,sizeof(inbuf));
310 for (;;) {
311 if (getln(&in,&line,&match,'\n') == -1) die_read();
312 if (buffer_put(buffer_1,line.s,line.len) == -1) die_write();
313 if (!match) break;
314 }
315 }
316
317 if (buffer_puts(buffer_1,".\n") == -1) die_write();
318 if (buffer_flush(buffer_1) == -1) die_write();
319 _exit(0);
320}
char auto_break[]
char auto_qmail[]
char auto_usera[]
int main()
Definition: chkshsgr.c:6
void die_write()
Definition: columnt.c:17
void die_read()
Definition: columnt.c:16
int constmap_init(struct constmap *cm, char *s, int len, int flagcolon)
Definition: constmap.c:35
int control_readfile(stralloc *sa, char *fn, int flagme)
Definition: control.c:87
int stralloc_copys(stralloc *, char const *)
void _exit(int)
int match
Definition: matchup.c:196
stralloc incl
Definition: qmail-pw2u.c:89
stralloc sub
Definition: qmail-pw2u.c:204
stralloc mana
Definition: qmail-pw2u.c:91
struct constmap mapuser
Definition: qmail-pw2u.c:93
int homestrategy
Definition: qmail-pw2u.c:84
int flagnoupper
Definition: qmail-pw2u.c:83
stralloc home
Definition: qmail-pw2u.c:99
stralloc gidstr
Definition: qmail-pw2u.c:98
unsigned long uid
Definition: qmail-pw2u.c:100
stralloc user
Definition: qmail-pw2u.c:96
int fd
Definition: qmail-pw2u.c:238
int okexcl
Definition: qmail-pw2u.c:90
struct constmap mapmana
Definition: qmail-pw2u.c:91
struct constmap mapincl
Definition: qmail-pw2u.c:89
int okincl
Definition: qmail-pw2u.c:89
stralloc excl
Definition: qmail-pw2u.c:90
stralloc uugh
Definition: qmail-pw2u.c:95
stralloc line
Definition: qmail-pw2u.c:102
buffer in
Definition: qmail-pw2u.c:240
struct constmap mapexcl
Definition: qmail-pw2u.c:90
char * dashcolon
Definition: qmail-pw2u.c:81
int okmana
Definition: qmail-pw2u.c:91
int flagalias
Definition: qmail-pw2u.c:82
stralloc allusers
Definition: qmail-pw2u.c:93
stralloc uidstr
Definition: qmail-pw2u.c:97
char inbuf[BUFSIZE_LINE]
Definition: qmail-pw2u.c:239
stralloc fn
Definition: qmail-qmaint.c:551
void die_home()
Definition: qmail-qmqpc.c:33
#define BUFSIZE_LINE
Definition: qmail.h:8
void die_nomem(void)
Definition: qreceipt.c:23
void die_control(void)
Definition: qmail-qmqpc.c:31