SECURITY: off-by-one in smtp transport (read response)
[exim.git] / src / src / functions.h
index 38309e7ddf5b97f320a74e12a1b3d281607a004b..06b6974ae8c7dec98e8acbdd01a4043f55673145 100644 (file)
@@ -75,6 +75,7 @@ extern BOOL    tls_openssl_options_parse(uschar *, long *);
 # endif
 extern int     tls_read(void *, uschar *, size_t);
 extern int     tls_server_start(uschar **);
+extern void    tls_shutdown_wr(void *);
 extern BOOL    tls_smtp_buffered(void);
 extern int     tls_ungetc(int);
 #if defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT)
@@ -204,7 +205,6 @@ extern void    deliver_set_expansions(address_item *);
 extern int     deliver_split_address(address_item *);
 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);
@@ -340,6 +340,9 @@ extern int     match_isinlist(const uschar *, const uschar **, int, tree_node **
                  unsigned int *, int, BOOL, const uschar **);
 extern int     match_check_string(const uschar *, const uschar *, int, BOOL, BOOL, BOOL,
                  const uschar **);
+
+extern void    message_start(void);
+extern void    message_tidyup(void);
 extern void    md5_end(md5 *, const uschar *, int, uschar *);
 extern void    md5_mid(md5 *, const uschar *);
 extern void    md5_start(md5 *);
@@ -368,16 +371,16 @@ extern FILE   *modefopen(const uschar *, const char *, mode_t);
 
 extern int     open_cutthrough_connection( address_item * addr );
 
