*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
-/* Copyright (c) The Exim Maintainers 2020 */
+/* Copyright (c) The Exim Maintainers 2020 - 2021 */
/* See the file NOTICE for conditions of use and distribution. */
extern void tls_close(void *, int);
extern BOOL tls_could_read(void);
extern void tls_daemon_init(void);
-extern void tls_daemon_tick(void);
+extern int tls_daemon_tick(void);
extern BOOL tls_dropprivs_validate_require_cipher(BOOL);
extern BOOL tls_export_cert(uschar *, size_t, void *);
extern int tls_feof(void);
extern void tls_free_cert(void **);
extern int tls_getc(unsigned);
extern uschar *tls_getbuf(unsigned *);
-extern void tls_get_cache(void);
+extern void tls_get_cache(unsigned);
+extern BOOL tls_hasc(void);
extern BOOL tls_import_cert(const uschar *, void **);
extern BOOL tls_is_name_for_cert(const uschar *, void *);
# ifdef USE_OPENSSL
extern int b64decode(const uschar *, uschar **);
extern int bdat_getc(unsigned);
extern uschar *bdat_getbuf(unsigned *);
+extern BOOL bdat_hasc(void);
extern int bdat_ungetc(int);
extern void bdat_flush_data(void);
extern int ipv6_nmtoa(int *, uschar *);
extern uschar *local_part_quote(uschar *);
-extern int log_create(uschar *);
-extern int log_create_as_exim(uschar *);
+extern int log_open_as_exim(uschar * const);
extern void log_close_all(void);
extern macro_item * macro_create(const uschar *, const uschar *, BOOL);
extern uschar *parse_extract_address(const uschar *, uschar **, int *, int *, int *,
BOOL);
-extern int parse_forward_list(uschar *, int, address_item **, uschar **,
+extern int parse_forward_list(const uschar *, int, address_item **, uschar **,
const uschar *, uschar *, error_block **);
-extern uschar *parse_find_address_end(uschar *, BOOL);
+extern uschar *parse_find_address_end(const uschar *, BOOL);
extern const uschar *parse_find_at(const uschar *);
extern const uschar *parse_fix_phrase(const uschar *, int);
extern const uschar *parse_message_id(const uschar *, uschar **, uschar **);
-extern const uschar *parse_quote_2047(const uschar *, int, uschar *, BOOL);
+extern const uschar *parse_quote_2047(const uschar *, int, const uschar *,
+ BOOL);
extern const uschar *parse_date_time(const uschar *str, time_t *t);
+extern void priv_drop_temp(const uid_t, const gid_t);
+extern void priv_restore(void);
extern int vaguely_random_number(int);
#ifndef DISABLE_TLS
extern int vaguely_random_number_fallback(int);
#ifdef WITH_CONTENT_SCAN
extern int regex(const uschar **);
#endif
-extern BOOL regex_match_and_setup(const pcre *, const uschar *, int, int);
-extern const pcre *regex_must_compile(const uschar *, BOOL, BOOL);
+extern BOOL regex_match(const pcre2_code *, const uschar *, int, uschar **);
+extern BOOL regex_match_and_setup(const pcre2_code *, const uschar *, int, int);
+extern const pcre2_code *regex_must_compile(const uschar *, BOOL, BOOL);
extern void retry_add_item(address_item *, uschar *, int);
extern BOOL retry_check_address(const uschar *, host_item *, uschar *, BOOL,
uschar **, uschar **);
extern const uschar *rewrite_one(const uschar *, int, BOOL *, BOOL, uschar *,
rewrite_rule *);
extern void rewrite_test(const uschar *);
-extern uschar *rfc2047_decode2(uschar *, BOOL, uschar *, int, int *, int *,
- uschar **);
+extern uschar *rfc2047_decode2(uschar *, BOOL, const 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 *, unsigned *);
extern BOOL smtp_get_port(uschar *, address_item *, int *, uschar *);
extern int smtp_getc(unsigned);
extern uschar *smtp_getbuf(unsigned *);
-extern void smtp_get_cache(void);
+extern void smtp_get_cache(unsigned);
+extern BOOL smtp_hasc(void);
extern int smtp_handle_acl_fail(int, int, uschar *, uschar *);
extern void smtp_log_no_mail(void);
extern void smtp_message_code(uschar **, int *, uschar **, uschar **, BOOL);
extern int stdin_getc(unsigned);
extern int stdin_feof(void);
extern int stdin_ferror(void);
+extern BOOL stdin_hasc(void);
extern int stdin_ungetc(int);
extern void store_exit(void);
extern void store_init(void);
+extern void store_writeprotect(int);
extern gstring *string_append(gstring *, int, ...) WARN_UNUSED_RESULT;
extern gstring *string_append_listele(gstring *, uschar, const uschar *) WARN_UNUSED_RESULT;
/******************************************************************************/
/* Taint-checked file opens */
+static inline uschar *
+is_tainted2(const void *p, int lflags, const char* fmt, ...)
+{
+va_list ap;
+uschar *msg;
+rmark mark;
+
+if (!is_tainted(p))
+ return NULL;
+
+mark = store_mark();
+va_start(ap, fmt);
+msg = string_from_gstring(string_vformat(NULL, SVFMT_TAINT_NOCHK|SVFMT_EXTEND, fmt, ap));
+va_end(ap);
+
+#ifdef ALLOW_INSECURE_TAINTED_DATA
+if (allow_insecure_tainted_data)
+ {
+ if LOGGING(tainted) log_write(0, LOG_MAIN, "Warning: %s", msg);
+ store_reset(mark);
+ return NULL;
+ }
+#endif
+
+if (lflags) log_write(0, lflags, "%s", msg);
+return msg; /* no store_reset(), as the message might be used afterwards and Exim
+ is expected to exit anyway, so we do not care about the leaked
+ storage */
+}
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'", pathname);
+if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
+ return open(pathname, flags);
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'", pathname);
+if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
+ return open(pathname, flags, mode);
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'", pathname);
+if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
+ return openat(dirfd, pathname, flags);
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'", pathname);
+if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
+ return openat(dirfd, pathname, flags, mode);
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'", pathname);
+if (!is_tainted2(pathname, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname))
+ return fopen(pathname, mode);
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);
+if (!is_tainted2(name, LOG_MAIN|LOG_PANIC, "Tainted dirname '%s'", name))
+ return opendir(CCS name);
errno = EACCES;
return NULL;
}