[dovecot-cvs] dovecot/src/lib env-util.c,1.2,1.3 failures.c,1.7,1.8 failures.h,1.2,1.3 lib.c,1.6,1.7 process-title.c,1.1,1.2 restrict-access.c,1.5,1.6 restrict-access.h,1.1.1.1,1.2

cras at procontrol.fi cras at procontrol.fi
Wed Dec 18 06:00:03 EET 2002


Update of /home/cvs/dovecot/src/lib
In directory danu:/tmp/cvs-serv2284/lib

Modified Files:
	env-util.c failures.c failures.h lib.c process-title.c 
	restrict-access.c restrict-access.h 
Log Message:
Drop root privileges earlier. Close syslog more later in imap-master when   
forking new processes, so that any errors get logged. Make sure that all   
errors show up in log files - use specific exit status codes if we can't
write to log file. Make sure imap and login processes always drop root
privileges even if master process didn't ask for it for some reason.
putenv() wasn't verified to succeed - luckily we never allowed large user
given data there.     



Index: env-util.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/env-util.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- env-util.c	26 Nov 2002 21:13:14 -0000	1.2
+++ env-util.c	18 Dec 2002 04:00:01 -0000	1.3
@@ -35,7 +35,8 @@
 	if (pool == NULL)
 		pool = pool_create("Environment", 1024, FALSE);
 
-	putenv(p_strdup(pool, env));
+	if (putenv(p_strdup(pool, env)) < 0)
+		i_fatal("Environment full, can't add: %s", env);
 }
 
 void env_clean(void)

Index: failures.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/failures.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- failures.c	1 Dec 2002 15:58:36 -0000	1.7
+++ failures.c	18 Dec 2002 04:00:01 -0000	1.8
@@ -35,7 +35,7 @@
 
 static void default_panic_handler(const char *format, va_list args)
 	__attr_noreturn__;
-static void default_fatal_handler(const char *format, va_list args)
+static void default_fatal_handler(int status, const char *format, va_list args)
 	__attr_noreturn__;
 
 static void default_error_handler(const char *format, va_list args);
@@ -43,7 +43,7 @@
 
 /* Initialize working defaults */
 static FailureFunc panic_handler __attr_noreturn__ = default_panic_handler;
-static FailureFunc fatal_handler __attr_noreturn__ = default_fatal_handler;
+static FatalFailureFunc fatal_handler __attr_noreturn__ = default_fatal_handler;
 static FailureFunc error_handler = default_error_handler;
 static FailureFunc warning_handler = default_warning_handler;
 
@@ -80,7 +80,7 @@
 	abort();
 }
 
-static void default_fatal_handler(const char *format, va_list args)
+static void default_fatal_handler(int status, const char *format, va_list args)
 {
 	write_prefix();
 
@@ -88,7 +88,10 @@
 	vfprintf(log_fd, printf_string_fix_format(format), args);
 	fputc('\n', log_fd);
 
-	exit(98);
+	if (fflush(log_fd) < 0 && status == FATAL_DEFAULT)
+		status = FATAL_LOGWRITE;
+
+	exit(status);
 }
 
 static void default_error_handler(const char *format, va_list args)
@@ -103,7 +106,8 @@
         fputc('\n', log_fd);
 	t_pop();
 
-	fflush(log_fd);
+	if (fflush(log_fd) < 0)
+		exit(FATAL_LOGWRITE);
 
 	errno = old_errno;
 }
@@ -120,7 +124,8 @@
 	fputc('\n', log_fd);
 	t_pop();
 
-	fflush(log_fd);
+	if (fflush(log_fd) < 0)
+		exit(FATAL_LOGWRITE);
 
 	errno = old_errno;
 }
@@ -139,7 +144,16 @@
 	va_list args;
 
 	va_start(args, format);
-	fatal_handler(format, args);
+	fatal_handler(FATAL_DEFAULT, format, args);
+	va_end(args);
+}
+
+void i_fatal_status(int status, const char *format, ...)
+{
+	va_list args;
+
+	va_start(args, format);
+	fatal_handler(status, format, args);
 	va_end(args);
 }
 
