X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Fexim.c;h=ad7635d98fe7fce0ae5bc0928a550cb3c374d7b2;hb=e29b631dc8f5694dd5964b40a85086015fdff054;hp=5a1437c3bfa8b71b80a07dc77461d8737d8d44bb;hpb=9bfb7e1bec2b3b6022c2e7b42df9ac606693dcfd;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/exim.c b/src/src/exim.c index 5a1437c3b..ad7635d98 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 - 2016 */ +/* 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,15 @@ 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_ARC + fprintf(f, " Experimental_ARC"); +#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 +949,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 +999,8 @@ DEBUG(D_any) do { gnu_get_libc_version()); #endif +show_db_version(f); + #ifdef SUPPORT_TLS tls_version_report(f); #endif @@ -1120,8 +1068,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 +1375,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 +1405,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 +2425,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) { @@ -3196,10 +3177,10 @@ for (i = 1; i < argc; i++) which sets the host protocol and host name */ if (*argrest == 0) - { - if (i+1 < argc) argrest = argv[++i]; else + if (i+1 < argc) + argrest = argv[++i]; + else { badarg = TRUE; break; } - } if (*argrest != 0) { @@ -3213,9 +3194,7 @@ for (i = 1; i < argc; i++) hn = Ustrchr(argrest, ':'); if (hn == NULL) - { received_protocol = argrest; - } else { int old_pool = store_pool; @@ -3795,12 +3774,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 - @@ -3820,9 +3796,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 "/" */ @@ -3878,7 +3851,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"); @@ -4598,30 +4571,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"); } @@ -4993,7 +4969,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); @@ -5013,6 +4989,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; @@ -5020,15 +5000,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 */ @@ -5036,25 +5009,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 */ @@ -5065,7 +5031,7 @@ if (expansion_test) deliver_datafile = -1; } - exim_exit(EXIT_SUCCESS, US"main"); + exim_exit(EXIT_SUCCESS, US"main: expansion test"); } @@ -5245,7 +5211,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", @@ -5828,50 +5794,5 @@ exim_exit(EXIT_SUCCESS, US"main"); /* Never returns */ return 0; /* To stop compiler warning */ } -/************************************************* -* read as much as requested * -*************************************************/ - -/* The syscall read(2) doesn't always returns as much as we want. For -several reasons it might get less. (Not talking about signals, as syscalls -are restartable). When reading from a network or pipe connection the sender -might send in smaller chunks, with delays between these chunks. The read(2) -may return such a chunk. - -The more the writer writes and the smaller the pipe between write and read is, -the more we get the chance of reading leass than requested. (See bug 2130) - -This function read(2)s until we got all the data we *requested*. - -Note: This function may block. Use it only if you're sure about the -amount of data you will get. - -Argument: - fd the file descriptor to read from - buffer pointer to a buffer of size len - len the requested(!) amount of bytes - -Returns: the amount of bytes read -*/ -ssize_t -readn(int fd, void *buffer, size_t len) -{ - void *next = buffer; - void *end = buffer + len; - - while (next < end) - { - ssize_t got = read(fd, next, end - next); - - /* I'm not sure if there are signals that can interrupt us, - for now I assume the worst */ - if (got == -1 && errno == EINTR) continue; - if (got <= 0) return next - buffer; - next += got; - } - - return len; -} - /* End of exim.c */