X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/9242a7e8cfa94bbc9dd7eca6bd651b569b871c4e..dec766a1977250758eb7a3e127e079a9271afd89:/src/src/exim.c diff --git a/src/src/exim.c b/src/src/exim.c index 57b701612..9fceaf524 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2017 */ +/* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ @@ -543,7 +543,7 @@ close_unwanted(void) if (smtp_input) { #ifdef SUPPORT_TLS - tls_close(TRUE, FALSE); /* Shut down the TLS library */ + tls_close(TRUE, TLS_NO_SHUTDOWN); /* Shut down the TLS library */ #endif (void)close(fileno(smtp_in)); (void)close(fileno(smtp_out)); @@ -743,26 +743,26 @@ else * Show supported features * *************************************************/ -/* This function is called for -bV/--version and for -d to output the optional -features of the current Exim binary. - -Arguments: a FILE for printing -Returns: nothing -*/ - static void -show_whats_supported(FILE *f) +show_db_version(FILE * f) { - auth_info *authi; - #ifdef DB_VERSION_STRING -fprintf(f, "Berkeley DB: %s\n", DB_VERSION_STRING); +DEBUG(D_any) + { + fprintf(f, "Library version: BDB: Compile: %s\n", DB_VERSION_STRING); + fprintf(f, " Runtime: %s\n", + db_version(NULL, NULL, NULL)); + } +else + fprintf(f, "Berkeley DB: %s\n", DB_VERSION_STRING); + #elif defined(BTREEVERSION) && defined(HASHVERSION) #ifdef USE_DB fprintf(f, "Probably Berkeley DB version 1.8x (native mode)\n"); #else fprintf(f, "Probably Berkeley DB version 1.8x (compatibility mode)\n"); #endif + #elif defined(_DBM_RDONLY) || defined(dbm_dirfno) fprintf(f, "Probably ndbm\n"); #elif defined(USE_TDB) @@ -774,6 +774,22 @@ fprintf(f, "Using tdb\n"); fprintf(f, "Probably GDBM (compatibility mode)\n"); #endif #endif +} + + +/* This function is called for -bV/--version and for -d to output the optional +features of the current Exim binary. + +Arguments: a FILE for printing +Returns: nothing +*/ + +static void +show_whats_supported(FILE * f) +{ +auth_info * authi; + +DEBUG(D_any) {} else show_db_version(f); fprintf(f, "Support for:"); #ifdef SUPPORT_CRYPTEQ @@ -801,11 +817,11 @@ fprintf(f, "Support for:"); fprintf(f, " TCPwrappers"); #endif #ifdef SUPPORT_TLS - #ifdef USE_GNUTLS +# ifdef USE_GNUTLS fprintf(f, " GnuTLS"); - #else +# else fprintf(f, " OpenSSL"); - #endif +# endif #endif #ifdef SUPPORT_TRANSLATE_IP_ADDRESS fprintf(f, " translate_ip_address"); @@ -816,6 +832,9 @@ fprintf(f, "Support for:"); #ifdef WITH_CONTENT_SCAN fprintf(f, " Content_Scanning"); #endif +#ifdef SUPPORT_DANE + fprintf(f, " DANE"); +#endif #ifndef DISABLE_DKIM fprintf(f, " DKIM"); #endif @@ -840,6 +859,9 @@ fprintf(f, "Support for:"); #ifdef SUPPORT_SOCKS fprintf(f, " SOCKS"); #endif +#ifdef SUPPORT_SPF + fprintf(f, " SPF"); +#endif #ifdef TCP_FASTOPEN deliver_init(); if (tcp_fastopen_ok) fprintf(f, " TCP_Fast_Open"); @@ -850,18 +872,12 @@ fprintf(f, "Support for:"); #ifdef EXPERIMENTAL_QUEUEFILE fprintf(f, " Experimental_QUEUEFILE"); #endif -#ifdef EXPERIMENTAL_SPF - fprintf(f, " Experimental_SPF"); -#endif #ifdef EXPERIMENTAL_SRS fprintf(f, " Experimental_SRS"); #endif #ifdef EXPERIMENTAL_BRIGHTMAIL fprintf(f, " Experimental_Brightmail"); #endif -#ifdef EXPERIMENTAL_DANE - fprintf(f, " Experimental_DANE"); -#endif #ifdef EXPERIMENTAL_DCC fprintf(f, " Experimental_DCC"); #endif @@ -930,86 +946,13 @@ fprintf(f, "Lookups (built-in):"); #endif fprintf(f, "\n"); -fprintf(f, "Authenticators:"); -#ifdef AUTH_CRAM_MD5 - fprintf(f, " cram_md5"); -#endif -#ifdef AUTH_CYRUS_SASL - fprintf(f, " cyrus_sasl"); -#endif -#ifdef AUTH_DOVECOT - fprintf(f, " dovecot"); -#endif -#ifdef AUTH_GSASL - fprintf(f, " gsasl"); -#endif -#ifdef AUTH_HEIMDAL_GSSAPI - fprintf(f, " heimdal_gssapi"); -#endif -#ifdef AUTH_PLAINTEXT - fprintf(f, " plaintext"); -#endif -#ifdef AUTH_SPA - fprintf(f, " spa"); -#endif -#ifdef AUTH_TLS - fprintf(f, " tls"); -#endif -fprintf(f, "\n"); +auth_show_supported(f); +route_show_supported(f); +transport_show_supported(f); -fprintf(f, "Routers:"); -#ifdef ROUTER_ACCEPT - fprintf(f, " accept"); -#endif -#ifdef ROUTER_DNSLOOKUP - fprintf(f, " dnslookup"); -#endif -#ifdef ROUTER_IPLITERAL - fprintf(f, " ipliteral"); -#endif -#ifdef ROUTER_IPLOOKUP - fprintf(f, " iplookup"); -#endif -#ifdef ROUTER_MANUALROUTE - fprintf(f, " manualroute"); -#endif -#ifdef ROUTER_QUERYPROGRAM - fprintf(f, " queryprogram"); -#endif -#ifdef ROUTER_REDIRECT - fprintf(f, " redirect"); -#endif -fprintf(f, "\n"); - -fprintf(f, "Transports:"); -#ifdef TRANSPORT_APPENDFILE - fprintf(f, " appendfile"); - #ifdef SUPPORT_MAILDIR - fprintf(f, "/maildir"); - #endif - #ifdef SUPPORT_MAILSTORE - fprintf(f, "/mailstore"); - #endif - #ifdef SUPPORT_MBX - fprintf(f, "/mbx"); - #endif -#endif -#ifdef TRANSPORT_AUTOREPLY - fprintf(f, " autoreply"); -#endif -#ifdef TRANSPORT_LMTP - fprintf(f, " lmtp"); -#endif -#ifdef TRANSPORT_PIPE - fprintf(f, " pipe"); -#endif -#ifdef EXPERIMENTAL_QUEUEFILE - fprintf(f, " queuefile"); -#endif -#ifdef TRANSPORT_SMTP - fprintf(f, " smtp"); +#ifdef WITH_CONTENT_SCAN +malware_show_supported(f); #endif -fprintf(f, "\n"); if (fixed_never_users[0] > 0) { @@ -1053,6 +996,8 @@ DEBUG(D_any) do { gnu_get_libc_version()); #endif +show_db_version(f); + #ifdef SUPPORT_TLS tls_version_report(f); #endif @@ -1120,8 +1065,8 @@ switch(request) "If the string is not recognised, you'll get this help (on stderr).\n" "\n" " exim -bI:help this information\n" -" exim -bI:dscp dscp value keywords known\n" -" exim -bI:sieve list of supported sieve extensions, one per line.\n" +" exim -bI:dscp list of known dscp value keywords\n" +" exim -bI:sieve list of supported sieve extensions\n" ); return; case CMDINFO_SIEVE: @@ -1427,7 +1372,7 @@ whites[i] = NULL; /* The list of commandline macros should be very short. Accept the N*M complexity. */ -for (m = macros; m; m = m->next) if (m->command_line) +for (m = macros_user; m; m = m->next) if (m->command_line) { found = FALSE; for (w = whites; *w; ++w) @@ -1457,6 +1402,39 @@ return TRUE; } +/************************************************* +* Expansion testing * +*************************************************/ + +/* Expand and print one item, doing macro-processing. + +Arguments: + item line for expansion +*/ + +static void +expansion_test_line(uschar * line) +{ +int len; +BOOL dummy_macexp; + +Ustrncpy(big_buffer, line, big_buffer_size); +big_buffer[big_buffer_size-1] = '\0'; +len = Ustrlen(big_buffer); + +(void) macros_expand(0, &len, &dummy_macexp); + +if (isupper(big_buffer[0])) + { + if (macro_read_assignment(big_buffer)) + printf("Defined macro '%s'\n", mlast->name); + } +else + if ((line = expand_string(big_buffer))) printf("%s\n", CS line); + else printf("Failed: %s\n", expand_string_message); +} + + /************************************************* * Entry point and high-level code * *************************************************/ @@ -2444,14 +2422,14 @@ for (i = 1; i < argc; i++) while (isspace(*s)) s++; } - for (m = macros; m; m = m->next) + for (m = macros_user; m; m = m->next) if (Ustrcmp(m->name, name) == 0) { fprintf(stderr, "exim: duplicated -D in command line\n"); exit(EXIT_FAILURE); } - m = macro_create(string_copy(name), string_copy(s), TRUE); + m = macro_create(name, s, TRUE); if (clmacro_count >= MAX_CLMACROS) { @@ -3793,12 +3771,9 @@ NOTE: immediatly after opening the configuration file we change the working directory to "/"! Later we change to $spool_directory. We do it there, because during readconf_main() some expansion takes place already. */ -/* Store the initial cwd before we change directories */ -if ((initial_cwd = os_getcwd(NULL, 0)) == NULL) - { - perror("exim: can't get the current working directory"); - exit(EXIT_FAILURE); - } +/* Store the initial cwd before we change directories. Can be NULL if the +dir has already been unlinked. */ +initial_cwd = os_getcwd(NULL, 0); /* checking: -be[m] expansion test - @@ -3818,9 +3793,6 @@ defined) */ readconf_main(checking || list_options); -if (builtin_macros_create_trigger) DEBUG(D_any) - debug_printf("Builtin macros created (expensive) due to config line '%.*s'\n", - Ustrlen(builtin_macros_create_trigger)-1, builtin_macros_create_trigger); /* Now in directory "/" */ @@ -3876,7 +3848,7 @@ else } /* At this point, we know if the user is privileged and some command-line -options become possibly imperssible, depending upon the configuration file. */ +options become possibly impermissible, depending upon the configuration file. */ if (checking && commandline_checks_require_admin && !admin_user) { fprintf(stderr, "exim: those command-line flags are set to require admin\n"); @@ -4596,30 +4568,33 @@ if (test_retry_arg >= 0) if (list_options) { + BOOL fail = FALSE; set_process_info("listing variables"); - if (recipients_arg >= argc) readconf_print(US"all", NULL, flag_n); - else for (i = recipients_arg; i < argc; i++) + if (recipients_arg >= argc) + fail = !readconf_print(US"all", NULL, flag_n); + else for (i = recipients_arg; i < argc; i++) + { + if (i < argc - 1 && + (Ustrcmp(argv[i], "router") == 0 || + Ustrcmp(argv[i], "transport") == 0 || + Ustrcmp(argv[i], "authenticator") == 0 || + Ustrcmp(argv[i], "macro") == 0 || + Ustrcmp(argv[i], "environment") == 0)) { - if (i < argc - 1 && - (Ustrcmp(argv[i], "router") == 0 || - Ustrcmp(argv[i], "transport") == 0 || - Ustrcmp(argv[i], "authenticator") == 0 || - Ustrcmp(argv[i], "macro") == 0 || - Ustrcmp(argv[i], "environment") == 0)) - { - readconf_print(argv[i+1], argv[i], flag_n); - i++; - } - else readconf_print(argv[i], NULL, flag_n); + fail |= !readconf_print(argv[i+1], argv[i], flag_n); + i++; } - exim_exit(EXIT_SUCCESS, US"main"); + else + fail = !readconf_print(argv[i], NULL, flag_n); + } + exim_exit(fail ? EXIT_FAILURE : EXIT_SUCCESS, US"main"); } if (list_config) { set_process_info("listing config"); - readconf_print(US"config", NULL, flag_n); - exim_exit(EXIT_SUCCESS, US"main"); + exim_exit(readconf_print(US"config", NULL, flag_n) + ? EXIT_SUCCESS : EXIT_FAILURE, US"main"); } @@ -4991,7 +4966,7 @@ if (expansion_test) /* Read a test message from a file. We fudge it up to be on stdin, saving stdin itself for later reading of expansion strings. */ - else if (expansion_test_message != NULL) + else if (expansion_test_message) { int save_stdin = dup(0); int fd = Uopen(expansion_test_message, O_RDONLY, 0); @@ -5011,6 +4986,10 @@ if (expansion_test) clearerr(stdin); /* Required by Darwin */ } + /* Only admin users may see config-file macros this way */ + + if (!admin_user) macros_user = macros = mlast = NULL; + /* Allow $recipients for this testing */ enable_dollar_recipients = TRUE; @@ -5018,15 +4997,8 @@ if (expansion_test) /* Expand command line items */ if (recipients_arg < argc) - { while (recipients_arg < argc) - { - uschar *s = argv[recipients_arg++]; - uschar *ss = expand_string(s); - if (ss == NULL) printf ("Failed: %s\n", expand_string_message); - else printf("%s\n", CS ss); - } - } + expansion_test_line(argv[recipients_arg++]); /* Read stdin */ @@ -5034,25 +5006,18 @@ if (expansion_test) { char *(*fn_readline)(const char *) = NULL; void (*fn_addhist)(const char *) = NULL; + uschar * s; - #ifdef USE_READLINE +#ifdef USE_READLINE void *dlhandle = set_readline(&fn_readline, &fn_addhist); - #endif +#endif - for (;;) - { - uschar *ss; - uschar *source = get_stdinput(fn_readline, fn_addhist); - if (source == NULL) break; - ss = expand_string(source); - if (ss == NULL) - printf ("Failed: %s\n", expand_string_message); - else printf("%s\n", CS ss); - } + while (s = get_stdinput(fn_readline, fn_addhist)) + expansion_test_line(s); - #ifdef USE_READLINE - if (dlhandle != NULL) dlclose(dlhandle); - #endif +#ifdef USE_READLINE + if (dlhandle) dlclose(dlhandle); +#endif } /* The data file will be open after -Mset */ @@ -5063,7 +5028,7 @@ if (expansion_test) deliver_datafile = -1; } - exim_exit(EXIT_SUCCESS, US"main"); + exim_exit(EXIT_SUCCESS, US"main: expansion test"); } @@ -5243,7 +5208,7 @@ already been done (which it will have been for inetd). This caters for the case when it is forced by -oMa. However, we must flag that it isn't a socket, so that the test for IP options is skipped for -bs input. */ -if (sender_host_address != NULL && sender_fullhost == NULL) +if (sender_host_address && !sender_fullhost) { host_build_sender_fullhost(); set_process_info("handling incoming connection from %s via -oMa",