xref: /openbsd-src/usr.sbin/mailwrapper/mailwrapper.c (revision 3882aa9547ad88e16a33cceae7b0292cb2a4583c)
1*3882aa95Santon /*	$OpenBSD: mailwrapper.c,v 1.23 2017/06/14 16:32:11 anton Exp $	*/
2a53d1a28Sjakob /*	$NetBSD: mailwrapper.c,v 1.2 1999/02/20 22:10:07 thorpej Exp $	*/
3a53d1a28Sjakob 
4a53d1a28Sjakob /*
5a53d1a28Sjakob  * Copyright (c) 1998
6a53d1a28Sjakob  * 	Perry E. Metzger.  All rights reserved.
7a53d1a28Sjakob  *
8a53d1a28Sjakob  * Redistribution and use in source and binary forms, with or without
9a53d1a28Sjakob  * modification, are permitted provided that the following conditions
10a53d1a28Sjakob  * are met:
11a53d1a28Sjakob  * 1. Redistributions of source code must retain the above copyright
12a53d1a28Sjakob  *    notice, this list of conditions and the following disclaimer.
13a53d1a28Sjakob  * 2. Redistributions in binary form must reproduce the above copyright
14a53d1a28Sjakob  *    notice, this list of conditions and the following disclaimer in the
15a53d1a28Sjakob  *    documentation and/or other materials provided with the distribution.
16a53d1a28Sjakob  * 3. All advertising materials mentioning features or use of this software
17a53d1a28Sjakob  *    must display the following acknowledgment:
18a53d1a28Sjakob  *	This product includes software developed for the NetBSD Project
19a53d1a28Sjakob  *	by Perry E. Metzger.
20a53d1a28Sjakob  * 4. The name of the author may not be used to endorse or promote products
21a53d1a28Sjakob  *    derived from this software without specific prior written permission.
22a53d1a28Sjakob  *
23a53d1a28Sjakob  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24a53d1a28Sjakob  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25a53d1a28Sjakob  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26a53d1a28Sjakob  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27a53d1a28Sjakob  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28a53d1a28Sjakob  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29a53d1a28Sjakob  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30a53d1a28Sjakob  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31a53d1a28Sjakob  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32a53d1a28Sjakob  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33a53d1a28Sjakob  */
34a53d1a28Sjakob 
35a53d1a28Sjakob #include <err.h>
36a53d1a28Sjakob #include <stdio.h>
37a53d1a28Sjakob #include <string.h>
38a53d1a28Sjakob #include <stdlib.h>
3976d33112Sjakob #include <syslog.h>
40a53d1a28Sjakob #include <unistd.h>
41a53d1a28Sjakob #include <util.h>
42a53d1a28Sjakob 
43a53d1a28Sjakob #define _PATH_MAILERCONF	"/etc/mailer.conf"
4460e6d519Ssunil #define _PATH_DEFAULTMTA	"/usr/sbin/smtpctl"
45a53d1a28Sjakob 
46a53d1a28Sjakob struct arglist {
47a53d1a28Sjakob 	size_t argc, maxc;
48a53d1a28Sjakob 	char **argv;
49a53d1a28Sjakob };
50a53d1a28Sjakob 
51c72b5b24Smillert static void initarg(struct arglist *);
523a1ce664Sjung static void addarg(struct arglist *, const char *);
53a53d1a28Sjakob 
54a53d1a28Sjakob extern const char *__progname;	/* from crt0.o */
55a53d1a28Sjakob 
56a53d1a28Sjakob static void
initarg(struct arglist * al)5755ef04e3Sderaadt initarg(struct arglist *al)
58a53d1a28Sjakob {
59a53d1a28Sjakob 	al->argc = 0;
60a53d1a28Sjakob 	al->maxc = 10;
611ed98fdfSderaadt 	if ((al->argv = calloc(al->maxc, sizeof(char *))) == NULL)
620f09aad0Sderaadt 		err(1, "malloc");
63a53d1a28Sjakob }
64a53d1a28Sjakob 
65a53d1a28Sjakob static void
addarg(struct arglist * al,const char * arg)663a1ce664Sjung addarg(struct arglist *al, const char *arg)
67a53d1a28Sjakob {
68a53d1a28Sjakob 	if (al->argc == al->maxc) {
69a53d1a28Sjakob 		al->maxc <<= 1;
70779af70dSderaadt 		al->argv = reallocarray(al->argv, al->maxc, sizeof(char *));
719c4bd211Smillert 		if (al->argv == NULL)
720f09aad0Sderaadt 			err(1, "realloc");
73a53d1a28Sjakob 	}
743a1ce664Sjung 
75a53d1a28Sjakob 	al->argv[al->argc++] = (char *)arg;
76a53d1a28Sjakob }
77a53d1a28Sjakob 
78a53d1a28Sjakob int
main(int argc,char * argv[])79*3882aa95Santon main(int argc, char *argv[])
80a53d1a28Sjakob {
81a53d1a28Sjakob 	FILE *config;
82a53d1a28Sjakob 	char *line, *cp, *from, *to, *ap;
83366cf49cSmillert 	const char *progname;
84a53d1a28Sjakob 	size_t len, lineno = 0;
85a53d1a28Sjakob 	struct arglist al;
86a53d1a28Sjakob 
870b6ac1ffSderaadt 	if (pledge("stdio rpath exec", NULL) == -1)
880b6ac1ffSderaadt 		err(1, "pledge");
890b6ac1ffSderaadt 
90366cf49cSmillert 	/* change __progname to mailwrapper so we get sensible error messages */
91366cf49cSmillert 	progname = __progname;
92366cf49cSmillert 	__progname = "mailwrapper";
93366cf49cSmillert 
94a53d1a28Sjakob 	initarg(&al);
95a53d1a28Sjakob 	for (len = 0; len < argc; len++)
963a1ce664Sjung 		addarg(&al, argv[len]);
97a53d1a28Sjakob 
980b6ac1ffSderaadt 	config = fopen(_PATH_MAILERCONF, "r");
990b6ac1ffSderaadt 
1000b6ac1ffSderaadt 	if (pledge("stdio exec", NULL) == -1)
1010b6ac1ffSderaadt 		err(1, "pledge");
1020b6ac1ffSderaadt 
1030b6ac1ffSderaadt 	if (config == NULL) {
1043a1ce664Sjung 		addarg(&al, NULL);
105366cf49cSmillert 		openlog(__progname, LOG_PID, LOG_MAIL);
1060f09aad0Sderaadt 		syslog(LOG_INFO, "cannot open %s, using %s as default MTA",
10776d33112Sjakob 		    _PATH_MAILERCONF, _PATH_DEFAULTMTA);
10876d33112Sjakob 		closelog();
109*3882aa95Santon 		execv(_PATH_DEFAULTMTA, al.argv);
1100731caacSmillert 		err(1, "cannot exec %s", _PATH_DEFAULTMTA);
11176d33112Sjakob 		/*NOTREACHED*/
11276d33112Sjakob 	}
113a53d1a28Sjakob 
114a53d1a28Sjakob 	for (;;) {
115a53d1a28Sjakob 		if ((line = fparseln(config, &len, &lineno, NULL, 0)) == NULL) {
116a53d1a28Sjakob 			if (feof(config))
1170f09aad0Sderaadt 				errx(1, "no mapping in %s", _PATH_MAILERCONF);
1180f09aad0Sderaadt 			err(1, "fparseln");
119a53d1a28Sjakob 		}
120a53d1a28Sjakob 
121a53d1a28Sjakob #define	WS	" \t\n"
122a53d1a28Sjakob 		cp = line;
123a53d1a28Sjakob 
124a53d1a28Sjakob 		cp += strspn(cp, WS);
125a53d1a28Sjakob 		if (cp[0] == '\0') {
126a53d1a28Sjakob 			/* empty line */
127a53d1a28Sjakob 			free(line);
128a53d1a28Sjakob 			continue;
129a53d1a28Sjakob 		}
130a53d1a28Sjakob 
131bf3eb731Sotto 		if ((from = strsep(&cp, WS)) == NULL || cp == NULL)
132a53d1a28Sjakob 			goto parse_error;
133a53d1a28Sjakob 
134a53d1a28Sjakob 		cp += strspn(cp, WS);
135a53d1a28Sjakob 
136a53d1a28Sjakob 		if ((to = strsep(&cp, WS)) == NULL)
137a53d1a28Sjakob 			goto parse_error;
138a53d1a28Sjakob 
139366cf49cSmillert 		if (strcmp(from, progname) == 0) {
140a53d1a28Sjakob 			for (ap = strsep(&cp, WS); ap != NULL;
141a53d1a28Sjakob 			    ap = strsep(&cp, WS))
142a53d1a28Sjakob 				if (*ap)
1433a1ce664Sjung 					addarg(&al, ap);
144a53d1a28Sjakob 			break;
145a53d1a28Sjakob 		}
146a53d1a28Sjakob 
147a53d1a28Sjakob 		free(line);
148a53d1a28Sjakob 	}
149a53d1a28Sjakob 
150a53d1a28Sjakob 	(void)fclose(config);
151a53d1a28Sjakob 
1523a1ce664Sjung 	addarg(&al, NULL);
1534ddf7c6bSimp 
154*3882aa95Santon 	execv(to, al.argv);
1550731caacSmillert 	err(1, "cannot exec %s", to);
156a53d1a28Sjakob 	/*NOTREACHED*/
157a53d1a28Sjakob parse_error:
1580f09aad0Sderaadt 	errx(1, "parse error in %s at line %lu",
159a53d1a28Sjakob 	    _PATH_MAILERCONF, (u_long)lineno);
160a53d1a28Sjakob 	/*NOTREACHED*/
161a53d1a28Sjakob }
162