@@ -168,7 +182,7 @@
         panic_handler = func;
 }
 
-void i_set_fatal_handler(FailureFunc func __attr_noreturn__)
+void i_set_fatal_handler(FatalFailureFunc func __attr_noreturn__)
 {
 	if (func == NULL)
 		func = default_fatal_handler;
@@ -195,10 +209,10 @@
         abort();
 }
 
-void i_syslog_fatal_handler(const char *fmt, va_list args)
+void i_syslog_fatal_handler(int status, const char *fmt, va_list args)
 {
 	vsyslog(LOG_CRIT, fmt, args);
-	exit(98);
+	exit(status);
 }
 
 void i_syslog_error_handler(const char *fmt, va_list args)
@@ -211,28 +225,40 @@
 	vsyslog(LOG_WARNING, fmt, args);
 }
 
+void i_set_failure_syslog(const char *ident, int options, int facility)
+{
+	openlog(ident, options, facility);
+
+	i_set_panic_handler(i_syslog_panic_handler);
+	i_set_fatal_handler(i_syslog_fatal_handler);
+	i_set_error_handler(i_syslog_error_handler);
+	i_set_warning_handler(i_syslog_warning_handler);
+}
+
 void i_set_failure_file(const char *path, const char *prefix)
 {
 	if (log_fd != NULL && log_fd != stderr)
 		(void)fclose(log_fd);
 
-	log_fd = fopen(path, "a");
-	if (log_fd == NULL)
-		i_fatal("Can't open log file %s: %m", path);
-	fd_close_on_exec(fileno(log_fd), TRUE);
-
 	i_free(log_prefix);
 	log_prefix = i_strconcat(prefix, ": ", NULL);
+
+	if (path == NULL)
+		log_fd = stderr;
+	else {
+		log_fd = fopen(path, "a");
+		if (log_fd == NULL) {
+			i_fatal_status(FATAL_LOGOPEN,
+				       "Can't open log file %s: %m", path);
+		}
+		fd_close_on_exec(fileno(log_fd), TRUE);
+	}
 }
 
 void i_set_failure_timestamp_format(const char *fmt)
 {
 	i_free(log_stamp_format);
         log_stamp_format = i_strdup(fmt);
-}
-
-void failures_init(void)
-{
 }
 
 void failures_deinit(void)

Index: failures.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib/failures.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- failures.h	12 Sep 2002 23:09:45 -0000	1.2
+++ failures.h	18 Dec 2002 04:00:01 -0000	1.3
@@ -1,34 +1,51 @@
 #ifndef __FAILURES_H
 #define __FAILURES_H
 
+/* Default exit status codes that we could use. */
+typedef enum {
+	FATAL_LOGOPEN	= 80, /* Can't open log file */
+	FATAL_LOGWRITE  = 81, /* Can't write to log file */
+	FATAL_OUTOFMEM	= 82, /* Out of memory */
+	FATAL_EXEC	= 83, /* exec() failed */
+
+	FATAL_DEFAULT	= 89
+} FatalExitStatus;
+
 #define DEFAULT_FAILURE_STAMP_FORMAT "%b %d %H:%M:%S "
 
 typedef void (*FailureFunc) (const char *, va_list);
+typedef void (*FatalFailureFunc) (int status, const char *, va_list);
 
 void i_panic(const char *format, ...) __attr_format__(1, 2) __attr_noreturn__;
 void i_fatal(const char *format, ...) __attr_format__(1, 2) __attr_noreturn__;
 void i_error(const char *format, ...) __attr_format__(1, 2);
 void i_warning(const char *format, ...) __attr_format__(1, 2);
 
+void i_fatal_status(int status, const char *format, ...)
+	__attr_format__(2, 3) __attr_noreturn__;
+
 /* Change failure handlers. Make sure they don't modify errno. */
 void i_set_panic_handler(FailureFunc func __attr_noreturn__);
-void i_set_fatal_handler(FailureFunc func __attr_noreturn__);
+void i_set_fatal_handler(FatalFailureFunc func __attr_noreturn__);
 void i_set_error_handler(FailureFunc func);
 void i_set_warning_handler(FailureFunc func);
 
