diff options
Diffstat (limited to 'src/cmd/upas/smtp')
-rw-r--r-- | src/cmd/upas/smtp/greylist.c | 3 | ||||
-rw-r--r-- | src/cmd/upas/smtp/mxdial.c | 173 | ||||
-rw-r--r-- | src/cmd/upas/smtp/rfc822.tab.h | 123 | ||||
-rw-r--r-- | src/cmd/upas/smtp/smtp.c | 89 | ||||
-rw-r--r-- | src/cmd/upas/smtp/smtpd.c | 28 |
5 files changed, 129 insertions, 287 deletions
diff --git a/src/cmd/upas/smtp/greylist.c b/src/cmd/upas/smtp/greylist.c index a3a3f4d4..1efd1457 100644 --- a/src/cmd/upas/smtp/greylist.c +++ b/src/cmd/upas/smtp/greylist.c @@ -241,7 +241,6 @@ isrcptrecent(char *rcpt) void vfysenderhostok(void) { - char *fqdn; int recent = 0; Link *l; @@ -258,7 +257,7 @@ vfysenderhostok(void) if (fd >= 0) { seek(fd, 0, 2); /* paranoia */ - fprint(fd, "# %s\n%s\n\n", fqdn, nci->rsys); + fprint(fd, "# unknown\n%s\n\n", nci->rsys); close(fd); } } else { diff --git a/src/cmd/upas/smtp/mxdial.c b/src/cmd/upas/smtp/mxdial.c index ae272c7d..31c6e5ba 100644 --- a/src/cmd/upas/smtp/mxdial.c +++ b/src/cmd/upas/smtp/mxdial.c @@ -22,7 +22,6 @@ Ndb *db; extern int debug; static int mxlookup(DS*, char*); -static int mxlookup1(DS*, char*); static int compar(const void*, const void*); static int callmx(DS*, char*, char*); static void expand_meta(DS *ds); @@ -113,83 +112,28 @@ callmx(DS *ds, char *dest, char *domain) } /* - * call the dns process and have it try to resolve the mx request - * - * this routine knows about the firewall and tries inside and outside - * dns's seperately. + * use dns to resolve the mx request */ static int mxlookup(DS *ds, char *domain) { - int n; - - /* just in case we find no domain name */ - strcpy(domain, ds->host); - - if(ds->netdir){ - n = mxlookup1(ds, domain); - } else { - ds->netdir = "/net"; - n = mxlookup1(ds, domain); - if(n == 0) { - ds->netdir = "/net.alt"; - n = mxlookup1(ds, domain); - } - } - - return n; -} - -static int -mxlookup1(DS *ds, char *domain) -{ - char buf[1024]; - char dnsname[Maxstring]; - char *fields[4]; - int i, n, fd, nmx; - - snprint(dnsname, sizeof dnsname, "%s/dns", ds->netdir); - - fd = open(dnsname, ORDWR); - if(fd < 0) - return 0; - + int i, n, nmx; + Ndbtuple *t, *tmx, *tpref, *tip; + + ds->netdir = "/net"; nmx = 0; - snprint(buf, sizeof(buf), "%s mx", ds->host); - if(debug) - fprint(2, "sending %s '%s'\n", dnsname, buf); - n = write(fd, buf, strlen(buf)); - if(n < 0){ - rerrstr(buf, sizeof buf); - if(debug) - fprint(2, "dns: %s\n", buf); - if(strstr(buf, "dns failure")){ - /* if dns fails for the mx lookup, we have to stop */ - close(fd); - return -1; + if((t = dnsquery(nil, ds->host, "mx")) != nil){ + for(tmx=t; (tmx=ndbfindattr(tmx->entry, nil, "mx")) != nil && nmx<Nmx; ){ + for(tpref=tmx->line; tpref != tmx; tpref=tmx->line){ + if(strcmp(tpref->attr, "pref") == 0){ + strncpy(mx[nmx].host, tmx->val, sizeof(mx[n].host)-1); + mx[nmx].pref = atoi(tpref->val); + nmx++; + break; + } + } } - } else { - /* - * get any mx entries - */ - seek(fd, 0, 0); - while(nmx < Nmx && (n = read(fd, buf, sizeof(buf)-1)) > 0){ - buf[n] = 0; - if(debug) - fprint(2, "dns mx: %s\n", buf); - n = getfields(buf, fields, 4, 1, " \t"); - if(n < 4) - continue; - - if(strchr(domain, '.') == 0) - strcpy(domain, fields[0]); - - strncpy(mx[nmx].host, fields[3], sizeof(mx[n].host)-1); - mx[nmx].pref = atoi(fields[2]); - nmx++; - } - if(debug) - fprint(2, "dns mx; got %d entries\n", nmx); + ndbfree(t); } /* @@ -210,20 +154,16 @@ mxlookup1(DS *ds, char *domain) * look up all ip addresses */ for(i = 0; i < nmx; i++){ - seek(fd, 0, 0); - snprint(buf, sizeof buf, "%s ip", mx[i].host); - mx[i].ip[0] = 0; - if(write(fd, buf, strlen(buf)) < 0) + if((t = dnsquery(nil, mx[i].host, "ip")) == nil) goto no; - seek(fd, 0, 0); - if((n = read(fd, buf, sizeof buf-1)) < 0) + if((tip = ndbfindattr(t, nil, "ip")) == nil){ + ndbfree(t); goto no; - buf[n] = 0; - if(getfields(buf, fields, 4, 1, " \t") < 3) - goto no; - strncpy(mx[i].ip, fields[2], sizeof(mx[i].ip)-1); + } + strncpy(mx[i].ip, tip->val, sizeof(mx[i].ip)-1); + ndbfree(t); continue; - + no: /* remove mx[i] and go around again */ nmx--; @@ -274,74 +214,17 @@ dial_string_parse(char *str, DS *ds) expand_meta(ds); } -#if 0 /* jpc */ -static void -expand_meta(DS *ds) -{ - char buf[128], cs[128], *net, *p; - int fd, n; - - net = ds->netdir; - if(!net) - net = "/net"; - - if(debug) - fprint(2, "expanding %s!%s\n", net, ds->host); - snprint(cs, sizeof(cs), "%s/cs", net); - if((fd = open(cs, ORDWR)) == -1){ - if(debug) - fprint(2, "open %s: %r\n", cs); - syslog(0, "smtp", "cannot open %s: %r", cs); - return; - } - - snprint(buf, sizeof(buf), "!ipinfo %s", ds->host+1); // +1 to skip $ - if(write(fd, buf, strlen(buf)) <= 0){ - if(debug) - fprint(2, "write %s: %r\n", cs); - syslog(0, "smtp", "%s to %s - write failed: %r", buf, cs); - close(fd); - return; - } - - seek(fd, 0, 0); - if((n = read(fd, ds->expand, sizeof(ds->expand)-1)) < 0){ - if(debug) - fprint(2, "read %s: %r\n", cs); - syslog(0, "smtp", "%s - read failed: %r", cs); - close(fd); - return; - } - close(fd); - - ds->expand[n] = 0; - if((p = strchr(ds->expand, '=')) == nil){ - if(debug) - fprint(2, "response %s: %s\n", cs, ds->expand); - syslog(0, "smtp", "%q from %s - bad response: %r", ds->expand, cs); - return; - } - ds->host = p+1; - - /* take only first one returned (quasi-bug) */ - if((p = strchr(ds->host, ' ')) != nil) - *p = 0; -} -#endif /* jpc */ - -/* XXX */ static void expand_meta(DS *ds) { - Ndb *db; + static Ndb *db; Ndbs s; char *sys, *smtpserver; + /* can't ask cs, so query database directly. */ sys = sysname(); - db = ndbopen(unsharp("#9/ndb/local")); - fprint(2,"%s",ds->host); + if(db == nil) + db = ndbopen(0); smtpserver = ndbgetvalue(db, &s, "sys", sys, "smtp", nil); - snprint(ds->host,128,"%s",smtpserver); - fprint(2," exanded to %s\n",ds->host); - + snprint(ds->host, 128, "%s", smtpserver); } diff --git a/src/cmd/upas/smtp/rfc822.tab.h b/src/cmd/upas/smtp/rfc822.tab.h index cddbbc0f..a31a0e67 100644 --- a/src/cmd/upas/smtp/rfc822.tab.h +++ b/src/cmd/upas/smtp/rfc822.tab.h @@ -1,98 +1,25 @@ -/* A Bison parser, made by GNU Bison 2.0. */ - -/* Skeleton parser for Yacc-like parsing with Bison, - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* As a special exception, when this file is copied by Bison into a - Bison output file, you may use that output file without restriction. - This special exception was added by the Free Software Foundation - in version 1.24 of Bison. */ - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - WORD = 258, - DATE = 259, - RESENT_DATE = 260, - RETURN_PATH = 261, - FROM = 262, - SENDER = 263, - REPLY_TO = 264, - RESENT_FROM = 265, - RESENT_SENDER = 266, - RESENT_REPLY_TO = 267, - SUBJECT = 268, - TO = 269, - CC = 270, - BCC = 271, - RESENT_TO = 272, - RESENT_CC = 273, - RESENT_BCC = 274, - REMOTE = 275, - PRECEDENCE = 276, - MIMEVERSION = 277, - CONTENTTYPE = 278, - MESSAGEID = 279, - RECEIVED = 280, - MAILER = 281, - BADTOKEN = 282 - }; -#endif -#define WORD 258 -#define DATE 259 -#define RESENT_DATE 260 -#define RETURN_PATH 261 -#define FROM 262 -#define SENDER 263 -#define REPLY_TO 264 -#define RESENT_FROM 265 -#define RESENT_SENDER 266 -#define RESENT_REPLY_TO 267 -#define SUBJECT 268 -#define TO 269 -#define CC 270 -#define BCC 271 -#define RESENT_TO 272 -#define RESENT_CC 273 -#define RESENT_BCC 274 -#define REMOTE 275 -#define PRECEDENCE 276 -#define MIMEVERSION 277 -#define CONTENTTYPE 278 -#define MESSAGEID 279 -#define RECEIVED 280 -#define MAILER 281 -#define BADTOKEN 282 - - - - -#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) -typedef int YYSTYPE; -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1 -#endif - -extern YYSTYPE yylval; - - - +#define WORD 57346 +#define DATE 57347 +#define RESENT_DATE 57348 +#define RETURN_PATH 57349 +#define FROM 57350 +#define SENDER 57351 +#define REPLY_TO 57352 +#define RESENT_FROM 57353 +#define RESENT_SENDER 57354 +#define RESENT_REPLY_TO 57355 +#define SUBJECT 57356 +#define TO 57357 +#define CC 57358 +#define BCC 57359 +#define RESENT_TO 57360 +#define RESENT_CC 57361 +#define RESENT_BCC 57362 +#define REMOTE 57363 +#define PRECEDENCE 57364 +#define MIMEVERSION 57365 +#define CONTENTTYPE 57366 +#define MESSAGEID 57367 +#define RECEIVED 57368 +#define MAILER 57369 +#define BADTOKEN 57370 diff --git a/src/cmd/upas/smtp/smtp.c b/src/cmd/upas/smtp/smtp.c index fb00cd5f..0661f4c6 100644 --- a/src/cmd/upas/smtp/smtp.c +++ b/src/cmd/upas/smtp/smtp.c @@ -5,6 +5,7 @@ #include <libsec.h> #include <auth.h> #include <ndb.h> +#include <thread.h> static char* connect(char*); static char* dotls(char*); @@ -59,7 +60,7 @@ void usage(void) { fprint(2, "usage: smtp [-adips] [-uuser] [-hhost] [.domain] net!host[!service] sender rcpt-list\n"); - exits(Giveup); + threadexitsall(Giveup); } int @@ -70,17 +71,16 @@ timeout(void *x, char *msg) if(strstr(msg, "alarm")){ fprint(2, "smtp timeout: connection to %s timed out\n", farend); if(quitting) - exits(quitrv); - exits(Retry); + threadexitsall(quitrv); + threadexitsall(Retry); } if(strstr(msg, "closed pipe")){ - /* call _exits() to prevent Bio from trying to flush closed pipe */ fprint(2, "smtp timeout: connection closed to %s\n", farend); if(quitting){ syslog(0, "smtp.fail", "closed pipe to %s", farend); - _exits(quitrv); + threadexitsall(quitrv); } - _exits(Retry); + threadexitsall(Retry); } return 0; } @@ -96,6 +96,14 @@ removenewline(char *p) p[n] = 0; } +int +exitcode(char *s) +{ + if(strstr(s, "Retry")) /* known to runq */ + return RetryCode; + return 1; +} + void threadmain(int argc, char **argv) { @@ -171,7 +179,7 @@ threadmain(int argc, char **argv) if(*argv == 0) usage(); addr = *argv++; argc--; - // expand $smtp if necessary XXX + // expand $smtp if necessary addr = expand_addr(addr); farend = addr; @@ -199,12 +207,12 @@ threadmain(int argc, char **argv) rv = data(from, &bfile); if(rv != 0) goto error; - exits(0); + threadexitsall(0); } /* mxdial uses its own timeout handler */ if((rv = connect(addr)) != 0) - exits(rv); + threadexitsall(rv); /* 10 minutes to get through the initial handshake */ atnotify(timeout, 1); @@ -238,7 +246,7 @@ threadmain(int argc, char **argv) if(ping){ quit(0); - exits(0); + threadexitsall(0); } rv = data(from, &bfile); @@ -246,7 +254,7 @@ threadmain(int argc, char **argv) goto error; quit(0); if(rcvrs == ok) - exits(0); + threadexitsall(0); /* * here when some but not all rcvrs failed @@ -258,7 +266,7 @@ threadmain(int argc, char **argv) fprint(2, " mail to %s failed: %s", argv[i], errs[i]); } } - exits(Giveup); + threadexitsall(Giveup); /* * here when all rcvrs failed @@ -271,7 +279,7 @@ error: fprint(2, "%s connect to %s:\n%s\n", thedate(), addr, s_to_c(reply)); if(!filter) quit(rv); - exits(rv); + threadexitsall(rv); } /* @@ -319,6 +327,8 @@ dotls(char *me) int fd; uchar hash[SHA1dlen]; + return Giveup; + c = mallocz(sizeof(*c), 1); /* Note: not freed on success */ if (c == nil) return Giveup; @@ -1097,27 +1107,44 @@ dBputc(int x) return Bputc(&bout, x); } -/* XXX */ char* -expand_addr(char* a) +expand_addr(char *addr) { + static char buf[256]; + char *p, *q, *name, *sys; + Ndbtuple *t; Ndb *db; - Ndbs s; - char *sys, *ret, *proto, *host; - - proto = strtok(a,"!"); - if ( strcmp(proto,"net") != 0 ) { - fprint(2,"unknown proto %s\n",proto); + + p = strchr(addr, '!'); + if(p){ + q = strchr(p+1, '!'); + name = p+1; + }else{ + name = addr; + q = nil; } - host = strtok(0,"!"); - if ( strcmp(host,"$smtp") == 0 ) { - sys = sysname(); - db = ndbopen(unsharp("#9/ndb/local")); - host = ndbgetvalue(db, &s, "sys", sys, "smtp", nil); - } - ret = malloc(strlen(proto)+strlen(host)+2); - sprint(ret,"%s!%s",proto,host); - - return ret; + if(name[0] != '$') + return addr; + name++; + if(q) + *q = 0; + + sys = sysname(); + db = ndbopen(0); + t = ndbipinfo(db, "sys", sys, &name, 1); + if(t == nil){ + ndbclose(db); + if(q) + *q = '!'; + return addr; + } + + *(name-1) = 0; + if(q) + *q = '!'; + else + q = ""; + snprint(buf, sizeof buf, "%s%s%s", addr, t->val, q); + return buf; } diff --git a/src/cmd/upas/smtp/smtpd.c b/src/cmd/upas/smtp/smtpd.c index 7b54b3cf..e59dbddd 100644 --- a/src/cmd/upas/smtp/smtpd.c +++ b/src/cmd/upas/smtp/smtpd.c @@ -7,6 +7,7 @@ #include <mp.h> #include <libsec.h> #include <auth.h> +#include <thread.h> #include "../smtp/rfc822.tab.h" #define DBGMX 1 @@ -84,11 +85,11 @@ s_error(char *f, char *status) else reply("452 out of memory %s\r\n", errbuf); syslog(0, "smtpd", "++Malloc failure %s [%s]", him, nci->rsys); - exits(status); + threadexitsall(status); } void -main(int argc, char **argv) +threadmain(int argc, char **argv) { char *p, buf[1024]; char *netdir; @@ -137,6 +138,8 @@ main(int argc, char **argv) passwordinclear = 1; break; case 'c': + fprint(2, "tls is not available\n"); + threadexitsall("no tls"); tlscert = ARGF(); break; case 't': @@ -145,7 +148,7 @@ main(int argc, char **argv) break; default: fprint(2, "usage: smtpd [-dfhrs] [-n net] [-c cert]\n"); - exits("usage"); + threadexitsall("usage"); }ARGEND; nci = getnetconninfo(netdir, 0); @@ -179,7 +182,7 @@ main(int argc, char **argv) atnotify(catchalarm, 1); alarm(45*60*1000); zzparse(); - exits(0); + threadexitsall(0); } void @@ -276,7 +279,7 @@ hello(String *himp, int extended) syslog(0, "smtpd", "Hung up on %s; claimed to be %s", nci->rsys, him); reply("554 Liar!\r\n"); - exits("client pretended to be us"); + threadexitsall("client pretended to be us"); return; } } @@ -533,7 +536,7 @@ quit(void) { reply("221 Successful termination\r\n"); close(0); - exits(0); + threadexitsall(0); } void @@ -1063,6 +1066,7 @@ sendermxcheck(void) char *who; int pid; Waitmsg *w; + static char *validate; who = s_to_c(senders.first->p); if(strcmp(who, "/dev/null") == 0){ @@ -1074,7 +1078,9 @@ sendermxcheck(void) return 0; } - if(access("/mail/lib/validatesender", AEXEC) < 0) + if(validate == nil) + validate = unsharp("#9/mail/lib/validatesender"); + if(access(validate, AEXEC) < 0) return 0; senddom = strdup(who); @@ -1095,9 +1101,9 @@ sendermxcheck(void) * Could add an option with the remote IP address * to allow validatesender to implement SPF eventually. */ - execl("/mail/lib/validatesender", "validatesender", + execl(validate, "validatesender", "-n", nci->root, senddom, user, nil); - _exits("exec validatesender: %r"); + threadexitsall("exec validatesender: %r"); default: break; } @@ -1265,7 +1271,7 @@ rejectcheck(void) if(rejectcount > MAXREJECTS){ syslog(0, "smtpd", "Rejected (%s/%s)", him, nci->rsys); reply("554 too many errors. transaction failed.\r\n"); - exits("errcount"); + threadexitsall("errcount"); } if(hardreject){ rejectcount++; @@ -1344,7 +1350,7 @@ starttls(void) /* force the client to hang up */ close(Bfildes(&bin)); /* probably fd 0 */ close(1); - exits("tls failed"); + threadexitsall("tls failed"); } Bterm(&bin); Binit(&bin, fd, OREAD); |