X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/1670ef10063d7708eb736a482d1ad25b9c59521d..754a0503134b184183f64c04ed30a3524fc3860b:/src/src/exim.c diff --git a/src/src/exim.c b/src/src/exim.c index 67fbc5cf7..30974c9c6 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -360,7 +360,7 @@ Returns: nothing */ void -set_process_info(char *format, ...) +set_process_info(const char *format, ...) { int len; va_list ap; @@ -397,7 +397,7 @@ Returns: the fopened FILE or NULL */ FILE * -modefopen(uschar *filename, char *options, mode_t mode) +modefopen(const uschar *filename, const char *options, mode_t mode) { mode_t saved_umask = umask(0777); FILE *f = Ufopen(filename, options); @@ -570,17 +570,20 @@ if (euid == root_uid || euid != uid || egid != gid || igflag) DEBUG(D_uid) { - int group_count; + int group_count, save_errno; gid_t group_list[NGROUPS_MAX]; debug_printf("changed uid/gid: %s\n uid=%ld gid=%ld pid=%ld\n", msg, (long int)geteuid(), (long int)getegid(), (long int)getpid()); group_count = getgroups(NGROUPS_MAX, group_list); + save_errno = errno; debug_printf(" auxiliary group list:"); if (group_count > 0) { int i; for (i = 0; i < group_count; i++) debug_printf(" %d", (int)group_list[i]); } + else if (group_count < 0) + debug_printf(" ", strerror(save_errno)); else debug_printf(" "); debug_printf("\n"); } @@ -909,20 +912,31 @@ if (fixed_never_users[0] > 0) fprintf(f, "Size of off_t: " SIZE_T_FMT "\n", sizeof(off_t)); -/* This runtime check is to help diagnose library linkage mismatches which -result in segfaults and the like; as such, it's left until the end, -just in case. There will still be a "Configuration file is" line still to -come. */ -#ifdef SUPPORT_TLS -tls_version_report(f); -#endif - /* Everything else is details which are only worth reporting when debugging. Perhaps the tls_version_report should move into this too. */ DEBUG(D_any) do { int i; +/* clang defines __GNUC__ (at least, for me) so test for it first */ +#if defined(__clang__) + fprintf(f, "Compiler: CLang [%s]\n", __clang_version__); +#elif defined(__GNUC__) + fprintf(f, "Compiler: GCC [%s]\n", +# ifdef __VERSION__ + __VERSION__ +# else + "? unknown version ?" +# endif + ); +#else + fprintf(f, "Compiler: \n"); +#endif + +#ifdef SUPPORT_TLS + tls_version_report(f); +#endif + #ifdef AUTH_CYRUS_SASL auth_cyrus_sasl_version_report(f); #endif @@ -931,8 +945,13 @@ DEBUG(D_any) do { " Runtime: %s\n", PCRE_MAJOR, PCRE_MINOR, /* PRE_PRERELEASE is either defined and empty or a string. - * This should work: */ + * unless its an ancient version of PCRE in which case it + * is not defined */ +#ifdef PCRE_PRERELEASE PCRE_PRERELEASE "", +#else + "", +#endif pcre_version()); init_lookup_list(); @@ -942,6 +961,17 @@ DEBUG(D_any) do { lookup_list[i]->version_report(f); } +#ifdef WHITELIST_D_MACROS + fprintf(f, "WHITELIST_D_MACROS: \"%s\"\n", WHITELIST_D_MACROS); +#else + fprintf(f, "WHITELIST_D_MACROS unset\n"); +#endif +#ifdef TRUSTED_CONFIG_LIST + fprintf(f, "TRUSTED_CONFIG_LIST: \"%s\"\n", TRUSTED_CONFIG_LIST); +#else + fprintf(f, "TRUSTED_CONFIG_LIST unset\n"); +#endif + } while (0); } @@ -1019,8 +1049,8 @@ Returns: the dlopen handle or NULL on failure */ static void * -set_readline(char * (**fn_readline_ptr)(char *), - char * (**fn_addhist_ptr)(char *)) +set_readline(char * (**fn_readline_ptr)(const char *), + void (**fn_addhist_ptr)(const char *)) { void *dlhandle; void *dlhandle_curses = dlopen("libcurses.so", RTLD_GLOBAL|RTLD_LAZY); @@ -1030,8 +1060,12 @@ if (dlhandle_curses != NULL) dlclose(dlhandle_curses); if (dlhandle != NULL) { - *fn_readline_ptr = (char *(*)(char*))dlsym(dlhandle, "readline"); - *fn_addhist_ptr = (char *(*)(char*))dlsym(dlhandle, "add_history"); + /* Checked manual pages; at least in GNU Readline 6.1, the prototypes are: + * char * readline (const char *prompt); + * void add_history (const char *string); + */ + *fn_readline_ptr = (char *(*)(const char*))dlsym(dlhandle, "readline"); + *fn_addhist_ptr = (void(*)(const char*))dlsym(dlhandle, "add_history"); } else { @@ -1061,7 +1095,7 @@ Returns: pointer to dynamic memory, or NULL at end of file */ static uschar * -get_stdinput(char *(*fn_readline)(char *), char *(*fn_addhist)(char *)) +get_stdinput(char *(*fn_readline)(const char *), void(*fn_addhist)(const char *)) { int i; int size = 0; @@ -1265,7 +1299,7 @@ for (m = macros; m != NULL; m = m->next) return FALSE; } } -debug_printf("macros_trusted overriden to true by whitelisting\n"); +DEBUG(D_any) debug_printf("macros_trusted overriden to true by whitelisting\n"); return TRUE; #endif } @@ -3265,6 +3299,11 @@ till after reading the config, which might specify the exim gid. Therefore, save the group list here first. */ group_count = getgroups(NGROUPS_MAX, group_list); +if (group_count < 0) + { + fprintf(stderr, "exim: getgroups() failed: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } /* There is a fundamental difference in some BSD systems in the matter of groups. FreeBSD and BSDI are known to be different; NetBSD and OpenBSD are @@ -3327,9 +3366,13 @@ if (( /* EITHER */ and should be used for any logging information because attempts to write to the log will usually fail. To arrange this, we unset really_exim. However, if no stderr is available there is no point - we might as well have a go - at the log (if it fails, syslog will be written). */ + at the log (if it fails, syslog will be written). + + Note that if the invoker is Exim, the logs remain available. Messing with + this causes unlogged successful deliveries. */ - if (log_stderr != NULL) really_exim = FALSE; + if ((log_stderr != NULL) && (real_uid != exim_uid)) + really_exim = FALSE; } /* Privilege is to be retained for the moment. It may be dropped later, @@ -3885,14 +3928,14 @@ else no need to complain then. */ if (rv == -1) { - if (!unprivileged) + if (!(unprivileged || removed_privilege)) { fprintf(stderr, "exim: changing group failed: %s\n", strerror(errno)); exit(EXIT_FAILURE); } else - debug_printf("changing group to %ld failed: %s\n", + DEBUG(D_any) debug_printf("changing group to %ld failed: %s\n", (long int)exim_gid, strerror(errno)); } } @@ -4527,8 +4570,8 @@ if (expansion_test) else { - char *(*fn_readline)(char *) = NULL; - char *(*fn_addhist)(char *) = NULL; + char *(*fn_readline)(const char *) = NULL; + void (*fn_addhist)(const char *) = NULL; #ifdef USE_READLINE void *dlhandle = set_readline(&fn_readline, &fn_addhist);