X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=src%2Fsrc%2Ffunctions.h;h=df4b33606982b574322c3f5c9127ad3160ba2ddf;hb=75b6e26f5ee1d313ba0d5b835e287f06b9770559;hp=488e84c6cd04d6bdb16e5bee1a2fd6d323bb9180;hpb=d85cdeb5e554b59bf4c43c54461409c15c6ee9c5;p=exim.git diff --git a/src/src/functions.h b/src/src/functions.h index 488e84c6c..df4b33606 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -48,6 +48,7 @@ extern uschar * tls_cert_fprt_md5(void *); extern uschar * tls_cert_fprt_sha1(void *); extern uschar * tls_cert_fprt_sha256(void *); +extern void tls_clean_env(void); extern BOOL tls_client_start(client_conn_ctx *, smtp_connect_args *, void *, tls_support *, uschar **); @@ -136,6 +137,7 @@ extern gstring *authres_spf(gstring *); #endif extern uschar *b64encode(const uschar *, int); +extern uschar *b64encode_taint(const uschar *, int, BOOL); extern int b64decode(const uschar *, uschar **); extern int bdat_getc(unsigned); extern uschar *bdat_getbuf(unsigned *); @@ -175,6 +177,7 @@ extern void debug_print_tree(tree_node *); extern void debug_vprintf(int, const char *, va_list); extern void decode_bits(unsigned int *, size_t, int *, uschar *, bit_table *, int, uschar *, int); +extern void delete_pid_file(void); extern address_item *deliver_make_addr(uschar *, BOOL); extern void delivery_log(int, address_item *, int, uschar *); extern int deliver_message(uschar *, BOOL, BOOL); @@ -186,6 +189,7 @@ extern void deliver_succeeded(address_item *); extern uschar *deliver_get_sender_address (uschar *id); extern void delivery_re_exec(int); +extern void die_tainted(const uschar *, const uschar *, int); extern BOOL directory_make(const uschar *, const uschar *, int, BOOL); #ifndef DISABLE_DKIM extern uschar *dkim_exim_query_dns_txt(const uschar *); @@ -196,8 +200,8 @@ extern BOOL dkim_transport_write_message(transport_ctx *, #endif extern dns_address *dns_address_from_rr(dns_answer *, dns_record *); extern int dns_basic_lookup(dns_answer *, const uschar *, int); -extern void dns_build_reverse(const uschar *, uschar *); -extern time_t dns_expire_from_soa(dns_answer *); +extern uschar *dns_build_reverse(const uschar *); +extern time_t dns_expire_from_soa(dns_answer *, int); extern void dns_init(BOOL, BOOL, BOOL); extern BOOL dns_is_aa(const dns_answer *); extern BOOL dns_is_secure(const dns_answer *); @@ -283,9 +287,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 *); @@ -359,8 +363,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); @@ -413,8 +421,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 *, @@ -539,6 +547,7 @@ extern int strcmpic(const uschar *, const uschar *); extern int strncmpic(const uschar *, const uschar *, int); extern uschar *strstric(uschar *, uschar *, BOOL); +extern int test_harness_fudged_queue_time(int); extern void tcp_init(void); #ifdef EXIM_TFO_PROBE extern void tfo_probe(void); @@ -602,6 +611,58 @@ extern BOOL write_chunk(transport_ctx *, uschar *, int); extern ssize_t write_to_fd_buf(int, const uschar *, size_t); +/******************************************************************************/ +/* Predicate: if an address is in a tainted pool. +By extension, a variable pointing to this address is tainted. +*/ + +static inline BOOL +is_tainted(const void * p) +{ +#if defined(COMPILE_UTILITY) || defined(MACRO_PREDEF) || defined(EM_VERSION_C) +return FALSE; + +#else +extern BOOL is_tainted_fn(const void *); +return is_tainted_fn(p); +#endif +} + +/******************************************************************************/ +/* String functions */ +static inline uschar * __Ustrcat(uschar * dst, const uschar * src, const char * func, int line) +{ +#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF) +if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrcat", CUS func, line); +#endif +return US strcat(CS dst, CCS src); +} +static inline uschar * __Ustrcpy(uschar * dst, const uschar * src, const char * func, int line) +{ +#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF) +if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrcpy", CUS func, line); +#endif +return US strcpy(CS dst, CCS src); +} +static inline uschar * __Ustrncat(uschar * dst, const uschar * src, size_t n, const char * func, int line) +{ +#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF) +if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrncat", CUS func, line); +#endif +return US strncat(CS dst, CCS src, n); +} +static inline uschar * __Ustrncpy(uschar * dst, const uschar * src, size_t n, const char * func, int line) +{ +#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF) +if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrncpy", CUS func, line); +#endif +return US strncpy(CS dst, CCS src, n); +} +/*XXX will likely need unchecked copy also */ + + +/******************************************************************************/ + #if !defined(MACRO_PREDEF) && !defined(COMPILE_UTILITY) /* exim_chown - in some NFSv4 setups *seemes* to be an issue with chown(, ). @@ -634,8 +695,8 @@ exim_chown(const uschar *name, uid_t owner, gid_t group) return chown(CCS name, owner, group) ? exim_chown_failure(-1, name, owner, group) : 0; } - #endif /* !MACRO_PREDEF && !COMPILE_UTILITY */ + /******************************************************************************/ /* String functions */ @@ -660,11 +721,14 @@ return ss; string_copy_taint_trc((s), tainted, __FUNCTION__, __LINE__) static inline uschar * -string_copy(const uschar * s) +string_copy_trc(const uschar * s, const char * func, int line) { -return string_copy_taint((s), is_tainted(s)); +return string_copy_taint_trc((s), is_tainted(s), func, line); } +#define string_copy(s) \ + string_copy_trc((s), __FUNCTION__, __LINE__) + /************************************************* * Copy, lowercase and save string * @@ -816,6 +880,12 @@ g->s[g->ptr] = '\0'; return g->s; } +static inline unsigned +gstring_length(const gstring * g) +{ +return g ? (unsigned)g->ptr : 0; +} + #define gstring_release_unused(g) \ gstring_release_unused_trc(g, __FUNCTION__, __LINE__) @@ -878,20 +948,42 @@ return string_sprintf("%s/%s/%s/%s", # endif static inline uschar * -spool_sname(const uschar * purpose, uschar * subdir) +spool_q_sname(const uschar * purpose, const uschar * q, uschar * subdir) { return string_sprintf("%s%s%s%s%s", - queue_name, *queue_name ? "/" : "", + q, *q ? "/" : "", purpose, *subdir ? "/" : "", subdir); } static inline uschar * -spool_fname(const uschar * purpose, const uschar * subdir, const uschar * fname, - const uschar * suffix) +spool_sname(const uschar * purpose, uschar * subdir) +{ +return spool_q_sname(purpose, queue_name, subdir); +} + +static inline uschar * +spool_q_fname(const uschar * purpose, const uschar * q, + const uschar * subdir, const uschar * fname, const uschar * suffix) { return string_sprintf("%s/%s/%s/%s/%s%s", + spool_directory, q, purpose, subdir, fname, suffix); +} + +static inline uschar * +spool_fname(const uschar * purpose, const uschar * subdir, const uschar * fname, + const uschar * suffix) +{ +#ifdef COMPILE_UTILITY /* version avoiding string-extension */ +int len = Ustrlen(spool_directory) + 1 + Ustrlen(queue_name) + 1 + Ustrlen(purpose) + 1 + + Ustrlen(subdir) + 1 + Ustrlen(fname) + Ustrlen(suffix) + 1; +uschar * buf = store_get(len, FALSE); +string_format(buf, len, "%s/%s/%s/%s/%s%s", spool_directory, queue_name, purpose, subdir, fname, suffix); +return buf; +#else +return spool_q_fname(purpose, queue_name, subdir, fname, suffix); +#endif } static inline void @@ -904,8 +996,10 @@ subdir_str[1] = '\0'; } /******************************************************************************/ +/* Time calculations */ + static inline void -timesince(struct timeval * diff, struct timeval * then) +timesince(struct timeval * diff, const struct timeval * then) { gettimeofday(diff, NULL); diff->tv_sec -= then->tv_sec; @@ -917,20 +1011,20 @@ if ((diff->tv_usec -= then->tv_usec) < 0) } static inline uschar * -string_timediff(struct timeval * diff) +string_timediff(const struct timeval * diff) { static uschar buf[sizeof("0.000s")]; if (diff->tv_sec >= 5 || !LOGGING(millisec)) return readconf_printtime((int)diff->tv_sec); -sprintf(CS buf, "%u.%03us", (uint)diff->tv_sec, (uint)diff->tv_usec/1000); +snprintf(CS buf, sizeof(buf), "%u.%03us", (uint)diff->tv_sec, (uint)diff->tv_usec/1000); return buf; } static inline uschar * -string_timesince(struct timeval * then) +string_timesince(const struct timeval * then) { struct timeval diff; timesince(&diff, then); @@ -938,7 +1032,7 @@ return string_timediff(&diff); } static inline void -report_time_since(struct timeval * t0, uschar * where) +report_time_since(const struct timeval * t0, const uschar * where) { # ifdef MEASURE_TIMING struct timeval diff; @@ -953,10 +1047,55 @@ 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 } +/******************************************************************************/ +/* Taint-checked file opens */ + +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); +errno = EACCES; +return -1; +} +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); +errno = EACCES; +return -1; +} +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); +errno = EACCES; +return -1; +} +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); +errno = EACCES; +return -1; +} + +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); +errno = EACCES; +return NULL; +} + #endif /* !MACRO_PREDEF */ #endif /* _FUNCTIONS_H_ */