summaryrefslogtreecommitdiff
path: root/debian/sensible_mda/sensible-mda.c
diff options
context:
space:
mode:
Diffstat (limited to 'debian/sensible_mda/sensible-mda.c')
-rw-r--r--debian/sensible_mda/sensible-mda.c350
1 files changed, 350 insertions, 0 deletions
diff --git a/debian/sensible_mda/sensible-mda.c b/debian/sensible_mda/sensible-mda.c
new file mode 100644
index 0000000..4278f99
--- /dev/null
+++ b/debian/sensible_mda/sensible-mda.c
@@ -0,0 +1,350 @@
+/*
+ * $Sendmail: sensible-mda.c,v 8.14.3 2009-02-28 22:32:11 cowboy Exp $
+ *
+ * sensible-mda.c
+ * Copyright (c) 1998, Johnie Ingram.
+ * Copyright (c) 1998-2009 Richard Nelson <cowboy@debian.org>.
+ *
+ * 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 const char id[] = "@(#)$Id: sensible-mda.c,v 8.14.3 2009-02-28 22:32:11 cowboy Exp $";
+#endif /* ! lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sysexits.h>
+#include <string.h>
+#include <syslog.h>
+
+// TODO: declare -x TCPREMOTEIP="$3"
+
+# define min(a, b) ((a) < (b) ? (a) : (b))
+
+#ifndef DEBUG
+ #define DEBUG 0
+ #endif
+#ifndef TESTING
+ #define TESTING 0
+ #endif
+
+#define PROCMAIL "/etc/mail/smrsh/procmail"
+#define MAILDROP "/etc/mail/smrsh/maildrop"
+#define DELIVER "/etc/mail/smrsh/deliver"
+#define MAIL_LOCAL "/etc/mail/smrsh/mail.local"
+
+#define PROCMAILRCS "/etc/procmailrcs/"
+
+static void help(void);
+static int drop_privs(char *, uid_t, gid_t);
+static void show_privs(void);
+static unsigned char program[PATH_MAX];
+
+static uid_t RealUid, RunAsUid;
+static gid_t RealGid, RunAsGid;
+
+int
+main (int argc, char *argv[]) {
+
+ struct stat MDA_stat;
+ int done = 1;
+ struct passwd* passwd_entry;
+
+ char *str_pos;
+ int exec_rc = EX_OK;
+
+ #if DEBUG
+ int arg_index;
+ int str_len;
+ #endif
+
+ (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
+ 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);
+ };
+
+ /*----------------------------------------------------------------
+ * Determine to whom we are delivering mail to, and set that
+ * as our real, effective, and saved {u,g}ids
+ *----------------------------------------------------------------*/
+ RealUid = RunAsUid = geteuid();
+ RealGid = RunAsGid = getegid();
+ passwd_entry=getpwnam(argv[2]);
+ if (passwd_entry) {
+ RunAsUid = passwd_entry->pw_uid;
+ RunAsGid = passwd_entry->pw_gid;
+ }
+ else {
+ (void) syslog( LOG_ERR, "User(%s) does not exist!\n",
+ argv[2]);
+ (void) closelog();
+ return (EX_TEMPFAIL);
+ };
+
+ /*----------------------------------------------------------------
+ * 1st: try delivery via PROCMAIL (Keep SUID, works better that way)
+ *----------------------------------------------------------------*/
+ if (!stat(PROCMAIL, &MDA_stat)) {
+ done = 0;
+ #if DEBUG
+ (void) syslog( LOG_INFO, "MDA: %s -t -f %s"
+ " -a %s -d %s\n",
+ PROCMAIL, argv[1], argv[3], argv[2]);
+ #endif
+ #if ! TESTING
+ exec_rc = execl (PROCMAIL, PROCMAIL, "-t",
+ "-f", argv[1],
+ "-a", argv[3],
+ "-d", argv[2], NULL);
+ (void) syslog( LOG_ERR, "%s did not execute %i,%i\n",
+ PROCMAIL, exec_rc, errno);
+ (void) closelog();
+ return (EX_TEMPFAIL);
+ #endif
+ done = 1;
+ };
+
+ /*----------------------------------------------------------------
+ * 2nd: try delivery via MAILDROP
+ *----------------------------------------------------------------*/
+ if (done && !stat(MAILDROP, &MDA_stat)) {
+ done = 0;
+ #if DEBUG
+ (void) syslog( LOG_INFO, "MDA: %s -f %s -d %s %s\n",
+ MAILDROP, argv[1], argv[2], argv[3]);
+ #endif
+ if (drop_privs( argv[2], RunAsUid, RunAsGid )) {
+ (void) closelog();
+ return (EX_TEMPFAIL);
+ };
+ #if ! TESTING
+ exec_rc = execl (MAILDROP, MAILDROP,
+ "-f", argv[1], "-d", argv[2], argv[3], NULL);
+ (void) syslog( LOG_ERR, "%s did not execute %i,%i\n",
+ MAILDROP, exec_rc, errno);
+ (void) closelog();
+ return (EX_TEMPFAIL);
+ #endif
+ done = 1;
+ };
+
+ /*----------------------------------------------------------------
+ * 3rd: try delivery via DELIVER
+ *----------------------------------------------------------------*/
+ if (done && !stat(DELIVER, &MDA_stat)) {
+ done = 0;
+ #if DEBUG
+ (void) syslog( LOG_INFO, "MDA: %s -r %s %s\n",
+ DELIVER, argv[1], argv[2]);
+ #endif
+ if (drop_privs( argv[2], RunAsUid, RunAsGid )) {
+ (void) closelog();
+ return (EX_TEMPFAIL);
+ };
+ #if ! TESTING
+ exec_rc = execl (DELIVER, DELIVER,
+ "-r", argv[1], argv[2], NULL);
+ (void) syslog( LOG_ERR, "%s did not execute %i,%i\n",
+ DELIVER, exec_rc, errno);
+ (void) closelog();
+ return (EX_TEMPFAIL);
+ #endif
+ done = 1;
+ };
+
+ /*----------------------------------------------------------------
+ * 4th: try delivery via MAIL.LOCAL (Needs SUID because of LMTP)
+ *----------------------------------------------------------------*/
+ if (done && !stat(MAIL_LOCAL, &MDA_stat)) {
+ done = 0;
+ #if DEBUG
+ (void) syslog( LOG_INFO, "MDA: %s -f %s %s\n",
+ MAIL_LOCAL, argv[1], argv[2]);
+ #endif
+ #if ! TESTING
+ exec_rc = execl (MAIL_LOCAL, MAIL_LOCAL,
+ "-f", argv[1], argv[2], NULL);
+ (void) syslog( LOG_ERR, "%s did not execute %i,%i\n",
+ MAIL_LOCAL, exec_rc, errno);
+ (void) closelog();
+ return (EX_TEMPFAIL);
+ #endif
+ done = 1;
+ };
+
+ (void) syslog( LOG_ERR, "No MDA was found! Tried: "
+ "%s, %s, %s, and %s.\n",
+ PROCMAIL, MAILDROP, DELIVER, MAIL_LOCAL );
+
+ (void) closelog();
+ return (EX_TEMPFAIL);
+ };
+
+/*-------------------------------------------------------------------
+ * drop_privs...
+ *-------------------------------------------------------------------*/
+static int
+drop_privs(char * luser, uid_t new_uid, gid_t new_gid) {
+ gid_t emptygidset[1];
+ uid_t EffUid;
+ gid_t EffGid;
+ int rval;
+
+ rval = EX_OK;
+ EffUid = geteuid();
+ EffGid = getegid();
+
+ /* reset group permissions; these can be set later */
+ emptygidset[0] = (RunAsGid != 0) ? RunAsGid : EffGid;
+ if (setgroups(1, emptygidset) == -1 && EffUid == 0) {
+ (void) syslog( LOG_ERR, "drop_privs: setgroups(1, %d) failed\n",
+ (int) emptygidset[0]);
+ rval = EX_OSERR;
+ };
+
+ /* reset primary group id */
+ if ((RunAsGid != 0) && EffGid != RunAsGid && setgid(RunAsGid) < 0) {
+ (void) syslog( LOG_ERR, "drop_privs: setgid(%d) failed\n",
+ (int) RunAsGid);
+ rval = EX_OSERR;
+ };
+
+ /* reset primary user id */
+ if ((RunAsUid != 0) && EffUid != RunAsUid && setuid(RunAsUid) < 0) {
+ (void) syslog( LOG_ERR, "drop_privs: setuid(%d) failed\n",
+ (int) RunAsUid);
+ rval = EX_OSERR;
+ };
+
+ #if DEBUG
+ show_privs();
+ (void) syslog( LOG_INFO, "drop_privs: rval = %d\n", rval);
+ #endif
+
+ if (rval) {
+ (void) syslog( LOG_ERR,
+ "Can not setreuid to %d:%d for user(%s)!\n",
+ RunAsUid, RunAsGid, luser);
+ show_privs();
+ };
+
+ return rval;
+ };
+
+/*-------------------------------------------------------------------
+ * show_privs...
+ *-------------------------------------------------------------------*/
+static void
+show_privs(void) {
+
+ (void) syslog( LOG_INFO, "show_privs: RealUser = %d:%d\n",
+ (int) RealUid, (int) RealGid);
+ (void) syslog( LOG_INFO, "show_privs: "
+ "get[ug]id=%d:%d, gete[ug]id=%d:%d\n",
+ (int) getuid(), (int) getgid(),
+ (int) geteuid(), (int) getegid());
+ (void) syslog( LOG_INFO, "show_privs: RunAsUser = %d:%d\n",
+ (int) RunAsUid, (int) RunAsGid);
+ return;
+ };
+
+/*-------------------------------------------------------------------
+ * 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 <from:$g> <user:$u> [<detail:$h>]"
+ "[<client:${client_addr}>]\n"
+ "\nCalls:\n"
+ "\tprocmail:\t procmail -t"
+ " -f <from>"
+ " -a <detail> -d <to>\n"
+ "\tmaildrop:\t maildrop -f <from> -d <to> <detail>\n"
+ "\tdeliver:\t deliver -r <from> <to>\n"
+ "\tmail.local:\t mail.local -f <from> <to>\n"
+ "\n"
+ ,program, program, program
+ );
+ return;
+ };
+