-extern uschar *parse_extract_address(uschar *, uschar **, int *, int *, int *,
+extern uschar *parse_extract_address(const uschar *, uschar **, int *, int *, int *,
                  BOOL);
 extern int     parse_forward_list(uschar *, int, address_item **, uschar **,
                  const uschar *, uschar *, error_block **);
 extern uschar *parse_find_address_end(uschar *, BOOL);
-extern uschar *parse_find_at(uschar *);
+extern const uschar *parse_find_at(const uschar *);
 extern const uschar *parse_fix_phrase(const uschar *, int);
-extern uschar *parse_message_id(uschar *, uschar **, uschar **);
+extern const uschar *parse_message_id(const uschar *, uschar **, uschar **);
 extern const uschar *parse_quote_2047(const uschar *, int, uschar *, BOOL);
-extern uschar *parse_date_time(uschar *str, time_t *t);
+extern const uschar *parse_date_time(const uschar *str, time_t *t);
 extern int     vaguely_random_number(int);
 #ifndef DISABLE_TLS
 extern int     vaguely_random_number_fallback(int);
@@ -405,7 +408,7 @@ extern void    readconf_driver_init(uschar *, driver_instance **,
 extern uschar *readconf_find_option(void *);
 extern void    readconf_main(BOOL);
 extern void    readconf_options_from_list(optionlist *, unsigned, const uschar *, uschar *);
-extern BOOL    readconf_print(uschar *, uschar *, BOOL);
+extern BOOL    readconf_print(const uschar *, uschar *, BOOL);
 extern uschar *readconf_printtime(int);
 extern uschar *readconf_readname(uschar *, int, uschar *);
 extern int     readconf_readtime(const uschar *, int, BOOL);
@@ -431,14 +434,14 @@ extern retry_config *retry_find_config(const uschar *, const uschar *, int, int)
 extern BOOL    retry_ultimate_address_timeout(uschar *, const uschar *,
                  dbdata_retry *, time_t);
 extern void    retry_update(address_item **, address_item **, address_item **);
-extern uschar *rewrite_address(uschar *, BOOL, BOOL, rewrite_rule *, int);
-extern uschar *rewrite_address_qualify(uschar *, BOOL);
+extern const uschar *rewrite_address(const uschar *, BOOL, BOOL, rewrite_rule *, int);
+extern const uschar *rewrite_address_qualify(const uschar *, BOOL);
 extern header_line *rewrite_header(header_line *,
                const uschar *, const uschar *,
                rewrite_rule *, int, BOOL);
-extern uschar *rewrite_one(uschar *, int, BOOL *, BOOL, uschar *,
+extern const uschar *rewrite_one(const uschar *, int, BOOL *, BOOL, uschar *,
                  rewrite_rule *);
-extern void    rewrite_test(uschar *);
+extern void    rewrite_test(const uschar *);
 extern uschar *rfc2047_decode2(uschar *, BOOL, uschar *, int, int *, int *,
                  uschar **);
 extern int     route_address(address_item *, address_item **, address_item **,
@@ -514,6 +517,7 @@ extern BOOL    spool_move_message(uschar *, uschar *, uschar *, uschar *);
 extern int     spool_open_datafile(uschar *);
 extern int     spool_open_temp(uschar *);
 extern int     spool_read_header(uschar *, BOOL, BOOL);
+extern uschar *spool_sender_from_msgid(const uschar *);
 extern int     spool_write_header(uschar *, int, uschar **);
 extern int     stdin_getc(unsigned);
 extern int     stdin_feof(void);
@@ -521,6 +525,8 @@ extern int     stdin_ferror(void);
 extern int     stdin_ungetc(int);
 
 extern void    store_exit(void);
+extern void    store_init(void);
+
 extern gstring *string_append(gstring *, int, ...) WARN_UNUSED_RESULT;
 extern gstring *string_append_listele(gstring *, uschar, const uschar *) WARN_UNUSED_RESULT;
 extern gstring *string_append_listele_n(gstring *, uschar, const uschar *, unsigned) WARN_UNUSED_RESULT;
@@ -587,8 +593,11 @@ extern BOOL    transport_check_waiting(const uschar *, const uschar *, int, usch
 extern void    transport_init(void);
 extern void    transport_do_pass_socket(const uschar *, const uschar *,
                 const uschar *, uschar *, int);
-extern BOOL    transport_pass_socket(const uschar *, const uschar *, const uschar *, uschar *,
-                 int);
+extern BOOL    transport_pass_socket(const uschar *, const uschar *, const uschar *, uschar *, int
+#ifdef EXPERIMENTAL_ESMTP_LIMITS
+                       , unsigned, unsigned, unsigned
+#endif
+                       );
 extern uschar *transport_rcpt_address(address_item *, BOOL);
 extern BOOL    transport_set_up_command(const uschar ***, uschar *,
                 BOOL, int, address_item *, uschar *, uschar **);
@@ -600,9 +609,9 @@ extern BOOL    transport_headers_send(transport_ctx *,
                  BOOL (*)(transport_ctx *, uschar *, int));
 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 *);
-extern void    tree_add_unusable(host_item *);
+extern void    tree_add_duplicate(const uschar *, address_item *);
+extern void    tree_add_nonrecipient(const uschar *);
+extern void    tree_add_unusable(const host_item *);
 extern void    tree_dup(tree_node **, tree_node *);
 extern int     tree_insertnode(tree_node **, tree_node *);
 extern tree_node *tree_search(tree_node *, const uschar *);
@@ -960,20 +969,34 @@ g->s = s;
 }
 
 
+# ifndef COMPILE_UTILITY
 /******************************************************************************/
+/* Use store_malloc for DNSA structs, and explicit frees. Using the same pool
+for them as the strings we proceed to copy from them meant they could not be
+released, hence blowing 64k for every DNS lookup. That mounted up. With malloc
+we do have to take care over marking tainted all copied strings.  A separate pool
+could be used and would handle that implicitly. */
 
 #define store_get_dns_answer() store_get_dns_answer_trc(CUS __FUNCTION__, __LINE__)
 
 static inline dns_answer *
 store_get_dns_answer_trc(const uschar * func, unsigned line)
 {
-return store_get_3(sizeof(dns_answer), TRUE, CCS func, line);  /* use tainted mem */
+/* return store_get_3(sizeof(dns_answer), TRUE, CCS func, line);   use tainted mem */
+return store_malloc_3(sizeof(dns_answer), CCS func, line);
+}
+
+#define store_free_dns_answer(dnsa) store_free_dns_answer_trc(dnsa, CUS __FUNCTION__, __LINE__)
+
+static inline void
+store_free_dns_answer_trc(dns_answer * dnsa, const uschar * func, unsigned line)
+{
+store_free_3(dnsa, CCS func, line);
 }
 
 /******************************************************************************/
 /* Routines with knowledge of spool layout */
 
-# ifndef COMPILE_UTILITY
 static inline void
 spool_pname_buf(uschar * buf, int len)
 {
@@ -1039,18 +1062,25 @@ subdir_str[1] = '\0';
 /******************************************************************************/
 /* Time calculations */
 
+/* Diff two times (later, earlier) returning diff in 1st arg */
 static inline void
-timesince(struct timeval * diff, const struct timeval * then)
+timediff(struct timeval * later, const struct timeval * earlier)
 {
-gettimeofday(diff, NULL);
-diff->tv_sec -= then->tv_sec;
-if ((diff->tv_usec -= then->tv_usec) < 0)
+later->tv_sec -= earlier->tv_sec;
+if ((later->tv_usec -= earlier->tv_usec) < 0)
   {
-  diff->tv_sec--;
-  diff->tv_usec += 1000*1000;
+  later->tv_sec--;
+  later->tv_usec += 1000*1000;
   }
 }
 
+static inline void
+timesince(struct timeval * diff, const struct timeval * then)
+{
+gettimeofday(diff, NULL);
+timediff(diff, then);
+}
+
 static inline uschar *
 string_timediff(const struct timeval * diff)
 {