Lookups: ret=key option
[users/jgh/exim.git] / src / src / functions.h
index 57314a677fb486b5ef0bc0a3783de08f7b227752..0028deb0d6d2622aa0c8e88d463c6984e74df84d 100644 (file)
@@ -3,6 +3,7 @@
 *************************************************/
 
 /* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 
@@ -13,6 +14,7 @@ are in in fact in separate headers. */
 #ifndef _FUNCTIONS_H_
 #define _FUNCTIONS_H_
 
+#include <ctype.h>
 #include <sys/time.h>
 
 
@@ -118,7 +120,7 @@ extern int     auth_get_data(uschar **, const uschar *, int);
 extern int     auth_get_no64_data(uschar **, uschar *);
 extern int     auth_prompt(const uschar *);
 extern int     auth_read_input(const uschar *);
-extern void    auth_show_supported(FILE *);
+extern gstring * auth_show_supported(gstring *);
 extern uschar *auth_xtextencode(uschar *, int);
 extern int     auth_xtextdecode(uschar *, uschar **);
 
@@ -148,10 +150,17 @@ extern void    bits_clear(unsigned int *, size_t, int *);
 extern void    bits_set(unsigned int *, size_t, int *);
 
 extern void    cancel_cutthrough_connection(BOOL, const uschar *);
+extern gstring *cat_file(FILE *, gstring *, uschar *);
+extern gstring *cat_file_tls(void *, gstring *, uschar *);
 extern int     check_host(void *, const uschar *, const uschar **, uschar **);
 extern uschar **child_exec_exim(int, BOOL, int *, BOOL, int, ...);
+extern pid_t   child_open_exim_function(int *, const uschar *);
+extern pid_t   child_open_exim2_function(int *, uschar *, uschar *,
+                const uschar *);
+extern pid_t   child_open_function(uschar **, uschar **, int,
+                int *, int *, BOOL, const uschar *);
 extern pid_t   child_open_uid(const uschar **, const uschar **, int,
-                uid_t *, gid_t *, int *, int *, uschar *, BOOL);
+                uid_t *, gid_t *, int *, int *, uschar *, BOOL, const uschar *);
 extern BOOL    cleanup_environment(void);
 extern void    cutthrough_data_puts(uschar *, int);
 extern void    cutthrough_data_put_nl(void);
@@ -175,6 +184,8 @@ extern void    debug_printf_indent(const char *, ...) PRINTF_FUNCTION(1,2);
 extern void    debug_print_string(uschar *);
 extern void    debug_print_tree(tree_node *);
 extern void    debug_vprintf(int, const char *, va_list);
+extern void    debug_print_socket(int);
+
 extern void    decode_bits(unsigned int *, size_t, int *,
                   uschar *, bit_table *, int, uschar *, int);
 extern void    delete_pid_file(void);
@@ -222,10 +233,10 @@ extern void    msg_event_raise(const uschar *, const address_item *);
 
 extern int     exim_chown_failure(int, const uschar*, uid_t, gid_t);
 extern const uschar * exim_errstr(int);
-extern void    exim_exit(int, const uschar *) NORETURN;
+extern void    exim_exit(int) NORETURN;
 extern void    exim_nullstd(void);
 extern void    exim_setugid(uid_t, gid_t, BOOL, uschar *);
