Add variables for wildcard portion of local-part affix. Bug 281
[exim.git] / src / src / functions.h
index ea3cf257c5f6869043b38a2959b08683c4953520..df4b33606982b574322c3f5c9127ad3160ba2ddf 100644 (file)
@@ -189,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 *);
@@ -286,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 *);
 
@@ -362,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);
@@ -416,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 *,
@@ -606,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(<exim-uid>, <exim-gid>).
@@ -638,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 */
 
@@ -664,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          *
@@ -820,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__)
@@ -906,9 +972,18 @@ return string_sprintf("%s/%s/%s/%s/%s%s",
 
 static inline uschar *
 spool_fname(const uschar * purpose, const uschar * subdir, const uschar * fname,
-               const uschar * suffix)
+       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
@@ -921,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;
@@ -934,7 +1011,7 @@ 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")];
 
@@ -947,7 +1024,7 @@ return buf;
 
 
 static inline uschar *
-string_timesince(struct timeval * then)
+string_timesince(const struct timeval * then)
 {
 struct timeval diff;
 timesince(&diff, then);
@@ -955,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;
@@ -970,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_ */