d54e3c2969578504405693fc6667c41eceaa7b24
[exim.git] / src / src / routers / rf_get_transport.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) The Exim Maintainers 2021 - 2022 */
6 /* Copyright (c) University of Cambridge 1995 - 2009 */
7 /* See the file NOTICE for conditions of use and distribution. */
8 /* SPDX-License-Identifier: GPL-2.0-or-later */
9
10 #include "../exim.h"
11 #include "rf_functions.h"
12
13
14 /*************************************************
15 *       Get transport for a router               *
16 *************************************************/
17
18 /* If transport_name contains $, it must be expanded each time and used as a
19 transport name. Otherwise, look up the transport only if the destination is not
20 already set.
21
22 Some routers (e.g. accept) insist that their transport option is set at
23 initialization time. However, for some (e.g. file_transport in redirect), there
24 is no such check, because the transport may not be required. Calls to this
25 function from the former type of router have require_name = NULL, because it
26 will never be used. NULL is also used in verify_only cases, where a transport
27 is not required.
28
29 Arguments:
30   tpname        the text of the transport name
31   tpptr         where to put the transport
32   addr          the address being processed
33   router_name   for error messages
34   require_name  used in the error message if transport is unset
35
36 Returns:        TRUE if *tpptr is already set and tpname has no '$' in it;
37                 TRUE if a transport has been placed in tpptr;
38                 FALSE if there's a problem, in which case
39                 addr->message contains a message, and addr->basic_errno has
40                 ERRNO_BADTRANSPORT set in it.
41 */
42
43 BOOL
44 rf_get_transport(uschar *tpname, transport_instance **tpptr, address_item *addr,
45   uschar *router_name, uschar *require_name)
46 {
47 uschar *ss;
48 BOOL expandable;
49
50 if (!tpname)
51   {
52   if (!require_name) return TRUE;
53   addr->basic_errno = ERRNO_BADTRANSPORT;
54   addr->message = string_sprintf("%s unset in %s router", require_name,
55     router_name);
56   return FALSE;
57   }
58
59 expandable = Ustrchr(tpname, '$') != NULL;
60 if (*tpptr != NULL && !expandable) return TRUE;
61
62 if (expandable)
63   {
64   if (!(ss = expand_string(tpname)))
65     {
66     addr->basic_errno = ERRNO_BADTRANSPORT;
67     addr->message = string_sprintf("failed to expand transport "
68       "\"%s\" in %s router: %s", tpname, router_name, expand_string_message);
69     return FALSE;
70     }
71   if (is_tainted(ss))
72     {
73     log_write(0, LOG_MAIN|LOG_PANIC,
74       "attempt to use tainted value '%s' from '%s' for transport", ss, tpname);
75     addr->basic_errno = ERRNO_BADTRANSPORT;
76     /* Avoid leaking info to an attacker */
77     addr->message = US"internal configuration error";
78     return FALSE;
79     }
80   }
81 else
82   ss = tpname;
83
84 for (transport_instance * tp = transports; tp; tp = tp->next)
85   if (Ustrcmp(tp->name, ss) == 0)
86     {
87     DEBUG(D_route) debug_printf("set transport %s\n", ss);
88     *tpptr = tp;
89     return TRUE;
90     }
91
92 addr->basic_errno = ERRNO_BADTRANSPORT;
93 addr->message = string_sprintf("transport \"%s\" not found in %s router", ss,
94   router_name);
95 return FALSE;
96 }
97
98 /* End of rf_get_transport.c */