2
* $Sendmail: sensible-mda.c,v 8.14.3 2009-03-01 10:48:34 cowboy Exp $
5
* Copyright (c) 1998, Johnie Ingram.
6
* Copyright (c) 1998-2009 Richard Nelson <cowboy@debian.org>.
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
static const char id[] = "@(#)$Id: sensible-mda.c,v 8.14.3 2009-03-01 10:48:34 cowboy Exp $";
32
#include <sys/types.h>
41
// TODO: declare -x TCPREMOTEIP="$3"
43
# define min(a, b) ((a) < (b) ? (a) : (b))
52
#define PROCMAIL "/etc/mail/smrsh/procmail"
53
#define MAILDROP "/etc/mail/smrsh/maildrop"
54
#define DELIVER "/etc/mail/smrsh/deliver"
55
#define MAIL_LOCAL "/etc/mail/smrsh/mail.local"
57
#define PROCMAILRCS "/etc/procmailrcs/"
59
static void help(void);
60
static int drop_privs(char *, uid_t, gid_t);
61
static void show_privs(void);
62
static unsigned char program[PATH_MAX];
64
static uid_t RealUid, RunAsUid;
65
static gid_t RealGid, RunAsGid;
68
main (int argc, char *argv[]) {
72
struct passwd* passwd_entry;
82
(void) openlog( "sensible-mda", LOG_PID+LOG_PERROR, LOG_MAIL );
84
/*----------------------------------------------------------------
86
*----------------------------------------------------------------*/
87
str_pos = strrchr(argv[0], '/');
92
(void) strncpy(program, str_pos,
93
min(strlen(str_pos), sizeof(program)-1));
94
program[sizeof(program)-1] = '\0';
98
for ( arg_index = 0; arg_index < argc; arg_index++ )
99
str_len += strlen( argv[arg_index] ) + 1;
100
str_pos = malloc( str_len + 1);
102
for ( arg_index = 0; arg_index < argc; arg_index++ ) {
103
(void) strcat( str_pos, argv[arg_index] );
104
(void) strcat( str_pos, " " );
106
(void) syslog( LOG_INFO, "Parms: %s\n", str_pos );
107
(void) free(str_pos);
110
/*----------------------------------------------------------------
111
* Parse input to determine to whom to speak and who we are...
112
* Must have at least three parameters unless first is ?,-?,/?.
113
*----------------------------------------------------------------*/
115
(strcmp(argv[1],"?") == 0 || strcmp(argv[1],"-?") == 0 ||
116
strcmp(argv[1],"/?") == 0 || strcmp(argv[1],"\\?") == 0 ||
117
strcmp(argv[1],"-h") == 0 || strcmp(argv[1],"--help") == 0)) {
118
(void) printf( "%s - Help\n", program );
124
(void) syslog( LOG_ERR, "%s - Required parameters elided.\n",
131
/*----------------------------------------------------------------
132
* Determine to whom we are delivering mail to, and set that
133
* as our real, effective, and saved {u,g}ids
134
*----------------------------------------------------------------*/
135
RealUid = RunAsUid = geteuid();
136
RealGid = RunAsGid = getegid();
137
passwd_entry=getpwnam(argv[2]);
139
RunAsUid = passwd_entry->pw_uid;
140
RunAsGid = passwd_entry->pw_gid;
143
(void) syslog( LOG_ERR, "User(%s) does not exist!\n",
146
return (EX_TEMPFAIL);
149
/*----------------------------------------------------------------
150
* 1st: try delivery via PROCMAIL (Keep SUID, works better that way)
151
*----------------------------------------------------------------*/
152
if (!stat(PROCMAIL, &MDA_stat)) {
155
(void) syslog( LOG_INFO, "MDA: %s -t -f %s"
157
PROCMAIL, argv[1], argv[3], argv[2]);
160
exec_rc = execl (PROCMAIL, PROCMAIL, "-t",
163
"-d", argv[2], NULL);
164
(void) syslog( LOG_ERR, "%s did not execute %i,%i\n",
165
PROCMAIL, exec_rc, errno);
167
return (EX_TEMPFAIL);
172
/*----------------------------------------------------------------
173
* 2nd: try delivery via MAILDROP
174
*----------------------------------------------------------------*/
175
if (done && !stat(MAILDROP, &MDA_stat)) {
178
(void) syslog( LOG_INFO, "MDA: %s -f %s -d %s %s\n",
179
MAILDROP, argv[1], argv[2], argv[3]);
181
if (drop_privs( argv[2], RunAsUid, RunAsGid )) {
183
return (EX_TEMPFAIL);
186
exec_rc = execl (MAILDROP, MAILDROP,
187
"-f", argv[1], "-d", argv[2], argv[3], NULL);
188
(void) syslog( LOG_ERR, "%s did not execute %i,%i\n",
189
MAILDROP, exec_rc, errno);
191
return (EX_TEMPFAIL);
196
/*----------------------------------------------------------------
197
* 3rd: try delivery via DELIVER
198
*----------------------------------------------------------------*/
199
if (done && !stat(DELIVER, &MDA_stat)) {
202
(void) syslog( LOG_INFO, "MDA: %s -r %s %s\n",
203
DELIVER, argv[1], argv[2]);
205
if (drop_privs( argv[2], RunAsUid, RunAsGid )) {
207
return (EX_TEMPFAIL);
210
exec_rc = execl (DELIVER, DELIVER,
211
"-r", argv[1], argv[2], NULL);
212
(void) syslog( LOG_ERR, "%s did not execute %i,%i\n",
213
DELIVER, exec_rc, errno);
215
return (EX_TEMPFAIL);
220
/*----------------------------------------------------------------
221
* 4th: try delivery via MAIL.LOCAL (Needs SUID because of LMTP)
222
*----------------------------------------------------------------*/
223
if (done && !stat(MAIL_LOCAL, &MDA_stat)) {
226
(void) syslog( LOG_INFO, "MDA: %s -f %s %s\n",
227
MAIL_LOCAL, argv[1], argv[2]);
230
exec_rc = execl (MAIL_LOCAL, MAIL_LOCAL,
231
"-f", argv[1], argv[2], NULL);
232
(void) syslog( LOG_ERR, "%s did not execute %i,%i\n",
233
MAIL_LOCAL, exec_rc, errno);
235
return (EX_TEMPFAIL);
240
(void) syslog( LOG_ERR, "No MDA was found! Tried: "
241
"%s, %s, %s, and %s.\n",
242
PROCMAIL, MAILDROP, DELIVER, MAIL_LOCAL );
245
return (EX_TEMPFAIL);
248
/*-------------------------------------------------------------------
250
*-------------------------------------------------------------------*/
252
drop_privs(char * luser, uid_t new_uid, gid_t new_gid) {
253
gid_t emptygidset[1];
262
/* reset group permissions; these can be set later */
263
emptygidset[0] = (RunAsGid != 0) ? RunAsGid : EffGid;
264
if (setgroups(1, emptygidset) == -1 && EffUid == 0) {
265
(void) syslog( LOG_ERR, "drop_privs: setgroups(1, %d) failed\n",
266
(int) emptygidset[0]);
270
/* reset primary group id */
271
if ((RunAsGid != 0) && EffGid != RunAsGid && setgid(RunAsGid) < 0) {
272
(void) syslog( LOG_ERR, "drop_privs: setgid(%d) failed\n",
277
/* reset primary user id */
278
if ((RunAsUid != 0) && EffUid != RunAsUid && setuid(RunAsUid) < 0) {
279
(void) syslog( LOG_ERR, "drop_privs: setuid(%d) failed\n",
286
(void) syslog( LOG_INFO, "drop_privs: rval = %d\n", rval);
290
(void) syslog( LOG_ERR,
291
"Can not setreuid to %d:%d for user(%s)!\n",
292
RunAsUid, RunAsGid, luser);
299
/*-------------------------------------------------------------------
301
*-------------------------------------------------------------------*/
305
(void) syslog( LOG_INFO, "show_privs: RealUser = %d:%d\n",
306
(int) RealUid, (int) RealGid);
307
(void) syslog( LOG_INFO, "show_privs: "
308
"get[ug]id=%d:%d, gete[ug]id=%d:%d\n",
309
(int) getuid(), (int) getgid(),
310
(int) geteuid(), (int) getegid());
311
(void) syslog( LOG_INFO, "show_privs: RunAsUser = %d:%d\n",
312
(int) RunAsUid, (int) RunAsGid);
316
/*-------------------------------------------------------------------
318
*-------------------------------------------------------------------*/
322
(void) printf("\n%s - Help information.\n\n"
324
"\tA general MTA->MDA wrapper to isolate the MTA from\n"
325
"\tthe vagaries of MDA installation and invocation.\n"
326
"\nSupported MTAs:\n"
328
"\nSupported MDAs:\n"
329
"\tprocmail, maildrop, deliver, mail.local\n"
333
"Go directly to jail, do not pass GO, "
334
"do not collect $200!\n"
336
"\t%s <from:$g> <user:$u> [<detail:$h>]"
337
"[<client:${client_addr}>]\n"
339
"\tprocmail:\t procmail -t"
341
" -a <detail> -d <to>\n"
342
"\tmaildrop:\t maildrop -f <from> -d <to> <detail>\n"
343
"\tdeliver:\t deliver -r <from> <to>\n"
344
"\tmail.local:\t mail.local -f <from> <to>\n"
346
,program, program, program