/* * sensible-mda.c * Copyright (c) 1998, Johnie Ingram. * Copyright (c) 1998-2001 Richard Nelson . * Time-stamp: <2000/08/28 12:00:00 cowboy> * * 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 of the License, 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., 675 Mass Ave, Cambridge, MA 02139, USA. * */ # ifndef lint static char id[] = "@(#)$Id: sensible-mda.c,v 03.00.01 2001/08/24 12:00:00 cowboy Exp $"; # endif /* ! lint */ #include #include #include #include #include #include #include #include #include // TODO: declare -x TCPREMOTEIP="$3" # define min(a, b) ((a) < (b) ? (a) : (b)) #define DEBUG 0 #define PROCMAIL "/usr/bin/procmail" #define MAILDROP "/usr/bin/maildrop" #define DELIVER "/usr/bin/deliver" #define MAIL_LOCAL "/usr/lib/sm.bin/mail.local" #define PROCMAILRCS "/etc/procmailrcs/" static void help(void); static unsigned char program[32]; static struct stat MDA_stat; static struct stat procmailrc_stat; static int done = 1; static struct passwd* passwd_entry; static uid_t euid; extern int errno; int main (int argc, char *argv[]) { char *procmailrc; char *str_pos; int exec_rc; (void) openlog( "sensible-mda", LOG_PID+LOG_PERROR, LOG_MAIL ); /*---------------------------------------------------------------- * Obtain program name *----------------------------------------------------------------*/ str_pos = strrchr(argv[0], '/'); if ( str_pos ) str_pos++; else str_pos = argv[0]; (void) strncpy(program, str_pos, min(strlen(str_pos), sizeof(program)-1)); program[sizeof(program)-1] = '\0'; #if DEBUG int arg_index; int str_len; str_len = 0; for ( arg_index = 0; arg_index < argc; arg_index++ ) str_len += strlen( argv[arg_index] ) + 1; str_pos = malloc( str_len + 1); str_pos[0] = '\0'; for ( arg_index = 0; arg_index < argc; arg_index++ ) { (void) strcat( str_pos, argv[arg_index] ); (void) strcat( str_pos, " " ); }; (void) syslog( LOG_INFO, "Parms: %s\n", str_pos ); (void) free(str_pos); #endif /*---------------------------------------------------------------- * Parse input to determine to whom to speak and who we are... * Must have at least three parameters unless first is ?,-?,/?. *----------------------------------------------------------------*/ if (argc >= 2 && (strcmp(argv[1],"?") == 0 || strcmp(argv[1],"-?") == 0 || strcmp(argv[1],"/?") == 0 || strcmp(argv[1],"\\?") == 0 || strcmp(argv[1],"-h") == 0 || strcmp(argv[1],"--help") == 0)) { (void) printf( "%s - Help\n", program ); help(); (void) closelog( ); return (EX_USAGE); }; if (argc < 3) { (void) syslog( LOG_ERR, "%s - Required parameters elided.\n", program ); help(); (void) closelog( ); return (EX_USAGE); }; euid = geteuid(); /*---------------------------------------------------------------- * 1st: try delivery via PROCMAIL *----------------------------------------------------------------*/ if (!lstat(PROCMAIL, &MDA_stat)) { if (MDA_stat.st_mode & S_ISUID) { procmailrc=malloc(strlen(PROCMAILRCS)+strlen(argv[2])+1); sprintf(procmailrc,"%s%s",PROCMAILRCS,argv[2]); passwd_entry=getpwnam(argv[2]); /* * If argv[2] is a valid user & * /etc/procmailrcs/argv[2] exists & is owned by argv[2] */ if (passwd_entry && !stat(procmailrc, &procmailrc_stat) && procmailrc_stat.st_uid==passwd_entry->pw_uid) { done = 0; (void) syslog( LOG_INFO, "MDA: %s\n", PROCMAIL ); exec_rc = execl (PROCMAIL, PROCMAIL, "-t", "-f", argv[1], "-m", procmailrc, "-a", argv[3], NULL); (void) syslog( LOG_INFO, "%s did not execute %i,%i\n", PROCMAIL, exec_rc, errno ); return (EX_TEMPFAIL); } else { done = 0; #if DEBUG (void) syslog( LOG_INFO, "MDA: %s\n", PROCMAIL ); #endif exec_rc = execl (PROCMAIL, PROCMAIL, "-t", "-f", argv[1], "-a", argv[3], "-d", argv[2], NULL); (void) syslog( LOG_INFO, "%s did not execute %i,%i\n", PROCMAIL, exec_rc, errno ); return (EX_TEMPFAIL); }; } else (void) syslog( LOG_INFO, "%s is not setuid!\n", PROCMAIL ); }; /*---------------------------------------------------------------- * 2nd: try delivery via MAILDROP *----------------------------------------------------------------*/ if (done && !lstat(MAILDROP, &MDA_stat)) { if ( (euid == 0) || (MDA_stat.st_mode & S_ISUID) ) { done = 0; #if DEBUG (void) syslog( LOG_INFO, "MDA: %s\n", MAILDROP ); #endif exec_rc = execl (MAILDROP, MAILDROP, "-f", argv[1], "-d", argv[2], NULL); (void) syslog( LOG_INFO, "%s did not execute %i,%i\n", MAILDROP, exec_rc, errno ); return (EX_TEMPFAIL); } else (void) syslog( LOG_INFO, "%s is not setuid!\n", MAILDROP ); }; /*---------------------------------------------------------------- * 3rd: try delivery via DELIVER *----------------------------------------------------------------*/ if (done && !lstat(DELIVER, &MDA_stat)) { if ( (euid == 0) || (MDA_stat.st_mode & S_ISUID) ) { done = 0; #if DEBUG (void) syslog( LOG_INFO, "MDA: %s\n", DELIVER ); #endif exec_rc = execl (DELIVER, DELIVER, "-r", argv[1], argv[2], NULL); (void) syslog( LOG_INFO, "%s did not execute %i,%i\n", DELIVER, exec_rc, errno ); return (EX_TEMPFAIL); } else (void) syslog( LOG_INFO, "%s is not setuid!\n", DELIVER ); }; /*---------------------------------------------------------------- * 4th: try delivery via MAIL.LOCAL *----------------------------------------------------------------*/ if (done && !lstat(MAIL_LOCAL, &MDA_stat)) { if ( (euid == 0) || (MDA_stat.st_mode & S_ISUID) ) { done = 0; #if DEBUG (void) syslog( LOG_INFO, "MDA: %s\n", MAIL_LOCAL ); #endif exec_rc = execl (MAIL_LOCAL, MAIL_LOCAL, "-f", argv[1], argv[2], NULL); (void) syslog( LOG_INFO, "%s did not execute %i,%i\n", MAIL_LOCAL, exec_rc, errno ); return (EX_TEMPFAIL); } else (void) syslog( LOG_INFO, "%s is not setuid!\n", MAIL_LOCAL ); }; (void) syslog( LOG_ERR, "No MDA was found (or was suid)! Tried: " "%s, %s, %s, and %s.\n", PROCMAIL, MAILDROP, DELIVER, MAIL_LOCAL ); (void) closelog( ); return (EX_TEMPFAIL); }; /*------------------------------------------------------------------- * Help... *-------------------------------------------------------------------*/ static void help(void) { (void) printf("\n%s - Help information.\n\n" "%s:\n" "\tA general MTA->MDA wrapper to isolate the MTA from\n" "\tthe vagaries of MDA installation and invocation.\n" "\nSupported MTAs:\n" "\tsendmail\n" "\nSupported MDAs:\n" "\tprocmail, maildrop, deliver, mail.local\n" "\nCalled by:\n" "\tSendmail\n" "\tYou - " "Go directly to jail, do not pass GO, " "do not collect $200!\n" "\nSyntax:\n" "\t%s []" "[]\n" "\nCalls:\n" "\tprocmail:\t procmail -t -f " "-a -d \n" "\tmaildrop:\t maildrop -f -d \n" "\tdeliver:\t deliver -r \n" "\tmail.local:\t mail.local -f \n" "\n" ,program, program, program ); return; };