summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2013-02-05 23:48:16 +0100
committermanuel <manuel@mausz.at>2013-02-05 23:48:16 +0100
commitb0c5a1bf27516611d34b6b7d56a0376e3c64171b (patch)
tree775492f51e62ed7b0dfe1eba75bfd189950c470f
parente52f8862b7bd6519055296a9b757259c0fd358d7 (diff)
downloadqmail-b0c5a1bf27516611d34b6b7d56a0376e3c64171b.tar.gz
qmail-b0c5a1bf27516611d34b6b7d56a0376e3c64171b.tar.bz2
qmail-b0c5a1bf27516611d34b6b7d56a0376e3c64171b.zip
[PATCH] realrcptto
-rw-r--r--Makefile13
-rw-r--r--qmail-qmtpd.c17
-rw-r--r--qmail-smtpd.c27
-rw-r--r--realrcptto.c421
4 files changed, 475 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index 72ec51e..aef981f 100644
--- a/Makefile
+++ b/Makefile
@@ -1434,11 +1434,13 @@ sig.h substdio.h readwrite.h exit.h now.h datetime.h fmt.h env.h
1434 1434
1435qmail-qmtpd: \ 1435qmail-qmtpd: \
1436load qmail-qmtpd.o rcpthosts.o control.o constmap.o received.o \ 1436load qmail-qmtpd.o rcpthosts.o control.o constmap.o received.o \
1437date822fmt.o now.o qmail.o auto_qmail.o \ 1437date822fmt.o now.o qmail.o auto_qmail.o realrcptto.o slurpclose.o \
1438auto_break.o auto_usera.o \
1438cdb.a fd.a wait.a datetime.a open.a getln.a sig.a case.a env.a \ 1439cdb.a fd.a wait.a datetime.a open.a getln.a sig.a case.a env.a \
1439stralloc.a alloc.a substdio.a error.a str.a fs.a 1440stralloc.a alloc.a substdio.a error.a str.a fs.a
1440 ./load qmail-qmtpd rcpthosts.o control.o constmap.o received.o \ 1441 ./load qmail-qmtpd rcpthosts.o control.o constmap.o received.o \
1441 date822fmt.o now.o qmail.o auto_qmail.o \ 1442 date822fmt.o now.o qmail.o auto_qmail.o realrcptto.o slurpclose.o \
1443 auto_break.o auto_usera.o \
1442 cdb.a fd.a wait.a datetime.a open.a getln.a sig.a case.a env.a \ 1444 cdb.a fd.a wait.a datetime.a open.a getln.a sig.a case.a env.a \
1443 stralloc.a alloc.a substdio.a error.a str.a fs.a 1445 stralloc.a alloc.a substdio.a error.a str.a fs.a
1444 1446
@@ -1607,12 +1609,14 @@ qmail-smtpd: \
1607load qmail-smtpd.o rcpthosts.o qregex.o commands.o timeoutread.o \ 1609load qmail-smtpd.o rcpthosts.o qregex.o commands.o timeoutread.o \
1608timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \ 1610timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \
1609date822fmt.o now.o qmail.o auto_qmail.o base64.o qmail-spp.o dns.o \ 1611date822fmt.o now.o qmail.o auto_qmail.o base64.o qmail-spp.o dns.o \
1612realrcptto.o slurpclose.o auto_break.o auto_usera.o \
1610cdb.a fd.a wait.a datetime.a getln.a open.a sig.a case.a env.a \ 1613cdb.a fd.a wait.a datetime.a getln.a open.a sig.a case.a env.a \
1611stralloc.a alloc.a strerr.a substdio.a error.a str.a fs.a \ 1614stralloc.a alloc.a strerr.a substdio.a error.a str.a fs.a \
1612socket.lib dns.lib 1615socket.lib dns.lib
1613 ./load qmail-smtpd qregex.o rcpthosts.o commands.o timeoutread.o \ 1616 ./load qmail-smtpd qregex.o rcpthosts.o commands.o timeoutread.o \
1614 timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \ 1617 timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \
1615 date822fmt.o now.o qmail.o auto_qmail.o base64.o qmail-spp.o dns.o \ 1618 date822fmt.o now.o qmail.o auto_qmail.o base64.o qmail-spp.o dns.o \
1619 realrcptto.o slurpclose.o auto_break.o auto_usera.o \
1616 tls.o ssl_timeoutio.o ndelay.a -L/usr/local/ssl/lib -lssl -lcrypto \ 1620 tls.o ssl_timeoutio.o ndelay.a -L/usr/local/ssl/lib -lssl -lcrypto \
1617 cdb.a fd.a wait.a datetime.a getln.a open.a sig.a case.a env.a \ 1621 cdb.a fd.a wait.a datetime.a getln.a open.a sig.a case.a env.a \
1618 stralloc.a alloc.a strerr.a substdio.a error.a str.a fs.a \ 1622 stralloc.a alloc.a strerr.a substdio.a error.a str.a fs.a \
@@ -1764,6 +1768,11 @@ compile readsubdir.c readsubdir.h direntry.h fmt.h scan.h str.h \
1764auto_split.h 1768auto_split.h
1765 ./compile readsubdir.c 1769 ./compile readsubdir.c
1766 1770
1771realrcptto.o: \
1772compile realrcptto.c auto_break.h auto_usera.h byte.h case.h cdb.h \
1773constmap.h error.h fmt.h open.h str.h stralloc.h uint32.h
1774 ./compile realrcptto.c
1775
1767received.o: \ 1776received.o: \
1768compile received.c fmt.h qmail.h substdio.h now.h datetime.h \ 1777compile received.c fmt.h qmail.h substdio.h now.h datetime.h \
1769datetime.h date822fmt.h received.h 1778datetime.h date822fmt.h received.h
diff --git a/qmail-qmtpd.c b/qmail-qmtpd.c
index df911a6..d772206 100644
--- a/qmail-qmtpd.c
+++ b/qmail-qmtpd.c
@@ -14,6 +14,15 @@
14 14
15void badproto() { _exit(100); } 15void badproto() { _exit(100); }
16void resources() { _exit(111); } 16void resources() { _exit(111); }
17void die_nomem() { resources(); }
18void die_control() { resources(); }
19void die_cdb() { resources(); }
20void die_sys() { resources(); }
21
22extern void realrcptto_init();
23extern void realrcptto_start();
24extern int realrcptto();
25extern int realrcptto_deny();
17 26
18int safewrite(fd,buf,len) int fd; char *buf; int len; 27int safewrite(fd,buf,len) int fd; char *buf; int len;
19{ 28{
@@ -98,6 +107,8 @@ main()
98 if (rcpthosts_init() == -1) resources(); 107 if (rcpthosts_init() == -1) resources();
99 relayclient = env_get("RELAYCLIENT"); 108 relayclient = env_get("RELAYCLIENT");
100 relayclientlen = relayclient ? str_len(relayclient) : 0; 109 relayclientlen = relayclient ? str_len(relayclient) : 0;
110
111 realrcptto_init();
101 112
102 if (control_readint(&databytes,"control/databytes") == -1) resources(); 113 if (control_readint(&databytes,"control/databytes") == -1) resources();
103 x = env_get("DATABYTES"); 114 x = env_get("DATABYTES");
@@ -114,6 +125,7 @@ main()
114 if (!local) local = "unknown"; 125 if (!local) local = "unknown";
115 126
116 for (;;) { 127 for (;;) {
128 realrcptto_start();
117 if (!stralloc_copys(&failure,"")) resources(); 129 if (!stralloc_copys(&failure,"")) resources();
118 flagsenderok = 1; 130 flagsenderok = 1;
119 131
@@ -216,6 +228,10 @@ main()
216 case -1: resources(); 228 case -1: resources();
217 case 0: failure.s[failure.len - 1] = 'D'; 229 case 0: failure.s[failure.len - 1] = 'D';
218 } 230 }
231
232 if (!failure.s[failure.len - 1])
233 if (!realrcptto(buf,1))
234 failure.s[failure.len - 1] = 'D';
219 235
220 if (!failure.s[failure.len - 1]) { 236 if (!failure.s[failure.len - 1]) {
221 qmail_to(&qq,buf); 237 qmail_to(&qq,buf);
@@ -231,6 +247,7 @@ main()
231 result = qmail_close(&qq); 247 result = qmail_close(&qq);
232 if (!flagsenderok) result = "Dunacceptable sender (#5.1.7)"; 248 if (!flagsenderok) result = "Dunacceptable sender (#5.1.7)";
233 if (databytes) if (!bytestooverflow) result = "Dsorry, that message size exceeds my databytes limit (#5.3.4)"; 249 if (databytes) if (!bytestooverflow) result = "Dsorry, that message size exceeds my databytes limit (#5.3.4)";
250 if (!relayclient && realrcptto_deny()) result = "Dsorry, no mailbox here by that name. (#5.1.1)\r\n";
234 251
235 if (*result) 252 if (*result)
236 len = str_len(result); 253 len = str_len(result);
diff --git a/qmail-smtpd.c b/qmail-smtpd.c
index 33ca503..9fb495b 100644
--- a/qmail-smtpd.c
+++ b/qmail-smtpd.c
@@ -116,6 +116,18 @@ void die_ipme()
116 out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); 116 out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush();
117 eflush(); _exit(1); 117 eflush(); _exit(1);
118} 118}
119void die_cdb()
120{
121 enew(); eout("Unable to read cdb user database!\n");
122 out("421 unable to read cdb user database (#4.3.0)\r\n"); flush();
123 eflush(); _exit(1);
124}
125void die_sys()
126{
127 enew(); eout("Unable to read system user database!\n");
128 out("421 unable to read system user database (#4.3.0)\r\n"); flush();
129 eflush(); _exit(1);
130}
119void straynewline() 131void straynewline()
120{ 132{
121 enew(); eout("Stray newline from "); eout(remoteip); eout(".\n"); 133 enew(); eout("Stray newline from "); eout(remoteip); eout(".\n");
@@ -162,6 +174,13 @@ int err_input() { out("501 malformed auth input (#5.5.4)\r\n"); return -1; }
162int err_wantstarttls() { out("530 Must issue a STARTTLS command first (#5.7.0)\r\n"); return -1; }; 174int err_wantstarttls() { out("530 Must issue a STARTTLS command first (#5.7.0)\r\n"); return -1; };
163void err_authfail() { out("535 authentication failed (#5.7.1)\r\n"); } 175void err_authfail() { out("535 authentication failed (#5.7.1)\r\n"); }
164 176
177extern void realrcptto_init();
178extern void realrcptto_start();
179extern int realrcptto();
180extern int realrcptto_deny();
181
182int flagauth = 0;
183
165stralloc greeting = {0}; 184stralloc greeting = {0};
166 185
167void smtp_greet(code) char *code; 186void smtp_greet(code) char *code;
@@ -260,6 +279,7 @@ void setup()
260 if (fdmbrt == -1) if (errno != error_noent) die_control(); 279 if (fdmbrt == -1) if (errno != error_noent) die_control();
261 280
262 281
282 realrcptto_init();
263 283
264 if (control_readint(&databytes,"control/databytes") == -1) die_control(); 284 if (control_readint(&databytes,"control/databytes") == -1) die_control();
265 x = env_get("DATABYTES"); 285 x = env_get("DATABYTES");
@@ -604,6 +624,7 @@ void smtp_mail(arg) char *arg;
604 if (!stralloc_copys(&rcptto,"")) die_nomem(); 624 if (!stralloc_copys(&rcptto,"")) die_nomem();
605 if (!stralloc_copys(&mailfrom,addr.s)) die_nomem(); 625 if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();
606 if (!stralloc_0(&mailfrom)) die_nomem(); 626 if (!stralloc_0(&mailfrom)) die_nomem();
627 realrcptto_start();
607 recipcount = 0; 628 recipcount = 0;
608 out("250 ok\r\n"); 629 out("250 ok\r\n");
609} 630}
@@ -653,6 +674,10 @@ void smtp_rcpt(arg) char *arg; {
653 flagbrt = 1; 674 flagbrt = 1;
654 log_deny("BAD RCPT TO", mailfrom.s,addr.s); 675 log_deny("BAD RCPT TO", mailfrom.s,addr.s);
655 } 676 }
677 if (!flagauth && !relayclient && !realrcptto(addr.s,1)) {
678 out("554 sorry, no mailbox here by that name. (#5.1.1)\r\n");
679 return;
680 }
656 if (!(spp_val = spp_rcpt(allowed))) return; 681 if (!(spp_val = spp_rcpt(allowed))) return;
657 if (!relayclient && spp_val == 1) { 682 if (!relayclient && spp_val == 1) {
658 if (!allowed) { 683 if (!allowed) {
@@ -785,6 +810,7 @@ void smtp_data() {
785 if (mailfrom.len == 1 && recipcount > 1) { err_badbounce(); return; } 810 if (mailfrom.len == 1 && recipcount > 1) { err_badbounce(); return; }
786 if (flagbrt) { err_brt(); return; } 811 if (flagbrt) { err_brt(); return; }
787 if (!spp_data()) return; 812 if (!spp_data()) return;
813 if (!relayclient && realrcptto_deny()) { out("550 sorry, no mailbox here by that name. (#5.1.1)\r\n"); return; }
788 seenmail = 0; 814 seenmail = 0;
789 if (databytes) bytestooverflow = databytes + 1; 815 if (databytes) bytestooverflow = databytes + 1;
790 if (qmail_open(&qqt) == -1) { err_qqt(); return; } 816 if (qmail_open(&qqt) == -1) { err_qqt(); return; }
@@ -821,7 +847,6 @@ static stralloc chal = {0}; /* plain challenge */
821static stralloc slop = {0}; /* b64 challenge */ 847static stralloc slop = {0}; /* b64 challenge */
822#endif 848#endif
823 849
824int flagauth = 0;
825char **childargs; 850char **childargs;
826char ssauthbuf[512]; 851char ssauthbuf[512];
827substdio ssauth = SUBSTDIO_FDBUF(safewrite,3,ssauthbuf,sizeof(ssauthbuf)); 852substdio ssauth = SUBSTDIO_FDBUF(safewrite,3,ssauthbuf,sizeof(ssauthbuf));
diff --git a/realrcptto.c b/realrcptto.c
new file mode 100644
index 0000000..7ec331a
--- /dev/null
+++ b/realrcptto.c
@@ -0,0 +1,421 @@
1#include <sys/types.h>
2#include <sys/stat.h>
3#include <unistd.h>
4#include <pwd.h>
5#include "auto_break.h"
6#include "auto_usera.h"
7#include "byte.h"
8#include "case.h"
9#include "cdb.h"
10#include "constmap.h"
11#include "error.h"
12#include "fmt.h"
13#include "open.h"
14#include "str.h"
15#include "stralloc.h"
16#include "uint32.h"
17#include "substdio.h"
18#include "env.h"
19#include "slurpclose.h"
20
21extern void die_nomem();
22extern void die_control();
23extern void die_cdb();
24extern void die_sys();
25
26static stralloc envnoathost = {0};
27static stralloc percenthack = {0};
28static stralloc locals = {0};
29static stralloc vdoms = {0};
30static struct constmap mappercenthack;
31static struct constmap maplocals;
32static struct constmap mapvdoms;
33
34static char *dash;
35static char *extension;
36static char *local;
37static struct passwd *pw;
38
39static char errbuf[128];
40static struct substdio sserr = SUBSTDIO_FDBUF(write,2,errbuf,sizeof errbuf);
41
42static char pidbuf[64];
43static char remoteipbuf[64]=" ";
44
45static int flagdenyall;
46static int flagdenyany;
47
48void realrcptto_init()
49{
50 char *x;
51
52 if (control_rldef(&envnoathost,"control/envnoathost",1,"envnoathost") != 1)
53 die_control();
54
55 if (control_readfile(&locals,"control/locals",1) != 1) die_control();
56 if (!constmap_init(&maplocals,locals.s,locals.len,0)) die_nomem();
57 switch(control_readfile(&percenthack,"control/percenthack",0)) {
58 case -1: die_control();
59 case 0: if (!constmap_init(&mappercenthack,"",0,0)) die_nomem();
60 case 1:
61 if (!constmap_init(&mappercenthack,percenthack.s,percenthack.len,0))
62 die_nomem();
63 }
64 switch(control_readfile(&vdoms,"control/virtualdomains",0)) {
65 case -1: die_control();
66 case 0: if (!constmap_init(&mapvdoms,"",0,1)) die_nomem();
67 case 1: if (!constmap_init(&mapvdoms,vdoms.s,vdoms.len,1)) die_nomem();
68 }
69
70 str_copy(pidbuf + fmt_ulong(pidbuf,getpid())," ");
71 x=env_get("PROTO");
72 if (x) {
73 static char const remoteip[]="REMOTEIP";
74 unsigned int len = str_len(x);
75 if (len <= sizeof remoteipbuf - sizeof remoteip) {
76 byte_copy(remoteipbuf,len,x);
77 byte_copy(remoteipbuf + len,sizeof remoteip,remoteip);
78 x = env_get(remoteipbuf);
79 len = str_len(x);
80 if (len + 1 < sizeof remoteipbuf) {
81 byte_copy(remoteipbuf,len,x);
82 remoteipbuf[len]=' ';
83 remoteipbuf[len + 1]='\0';
84 }
85 }
86 }
87
88 x = env_get("QMAILRRTDENYALL");
89 flagdenyall = (x && x[0]=='1' && x[1]=='\0');
90}
91
92void realrcptto_start()
93{
94 flagdenyany = 0;
95}
96
97static int denyaddr(addr, depth)
98char *addr;
99int depth;
100{
101 if (depth == 1)
102 {
103 substdio_puts(&sserr,"realrcptto ");
104 substdio_puts(&sserr,pidbuf);
105 substdio_puts(&sserr,remoteipbuf);
106 substdio_puts(&sserr,addr);
107 substdio_puts(&sserr,"\n");
108 substdio_flush(&sserr);
109 flagdenyany = 1;
110 }
111 return flagdenyall;
112}
113
114static void stat_error(path,error)
115char* path;
116int error;
117{
118 substdio_puts(&sserr,"unable to stat ");
119 substdio_puts(&sserr,path);
120 substdio_puts(&sserr,": ");
121 substdio_puts(&sserr,error_str(error));
122 substdio_puts(&sserr,"\n");
123 substdio_flush(&sserr);
124}
125
126#define GETPW_USERLEN 32
127
128static int userext()
129{
130 char username[GETPW_USERLEN];
131 struct stat st;
132
133 extension = local + str_len(local);
134 for (;;) {
135 if (extension - local < sizeof(username))
136 if (!*extension || (*extension == *auto_break)) {
137 byte_copy(username,extension - local,local);
138 username[extension - local] = 0;
139 case_lowers(username);
140 errno = 0;
141 pw = getpwnam(username);
142 if (errno == error_txtbsy) die_sys();
143 if (pw)
144 if (pw->pw_uid)
145 if (stat(pw->pw_dir,&st) == 0) {
146 if (st.st_uid == pw->pw_uid) {
147 dash = "";
148 if (*extension) { ++extension; dash = "-"; }
149 return 1;
150 }
151 }
152 else
153 if (error_temp(errno)) die_sys();
154 }
155 if (extension == local) return 0;
156 --extension;
157 }
158}
159
160// max lookups
161#define MAXRECURSION 5
162
163static int handleqme(qme, depth)
164stralloc *qme;
165int depth;
166{
167 stralloc cmds = {0};
168 char *username = NULL;
169 int fd, i, j, k, count;
170
171 if (depth >= MAXRECURSION) return 0;
172 if (!stralloc_ready(&cmds,0)) die_nomem();
173 cmds.len = 0;
174
175 fd = open_read(qme->s);
176 if (fd == -1) return 0;
177 if (slurpclose(fd,&cmds,256) == -1) die_nomem();
178 if (!cmds.len || (cmds.s[cmds.len - 1] != '\n'))
179 if (!stralloc_cats(&cmds,"\n")) die_nomem();
180
181 i = count = 0;
182 for (j = 0;j < cmds.len;++j)
183 {
184 if (cmds.s[j] == '\n')
185 {
186 cmds.s[j] = 0;
187 k = j;
188 while ((k > i) && ((cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t')))
189 cmds.s[--k] = 0;
190 switch(cmds.s[i])
191 {
192 case 0:
193 case '#':
194 case '.':
195 case '/':
196 case '|':
197 case '+':
198 break;
199 case '&':
200 ++i;
201 default:
202 count++;
203 username = cmds.s + i;
204 break;
205 }
206 i = j + 1;
207 }
208 }
209
210 if (count == 1 && username)
211 realrcptto(username, ++depth);
212
213 return 1;
214}
215
216int realrcptto(addr, depth)
217char *addr;
218int depth;
219{
220 env_unset("DTUSER");
221 return realrcptto_ex(addr, depth);
222}
223
224int realrcptto_ex(addr, depth)
225char *addr;
226int depth;
227{
228 char *homedir, *username;
229 static stralloc localpart = {0};
230 static stralloc lower = {0};
231 static stralloc nughde = {0};
232 static stralloc wildchars = {0};
233 static stralloc safeext = {0};
234 static stralloc qme = {0};
235 unsigned int i,at;
236
237 /* Short circuit, or full logging? Short circuit. */
238 if (flagdenyall && flagdenyany) return 1;
239
240 /* qmail-send:rewrite */
241 if (!stralloc_copys(&localpart,addr)) die_nomem();
242 i = byte_rchr(localpart.s,localpart.len,'@');
243 if (i == localpart.len) {
244 if (!stralloc_cats(&localpart,"@")) die_nomem();
245 if (!stralloc_cat(&localpart,&envnoathost)) die_nomem();
246 }
247 while (constmap(&mappercenthack,localpart.s + i + 1,localpart.len - i - 1)) {
248 unsigned int j = byte_rchr(localpart.s,i,'%');
249 if (j == i) break;
250 localpart.len = i;
251 i = j;
252 localpart.s[i] = '@';
253 }
254 at = byte_rchr(localpart.s,localpart.len,'@');
255 if (constmap(&maplocals,localpart.s + at + 1,localpart.len - at - 1)) {
256 localpart.len = at;
257 localpart.s[at] = '\0';
258 } else {
259 unsigned int xlen,newlen;
260 char *x;
261 for (i = 0;;++i) {
262 if (i > localpart.len) return denyaddr(addr, depth);
263 if (!i || (i == at + 1) || (i == localpart.len) ||
264 ((i > at) && (localpart.s[i] == '.'))) {
265 x = constmap(&mapvdoms,localpart.s + i,localpart.len - i);
266 if (x && i == at + 1) {
267 // set QMAILQUEUE if catch-all
268 char *qmailqueue;
269 qmailqueue = env_get("QMAILQUEUE");
270 if (qmailqueue) {
271 if (!env_put("QMAILQUEUE=bin/qmail-queue")) die_nomem();
272 }
273 }
274 if (x) break;
275 }
276 }
277 if (!*x) return 1;
278 xlen = str_len(x) + 1; /* +1 for '-' */
279 newlen = xlen + at + 1; /* +1 for \0 */
280 if (xlen < 1 || newlen - 1 < xlen || newlen < 1 ||
281 !stralloc_ready(&localpart,newlen))
282 die_nomem();
283 localpart.s[newlen - 1] = '\0';
284 byte_copyr(localpart.s + xlen,at,localpart.s);
285 localpart.s[xlen - 1] = '-';
286 byte_copy(localpart.s,xlen - 1,x);
287 localpart.len = newlen;
288 }
289
290 /* qmail-lspawn:nughde_get */
291 {
292 int r,fd,flagwild;
293 if (!stralloc_copys(&lower,"!")) die_nomem();
294 if (!stralloc_cats(&lower,localpart.s)) die_nomem();
295 if (!stralloc_0(&lower)) die_nomem();
296 case_lowerb(lower.s,lower.len);
297 if (!stralloc_copys(&nughde,"")) die_nomem();
298 fd = open_read("users/cdb");
299 if (fd == -1) {
300 if (errno != error_noent) die_cdb();
301 } else {
302 uint32 dlen;
303 r = cdb_seek(fd,"",0,&dlen);
304 if (r != 1) die_cdb();
305 if (!stralloc_ready(&wildchars,(unsigned int) dlen)) die_nomem();
306 wildchars.len = dlen;
307 if (cdb_bread(fd,wildchars.s,wildchars.len) == -1) die_cdb();
308 i = lower.len;
309 flagwild = 0;
310 do { /* i > 0 */
311 if (!flagwild || (i == 1) ||
312 (byte_chr(wildchars.s,wildchars.len,lower.s[i - 1])
313 < wildchars.len)) {
314 r = cdb_seek(fd,lower.s,i,&dlen);
315 if (r == -1) die_cdb();
316 if (r == 1) {
317 char *x;
318 if (!stralloc_ready(&nughde,(unsigned int) dlen)) die_nomem();
319 nughde.len = dlen;
320 if (cdb_bread(fd,nughde.s,nughde.len) == -1) die_cdb();
321 if (flagwild)
322 if (!stralloc_cats(&nughde,localpart.s + i - 1)) die_nomem();
323 if (!stralloc_0(&nughde)) die_nomem();
324 close(fd);
325 x=nughde.s;
326 /* skip username */
327 username=x;
328 x += byte_chr(x,nughde.s + nughde.len - x,'\0');
329 if (x == nughde.s + nughde.len) return 1;
330 ++x;
331 /* skip uid */
332 x += byte_chr(x,nughde.s + nughde.len - x,'\0');
333 if (x == nughde.s + nughde.len) return 1;
334 ++x;
335 /* skip gid */
336 x += byte_chr(x,nughde.s + nughde.len - x,'\0');
337 if (x == nughde.s + nughde.len) return 1;
338 ++x;
339 /* skip homedir */
340 homedir=x;
341 x += byte_chr(x,nughde.s + nughde.len - x,'\0');
342 if (x == nughde.s + nughde.len) return 1;
343 ++x;
344 /* skip dash */
345 dash=x;
346 x += byte_chr(x,nughde.s + nughde.len - x,'\0');
347 if (x == nughde.s + nughde.len) return 1;
348 ++x;
349 extension=x;
350 goto got_nughde;
351 }
352 }
353 --i;
354 flagwild = 1;
355 } while (i);
356 close(fd);
357 }
358 }
359
360 /* qmail-getpw */
361 local = localpart.s;
362 if (!userext()) {
363 extension = local;
364 dash = "-";
365 pw = getpwnam(auto_usera);
366 }
367 if (!pw) return denyaddr(addr, depth);
368 if (!stralloc_copys(&nughde,pw->pw_dir)) die_nomem();
369 if (!stralloc_0(&nughde)) die_nomem();
370 homedir=nughde.s;
371 username=pw->pw_name;
372
373 got_nughde:
374
375 /* qmail-local:qmesearch */
376 //if (!*dash) return 1;
377 if (!*dash) { env_put2("DTUSER", username); return 1; }
378 if (!stralloc_copys(&safeext,extension)) die_nomem();
379 case_lowerb(safeext.s,safeext.len);
380 for (i = 0;i < safeext.len;++i)
381 {
382 if (safeext.s[i] == '.')
383 safeext.s[i] = ':';
384 }
385 {
386 struct stat st;
387 int i;
388 if (!stralloc_copys(&qme,homedir)) die_nomem();
389 if (!stralloc_cats(&qme,"/.qmail")) die_nomem();
390 if (!stralloc_cats(&qme,dash)) die_nomem();
391 if (!stralloc_cat(&qme,&safeext)) die_nomem();
392 if (!stralloc_0(&qme)) die_nomem();
393 //if (stat(qme.s,&st) == 0) return 1;
394 if (stat(qme.s,&st) == 0) { handleqme(&qme, depth); return 1; }
395 if (errno != error_noent) {
396 stat_error(qme.s,errno);
397 return 1;
398 }
399 for (i = safeext.len;i >= 0;--i)
400 if (!i || (safeext.s[i - 1] == '-')) {
401 if (!stralloc_copys(&qme,homedir)) die_nomem();
402 if (!stralloc_cats(&qme,"/.qmail")) die_nomem();
403 if (!stralloc_cats(&qme,dash)) die_nomem();
404 if (!stralloc_catb(&qme,safeext.s,i)) die_nomem();
405 if (!stralloc_cats(&qme,"default")) die_nomem();
406 if (!stralloc_0(&qme)) die_nomem();
407 //if (stat(qme.s,&st) == 0) return 1;
408 if (stat(qme.s,&st) == 0) { handleqme(&qme, depth); return 1; }
409 if (errno != error_noent) {
410 stat_error(qme.s,errno);
411 return 1;
412 }
413 }
414 return denyaddr(addr, depth);
415 }
416}
417
418int realrcptto_deny()
419{
420 return flagdenyall && flagdenyany;
421}