-extern void    exim_underbar_exit(int);
+extern void    exim_underbar_exit(int) NORETURN;
 extern void    exim_wait_tick(struct timeval *, int);
 extern int     exp_bool(address_item *addr,
   uschar *mtype, uschar *mname, unsigned dgb_opt, uschar *oname, BOOL bvalue,
@@ -234,6 +245,8 @@ extern BOOL    expand_check_condition(uschar *, uschar *, uschar *);
 extern uschar *expand_file_big_buffer(const uschar *);
 extern uschar *expand_string(uschar *);        /* public, cannot make const */
 extern const uschar *expand_cstring(const uschar *); /* ... so use this one */
+extern uschar *expand_getkeyed(const uschar *, const uschar *);
+
 extern uschar *expand_hide_passwords(uschar * );
 extern uschar *expand_string_copy(const uschar *);
 extern int_eximarith_t expand_string_integer(uschar *, BOOL);
@@ -287,9 +300,9 @@ extern void    ip_keepalive(int, const uschar *, BOOL);
 extern int     ip_recv(client_conn_ctx *, uschar *, int, time_t);
 extern int     ip_socket(int, int);
 
-extern int     ip_tcpsocket(const uschar *, uschar **, int);
+extern int     ip_tcpsocket(const uschar *, uschar **, int, host_item *);
 extern int     ip_unixsocket(const uschar *, uschar **);
-extern int     ip_streamsocket(const uschar *, uschar **, int);
+extern int     ip_streamsocket(const uschar *, uschar **, int, host_item *);
 
 extern int     ipv6_nmtoa(int *, uschar *);
 
@@ -306,7 +319,7 @@ extern void    mainlog_close(void);
 extern int     malware(const uschar *, int);
 extern int     malware_in_file(uschar *);
 extern void    malware_init(void);
-extern void    malware_show_supported(FILE *);
+extern gstring * malware_show_supported(gstring *);
 #endif
 extern int     match_address_list(const uschar *, BOOL, BOOL, const uschar **,
                  unsigned int *, int, int, const uschar **);
@@ -363,8 +376,12 @@ extern int     vaguely_random_number_fallback(int);
 
 extern BOOL    queue_action(uschar *, int, uschar **, int, int);
 extern void    queue_check_only(void);
+extern unsigned queue_count(void);
+extern unsigned queue_count_cached(void);
 extern void    queue_list(int, uschar **, int);
-extern void    queue_count(void);
+#ifdef EXPERIMENTAL_QUEUE_RAMP
+extern void    queue_notify_daemon(const uschar * hostname);
+#endif
 extern void    queue_run(uschar *, uschar *, BOOL);
 
 extern int     random_number(int);
@@ -417,8 +434,8 @@ extern uschar *rfc2047_decode2(uschar *, BOOL, uschar *, int, int *, int *,
                  uschar **);
 extern int     route_address(address_item *, address_item **, address_item **,
                  address_item **, address_item **, int);
-extern int     route_check_prefix(const uschar *, const uschar *);
-extern int     route_check_suffix(const uschar *, const uschar *);
+extern int     route_check_prefix(const uschar *, const uschar *, unsigned *);
+extern int     route_check_suffix(const uschar *, const uschar *, unsigned *);
 extern BOOL    route_findgroup(uschar *, gid_t *);
 extern BOOL    route_finduser(const uschar *, struct passwd **, uid_t *);
 extern BOOL    route_find_expanded_group(uschar *, uschar *, uschar *, gid_t *,
@@ -426,15 +443,15 @@ extern BOOL    route_find_expanded_group(uschar *, uschar *, uschar *, gid_t *,
 extern BOOL    route_find_expanded_user(uschar *, uschar *, uschar *,
                  struct passwd **, uid_t *, uschar **);
 extern void    route_init(void);
-extern void    route_show_supported(FILE *);
+extern gstring * route_show_supported(gstring *);
 extern void    route_tidyup(void);
 
-extern uschar *search_find(void *, uschar *, uschar *, int, const uschar *, int,
-                 int, int *);
+extern uschar *search_find(void *, const uschar *, uschar *, int,
+                const uschar *, int, int, int *, const uschar *);
 extern int     search_findtype(const uschar *, int);
 extern int     search_findtype_partial(const uschar *, int *, const uschar **, int *,
-                 int *);
-extern void   *search_open(uschar *, int, int, uid_t *, gid_t *);
+                 int *, const uschar **);
+extern void   *search_open(const uschar *, int, int, uid_t *, gid_t *);
 extern void    search_tidyup(void);
 extern void    set_process_info(const char *, ...) PRINTF_FUNCTION(1,2);
 extern void    sha1_end(hctx *, const uschar *, int, uschar *);
@@ -511,7 +528,6 @@ extern int     string_is_ip_address(const uschar *, int *);
 #ifdef SUPPORT_I18N
 extern BOOL    string_is_utf8(const uschar *);
 #endif
-extern uschar *string_nextinlist(const uschar **, int *, uschar *, int);
 extern const uschar *string_printing2(const uschar *, BOOL);
 extern uschar *string_split_message(uschar *);
 extern uschar *string_unprinting(uschar *);
@@ -539,6 +555,11 @@ extern gstring *string_vformat_trc(gstring *, const uschar *, unsigned,
 extern uschar *string_open_failed_trc(int, const uschar *, unsigned,
                        const char *, ...) PRINTF_FUNCTION(4,5);
 
+#define string_nextinlist(lp, sp, b, l) \
+       string_nextinlist_trc((lp), (sp), (b), (l), US __FUNCTION__, __LINE__)
+extern uschar *string_nextinlist_trc(const uschar **listptr, int *separator, uschar *buffer, int buflen,
+                       const uschar * func, int line);
+
 extern int     strcmpic(const uschar *, const uschar *);
 extern int     strncmpic(const uschar *, const uschar *, int);
 extern uschar *strstric(uschar *, uschar *, BOOL);
@@ -567,7 +588,7 @@ extern void    transport_write_reset(int);
 extern BOOL    transport_write_string(int, const char *, ...);
 extern BOOL    transport_headers_send(transport_ctx *,
                  BOOL (*)(transport_ctx *, uschar *, int));
-extern void    transport_show_supported(FILE *);
+extern gstring * transport_show_supported(gstring *);
 extern BOOL    transport_write_message(transport_ctx *, int);
 extern void    tree_add_duplicate(uschar *, address_item *);
 extern void    tree_add_nonrecipient(uschar *);
@@ -620,10 +641,7 @@ return FALSE;
 
 #else
 extern BOOL is_tainted_fn(const void *);
-extern void * tainted_base, * tainted_top;
-
-return f.taint_check_slow
-  ? is_tainted_fn(p) : p >= tainted_base && p < tainted_top;
+return is_tainted_fn(p);
 #endif
 }
 
@@ -660,6 +678,15 @@ return US strncpy(CS dst, CCS src, n);
 /*XXX will likely need unchecked copy also */
 
 
+/* Advance the string pointer given over any whitespace.
+Return the next char as there's enought places using it to be useful. */
+
+#define Uskip_whitespace(sp) skip_whitespace(CUSS sp)
+
+static inline uschar skip_whitespace(const uschar ** sp)
+{ while (isspace(**sp)) (*sp)++; return **sp; }
+
+
 /******************************************************************************/
 
 #if !defined(MACRO_PREDEF) && !defined(COMPILE_UTILITY)
@@ -705,28 +732,44 @@ return chown(CCS name, owner, group)
 *************************************************/
 
 /* This function assumes that memcpy() is faster than strcpy().
+The result is explicitly nul-terminated.
 */
 
 static inline uschar *
-string_copy_taint_trc(const uschar *s, BOOL tainted, const char * func, int line)
+string_copyn_taint_trc(const uschar * s, unsigned len,
+       BOOL tainted, const char * func, int line)
 {
-int len = Ustrlen(s) + 1;
-uschar *ss = store_get_3(len, tainted, func, line);
+uschar * ss = store_get_3(len + 1, tainted, func, line);
 memcpy(ss, s, len);
+ss[len] = '\0';
 return ss;
 }
 
-#define string_copy_taint(s, tainted) \
-       string_copy_taint_trc((s), tainted, __FUNCTION__, __LINE__)
+static inline uschar *
+string_copy_taint_trc(const uschar * s, BOOL tainted, const char * func, int line)
+{ return string_copyn_taint_trc(s, Ustrlen(s), tainted, func, line); }
 
+static inline uschar *
+string_copyn_trc(const uschar * s, unsigned len, const char * func, int line)
+{ return string_copyn_taint_trc(s, len, is_tainted(s), func, line); }
 static inline uschar *
 string_copy_trc(const uschar * s, const char * func, int line)
-{
-return string_copy_taint_trc((s), is_tainted(s), func, line);
-}
+{ return string_copy_taint_trc(s, is_tainted(s), func, line); }
+
+
+/* String-copy functions explicitly setting the taint status */
 
+#define string_copyn_taint(s, len, tainted) \
+       string_copyn_taint_trc((s), (len), (tainted), __FUNCTION__, __LINE__)
+#define string_copy_taint(s, tainted) \
+       string_copy_taint_trc((s), (tainted), __FUNCTION__, __LINE__)
+
+/* Simple string-copy functions maintaining the taint */
+
+#define string_copyn(s, len) \
+       string_copyn_taint_trc((s), (len), is_tainted(s), __FUNCTION__, __LINE__)
 #define string_copy(s) \
-       string_copy_trc((s), __FUNCTION__, __LINE__)
+       string_copy_taint_trc((s), is_tainted(s), __FUNCTION__, __LINE__)
 
 
 /*************************************************
@@ -750,31 +793,6 @@ return ss;
 
 
 
-/*************************************************
-*       Copy and save string, given length       *
-*************************************************/
-
-/* It is assumed the data contains no zeros. A zero is added
-onto the end.
-
-Arguments:
-  s         string to copy
-  n         number of characters
-
-Returns:    copy of string in new store
-
-This is an API for local_scan hence not static.
-*/
-
-static inline uschar *
-string_copyn(const uschar *s, int n)
-{
-uschar *ss = store_get(n + 1, is_tainted(s));
-Ustrncpy(ss, s, n);
-ss[n] = 0;
-return ss;
-}
-
 /*************************************************
 * Copy, lowercase, and save string, given length *
 *************************************************/
@@ -918,6 +936,18 @@ va_end(ap);
 return g;
 }
 
+
+/* Copy the content of a string to tainted memory */
+
+static inline void
+gstring_rebuffer(gstring * g)
+{
+uschar * s = store_get(g->size, TRUE);
+memcpy(s, g->s, g->ptr);
+g->s = s;
+}
+
+
 /******************************************************************************/
 
 #define store_get_dns_answer() store_get_dns_answer_trc(CUS __FUNCTION__, __LINE__)
@@ -1046,7 +1076,7 @@ static inline void
 testharness_pause_ms(int millisec)
 {
 #ifndef MEASURE_TIMING
-if (f.running_in_test_harness) millisleep(millisec);
+if (f.running_in_test_harness && f.testsuite_delays) millisleep(millisec);
 #endif
 }
 
@@ -1057,7 +1087,7 @@ static inline int
 exim_open2(const char *pathname, int flags)
 {
 if (!is_tainted(pathname)) return open(pathname, flags);
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'\n", pathname);
+log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
 errno = EACCES;
 return -1;
 }
@@ -1065,7 +1095,7 @@ static inline int
 exim_open(const char *pathname, int flags, mode_t mode)
 {
 if (!is_tainted(pathname)) return open(pathname, flags, mode);
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'\n", pathname);
+log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
 errno = EACCES;
 return -1;
 }
@@ -1073,7 +1103,7 @@ static inline int
 exim_openat(int dirfd, const char *pathname, int flags)
 {
 if (!is_tainted(pathname)) return openat(dirfd, pathname, flags);
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'\n", pathname);
+log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
 errno = EACCES;
 return -1;
 }
@@ -1081,7 +1111,7 @@ static inline int
 exim_openat4(int dirfd, const char *pathname, int flags, mode_t mode)
 {
 if (!is_tainted(pathname)) return openat(dirfd, pathname, flags, mode);
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'\n", pathname);
+log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
 errno = EACCES;
 return -1;
 }
@@ -1090,11 +1120,62 @@ static inline FILE *
 exim_fopen(const char *pathname, const char *mode)
 {
 if (!is_tainted(pathname)) return fopen(pathname, mode);
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'\n", pathname);
+log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
+errno = EACCES;
+return NULL;
+}
+
+static inline DIR *
+exim_opendir(const uschar * name)
+{
+if (!is_tainted(name)) return opendir(CCS name);
+log_write(0, LOG_MAIN|LOG_PANIC, "Tainted dirname '%s'", name);
 errno = EACCES;
 return NULL;
 }
 
+/******************************************************************************/
+# if !defined(COMPILE_UTILITY)
+/* Process manipulation */
+
+static inline pid_t
+exim_fork(const unsigned char * purpose)
+{
+pid_t pid;
+DEBUG(D_any) debug_printf("%s forking for %s\n", process_purpose, purpose);
+if ((pid = fork()) == 0)
+  {
+  process_purpose = purpose;
+  DEBUG(D_any) debug_printf("postfork: %s\n", purpose);
+  }
+else
+  {
+  testharness_pause_ms(100); /* let child work */
+  DEBUG(D_any) debug_printf("%s forked for %s: %d\n", process_purpose, purpose, (int)pid);
+  }
+return pid;
+}
+
+
+static inline pid_t
+child_open_exim(int * fdptr, const uschar * purpose)
+{ return child_open_exim_function(fdptr, purpose); }
+
+static inline pid_t
+child_open_exim2(int * fdptr, uschar * sender,
+  uschar * sender_auth, const uschar * purpose)
+{ return child_open_exim2_function(fdptr, sender, sender_auth, purpose); }
+
+static inline pid_t
+child_open(uschar **argv, uschar **envp, int newumask, int *infdptr,
+  int *outfdptr, BOOL make_leader, const uschar * purpose)
+{ return child_open_function(argv, envp, newumask, infdptr,
+  outfdptr, make_leader, purpose);
+}
+
+# endif        /* !COMPILE_UTILITY */
+
+/******************************************************************************/
 #endif /* !MACRO_PREDEF */
 
 #endif  /* _FUNCTIONS_H_ */