X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/66581d1e830f4e68f2b074b8d79a80645c6a72ea..aa097c4c00f62487128d74f65c521f9e877b184f:/src/src/exim.c diff --git a/src/src/exim.c b/src/src/exim.c index 749868231..b3035ca7c 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -14,6 +14,8 @@ Also a few functions that don't naturally fit elsewhere. */ #include "exim.h" +extern void init_lookup_list(void); + /************************************************* @@ -776,53 +778,53 @@ fprintf(f, "Support for:"); #endif fprintf(f, "\n"); -fprintf(f, "Lookups:"); -#ifdef LOOKUP_LSEARCH +fprintf(f, "Lookups (built-in):"); +#if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2 fprintf(f, " lsearch wildlsearch nwildlsearch iplsearch"); #endif -#ifdef LOOKUP_CDB +#if defined(LOOKUP_CDB) && LOOKUP_CDB!=2 fprintf(f, " cdb"); #endif -#ifdef LOOKUP_DBM +#if defined(LOOKUP_DBM) && LOOKUP_DBM!=2 fprintf(f, " dbm dbmnz"); #endif -#ifdef LOOKUP_DNSDB +#if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2 fprintf(f, " dnsdb"); #endif -#ifdef LOOKUP_DSEARCH +#if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2 fprintf(f, " dsearch"); #endif -#ifdef LOOKUP_IBASE +#if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2 fprintf(f, " ibase"); #endif -#ifdef LOOKUP_LDAP +#if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2 fprintf(f, " ldap ldapdn ldapm"); #endif -#ifdef LOOKUP_MYSQL +#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2 fprintf(f, " mysql"); #endif -#ifdef LOOKUP_NIS +#if defined(LOOKUP_NIS) && LOOKUP_NIS!=2 fprintf(f, " nis nis0"); #endif -#ifdef LOOKUP_NISPLUS +#if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2 fprintf(f, " nisplus"); #endif -#ifdef LOOKUP_ORACLE +#if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2 fprintf(f, " oracle"); #endif -#ifdef LOOKUP_PASSWD +#if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2 fprintf(f, " passwd"); #endif -#ifdef LOOKUP_PGSQL +#if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2 fprintf(f, " pgsql"); #endif -#ifdef LOOKUP_SQLITE +#if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2 fprintf(f, " sqlite"); #endif -#ifdef LOOKUP_TESTDB +#if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2 fprintf(f, " testdb"); #endif -#ifdef LOOKUP_WHOSON +#if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2 fprintf(f, " whoson"); #endif fprintf(f, "\n"); @@ -914,6 +916,49 @@ 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; + +#ifdef AUTH_CYRUS_SASL + auth_cyrus_sasl_version_report(f); +#endif + + fprintf(f, "Library version: PCRE: Compile: %d.%d%s\n" + " Runtime: %s\n", + PCRE_MAJOR, PCRE_MINOR, + /* PRE_PRERELEASE is either defined and empty or a string. + * 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(); + for (i = 0; i < lookup_list_count; i++) + { + if (lookup_list[i]->version_report) + 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); } @@ -1271,7 +1316,7 @@ int arg_error_handling = error_handling; int filter_sfd = -1; int filter_ufd = -1; int group_count; -int i; +int i, rv; int list_queue_option = 0; int msg_action = 0; int msg_action_arg = -1; @@ -1610,8 +1655,20 @@ real_gid = getgid(); if (real_uid == root_uid) { - setgid(real_gid); - setuid(real_uid); + rv = setgid(real_gid); + if (rv) + { + fprintf(stderr, "exim: setgid(%ld) failed: %s\n", + (long int)real_gid, strerror(errno)); + exit(EXIT_FAILURE); + } + rv = setuid(real_uid); + if (rv) + { + fprintf(stderr, "exim: setuid(%ld) failed: %s\n", + (long int)real_uid, strerror(errno)); + exit(EXIT_FAILURE); + } } /* If neither the original real uid nor the original euid was root, Exim is @@ -1971,13 +2028,17 @@ for (i = 1; i < argc; i++) #endif if (real_uid != root_uid) { - #ifdef TRUSTED_CONFIG_PREFIX_LIST + #ifdef TRUSTED_CONFIG_LIST - if (Ustrstr(argrest, "/../")) + if (real_uid != exim_uid + #ifdef CONFIGURE_OWNER + && real_uid != config_uid + #endif + ) trusted_config = FALSE; else { - FILE *trust_list = Ufopen(TRUSTED_CONFIG_PREFIX_LIST, "rb"); + FILE *trust_list = Ufopen(TRUSTED_CONFIG_LIST, "rb"); if (trust_list) { struct stat statbuf; @@ -2003,8 +2064,8 @@ for (i = 1; i < argc; i++) { /* Well, the trust list at least is up to scratch... */ void *reset_point = store_get(0); - uschar *trusted_prefixes[32]; - int nr_prefixes = 0; + uschar *trusted_configs[32]; + int nr_configs = 0; int i = 0; while (Ufgets(big_buffer, big_buffer_size, trust_list)) @@ -2017,13 +2078,13 @@ for (i = 1; i < argc; i++) nl = Ustrchr(start, '\n'); if (nl) *nl = 0; - trusted_prefixes[nr_prefixes++] = string_copy(start); - if (nr_prefixes == 32) + trusted_configs[nr_configs++] = string_copy(start); + if (nr_configs == 32) break; } fclose(trust_list); - if (nr_prefixes) + if (nr_configs) { int sep = 0; uschar *list = argrest; @@ -2031,14 +2092,12 @@ for (i = 1; i < argc; i++) while (trusted_config && (filename = string_nextinlist(&list, &sep, big_buffer, big_buffer_size)) != NULL) { - for (i=0; i < nr_prefixes; i++) + for (i=0; i < nr_configs; i++) { - int len = Ustrlen(trusted_prefixes[i]); - if (Ustrlen(filename) >= len && - Ustrncmp(filename, trusted_prefixes[i], len) == 0) + if (Ustrcmp(filename, trusted_configs[i]) == 0) break; } - if (i == nr_prefixes) + if (i == nr_configs) { trusted_config = FALSE; break; @@ -3141,7 +3200,8 @@ if (debug_selector != 0) debug_printf("Exim version %s uid=%ld gid=%ld pid=%d D=%x\n", version_string, (long int)real_uid, (long int)real_gid, (int)getpid(), debug_selector); - show_whats_supported(stderr); + if (!version_printed) + show_whats_supported(stderr); } } @@ -3283,9 +3343,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). - if (log_stderr != NULL) really_exim = FALSE; + Note that if the invoker is Exim, the logs remain available. Messing with + this causes unlogged successful deliveries. */ + + if ((log_stderr != NULL) && (real_uid != exim_uid)) + really_exim = FALSE; } /* Privilege is to be retained for the moment. It may be dropped later, @@ -3483,7 +3547,7 @@ if (removed_privilege && (!trusted_config || macros != NULL) && else log_write(0, LOG_MAIN|LOG_PANIC, "exim user lost privilege for using %s option", - (int)exim_uid, trusted_config? "-D" : "-C"); + trusted_config? "-D" : "-C"); } /* Start up Perl interpreter if Perl support is configured and there is a @@ -3508,6 +3572,13 @@ if (opt_perl_at_start && opt_perl_startup != NULL) } #endif /* EXIM_PERL */ +/* Initialise lookup_list +If debugging, already called above via version reporting. +This does mean that debugging causes the list to be initialised while root. +This *should* be harmless -- all modules are loaded from a fixed dir and +it's code that would, if not a module, be part of Exim already. */ +init_lookup_list(); + /* Log the arguments of the call if the configuration file said so. This is a debugging feature for finding out what arguments certain MUAs actually use. Don't attempt it if logging is disabled, or if listing variables or if @@ -3823,7 +3894,28 @@ if (!unprivileged && /* originally had root AND */ /* When we are retaining a privileged uid, we still change to the exim gid. */ -else setgid(exim_gid); +else + { + int rv; + rv = setgid(exim_gid); + /* Impact of failure is that some stuff might end up with an incorrect group. + We track this for failures from root, since any attempt to change privilege + by root should succeed and failures should be examined. For non-root, + there's no security risk. For me, it's { exim -bV } on a just-built binary, + no need to complain then. */ + if (rv == -1) + { + if (!(unprivileged || removed_privilege)) + { + fprintf(stderr, + "exim: changing group failed: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + else + DEBUG(D_any) debug_printf("changing group to %ld failed: %s\n", + (long int)exim_gid, strerror(errno)); + } + } /* Handle a request to scan a file for malware */ if (malware_test_file)