-/* send failures to syslog() */
+/* Send failures to syslog() */
 void i_syslog_panic_handler(const char *fmt, va_list args) __attr_noreturn__;
-void i_syslog_fatal_handler(const char *fmt, va_list args) __attr_noreturn__;
+void i_syslog_fatal_handler(int status, const char *fmt, va_list args)
+	__attr_noreturn__;
 void i_syslog_error_handler(const char *fmt, va_list args);
 void i_syslog_warning_handler(const char *fmt, va_list args);
 
-/* send failures to specified log file instead of stderr. */
+/* Open syslog and set failure handlers to use it. */
+void i_set_failure_syslog(const char *ident, int options, int facility);
+
+/* Send failures to specified log file instead of stderr. */
 void i_set_failure_file(const char *path, const char *prefix);
 
-/* prefix failures with a timestamp. fmt is in strftime() format. */
+/* Prefix failures with a timestamp. fmt is in strftime() format. */
 void i_set_failure_timestamp_format(const char *fmt);
 
-void failures_init(void);
 void failures_deinit(void);
 
 #endif

Index: lib.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/lib.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- lib.c	28 Oct 2002 04:18:26 -0000	1.6
+++ lib.c	18 Dec 2002 04:00:01 -0000	1.7
@@ -44,7 +44,6 @@
 	/* standard way to get rand() return different values. */
 	srand((unsigned int) time(NULL));
 
-	failures_init();
 	data_stack_init();
 	imem_init();
 }

Index: process-title.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/process-title.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- process-title.c	3 Dec 2002 00:13:17 -0000	1.1
+++ process-title.c	18 Dec 2002 04:00:01 -0000	1.2
@@ -48,12 +48,12 @@
 		;
 
 	if ((p = malloc((i + 1) * sizeof(char *))) == NULL)
-		i_fatal("malloc() failed: %m");
+		i_panic("malloc() failed: %m");
 	environ = p;
 
 	for (i = 0; envp[i] != NULL; i++) {
 		if ((environ[i] = malloc(strlen(envp[i]) + 1)) == NULL)
-			i_fatal("malloc() failed: %m");
+			i_panic("malloc() failed: %m");
 
 		strcpy(environ[i], envp[i]);
 	}

Index: restrict-access.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/restrict-access.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- restrict-access.c	18 Dec 2002 02:23:13 -0000	1.5
+++ restrict-access.c	18 Dec 2002 04:00:01 -0000	1.6
@@ -42,7 +42,7 @@
 	env_put(t_strdup_printf("RESTRICT_SETGID=%ld", (long) gid));
 }
 
-void restrict_access_by_env(void)
+void restrict_access_by_env(int disallow_root)
 {
 	const char *env;
 	gid_t gid;
@@ -89,9 +89,16 @@
 	if (uid != 0) {
 		if (setuid(uid) != 0)
 			i_fatal("setuid(%ld) failed: %m", (long) uid);
+	}
 
-		/* just extra verification */
+	/* verify that we actually dropped the privileges */
+	if (uid != 0 || disallow_root) {
 		if (setuid(0) == 0)
 			i_fatal("We couldn't drop root privileges");
+	}
+
+	if (gid != 0 || disallow_root) {
+		if (getgid() == 0 || getegid() == 0 || setgid(0) == 0)
+			i_fatal("We couldn't drop root group privileges");
 	}
 }

Index: restrict-access.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib/restrict-access.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- restrict-access.h	9 Aug 2002 09:15:50 -0000	1.1.1.1
+++ restrict-access.h	18 Dec 2002 04:00:01 -0000	1.2
@@ -6,7 +6,9 @@
 void restrict_access_set_env(const char *user, uid_t uid, gid_t gid,
 			     const char *chroot_dir);
 
-/* chroot, setuid() and setgid() based on environment variables */
-void restrict_access_by_env(void);
+/* chroot, setuid() and setgid() based on environment variables.
+   If disallow_roots is TRUE, we'll kill ourself if we didn't have the
+   environment settings and we have root uid or gid. */
+void restrict_access_by_env(int disallow_root);
 
 #endif




More information about the dovecot-cvs mailing list