Commit | Line | Data |
---|---|---|
b7670459 PH |
1 | /************************************************* |
2 | * Exim - an Internet mail transport agent * | |
3 | *************************************************/ | |
4 | ||
f9ba5e22 | 5 | /* Copyright (c) University of Cambridge 1995 - 2018 */ |
b7670459 PH |
6 | /* See the file NOTICE for conditions of use and distribution. */ |
7 | ||
8 | ||
9 | #include "../exim.h" | |
10 | #include "lf_functions.h" | |
11 | ||
12 | ||
13 | ||
14 | /************************************************* | |
15 | * Call SQL server(s) to run an actual query * | |
16 | *************************************************/ | |
17 | ||
18 | /* All the SQL lookups are of the same form, with a list of servers to try | |
19 | until one can be accessed. It is now also possible to provide the server data | |
20 | as part of the query. This function manages server selection and looping; each | |
21 | lookup has its own function for actually performing the lookup. | |
22 | ||
23 | Arguments: | |
24 | name the lookup name, e.g. "MySQL" | |
25 | optionname the name of the servers option, e.g. "mysql_servers" | |
26 | optserverlist the value of the servers option | |
27 | query the query | |
28 | result where to pass back the result | |
29 | errmsg where to pass back an error message | |
14b3c5bc | 30 | do_cache to be set zero if data is changed |
b7670459 PH |
31 | func the lookup function to call |
32 | ||
33 | Returns: the return from the lookup function, or DEFER | |
34 | */ | |
35 | ||
36 | int | |
55414b25 JH |
37 | lf_sqlperform(const uschar *name, const uschar *optionname, |
38 | const uschar *optserverlist, const uschar *query, | |
0b4dfe7a JH |
39 | uschar **result, uschar **errmsg, uint *do_cache, const uschar * opts, |
40 | int(*fn)(const uschar *, uschar *, uschar **, uschar **, BOOL *, uint *, const uschar *)) | |
b7670459 | 41 | { |
0b4dfe7a | 42 | int rc; |
b7670459 | 43 | uschar *server; |
b7670459 PH |
44 | BOOL defer_break = FALSE; |
45 | ||
0b4dfe7a | 46 | DEBUG(D_lookup) debug_printf_indent("%s query: \"%s\" opts '%s'\n", name, query, opts); |
b7670459 PH |
47 | |
48 | /* Handle queries that do have server information at the start. */ | |
49 | ||
0b4dfe7a | 50 | if (Ustrncmp(query, "servers", 7) == 0) |
b7670459 | 51 | { |
0b4dfe7a | 52 | int qsep = 0; |
55414b25 JH |
53 | const uschar *s, *ss; |
54 | const uschar *qserverlist; | |
b7670459 | 55 | uschar *qserver; |
b7670459 PH |
56 | |
57 | s = query + 7; | |
0b4dfe7a | 58 | skip_whitespace(&s); |
b7670459 PH |
59 | if (*s++ != '=') |
60 | { | |
61 | *errmsg = string_sprintf("missing = after \"servers\" in %s lookup", name); | |
62 | return DEFER; | |
63 | } | |
0b4dfe7a | 64 | skip_whitespace(&s); |
b7670459 PH |
65 | |
66 | ss = Ustrchr(s, ';'); | |
0b4dfe7a | 67 | if (!ss) |
b7670459 PH |
68 | { |
69 | *errmsg = string_sprintf("missing ; after \"servers=\" in %s lookup", | |
70 | name); | |
71 | return DEFER; | |
72 | } | |
73 | ||
74 | if (ss == s) | |
75 | { | |
76 | *errmsg = string_sprintf("\"servers=\" defines no servers in \"%s\"", | |
77 | query); | |
78 | return DEFER; | |
79 | } | |
80 | ||
bb07bcd3 | 81 | qserverlist = string_sprintf("%.*s", (int)(ss - s), s); |
b7670459 | 82 | |
0b4dfe7a | 83 | while ((qserver = string_nextinlist(&qserverlist, &qsep, NULL, 0))) |
b7670459 | 84 | { |
0b4dfe7a | 85 | if (Ustrchr(qserver, '/')) |
b7670459 PH |
86 | server = qserver; |
87 | else | |
88 | { | |
89 | int len = Ustrlen(qserver); | |
0b4dfe7a | 90 | const uschar * serverlist = optserverlist; |
b7670459 | 91 | |
0b4dfe7a | 92 | for (int sep = 0; server = string_nextinlist(&serverlist, &sep, NULL, 0);) |
b7670459 PH |
93 | if (Ustrncmp(server, qserver, len) == 0 && server[len] == '/') |
94 | break; | |
b7670459 | 95 | |
0b4dfe7a | 96 | if (!server) |
b7670459 PH |
97 | { |
98 | *errmsg = string_sprintf("%s server \"%s\" not found in %s", name, | |
99 | qserver, optionname); | |
100 | return DEFER; | |
101 | } | |
102 | } | |
103 | ||
0b4dfe7a JH |
104 | if (is_tainted(server)) |
105 | { | |
106 | *errmsg = string_sprintf("%s server \"%s\" is tainted", name, server); | |
107 | return DEFER; | |
108 | } | |
109 | ||
110 | rc = (*fn)(ss+1, server, result, errmsg, &defer_break, do_cache, opts); | |
b7670459 PH |
111 | if (rc != DEFER || defer_break) return rc; |
112 | } | |
113 | } | |
114 | ||
0b4dfe7a JH |
115 | /* Handle queries that do not have server information at the start. */ |
116 | ||
117 | else | |
118 | { | |
119 | const uschar * serverlist = NULL; | |
120 | ||
121 | /* If options are present, scan for a server definition. Default to | |
122 | the "optserverlist" srgument. */ | |
123 | ||
124 | if (opts) | |
125 | { | |
126 | uschar * ele; | |
127 | for (int sep = ','; ele = string_nextinlist(&opts, &sep, NULL, 0); ) | |
128 | if (Ustrncmp(ele, "servers=", 8) == 0) | |
129 | { serverlist = ele + 8; break; } | |
130 | } | |
131 | ||
132 | if (!serverlist) | |
133 | serverlist = optserverlist; | |
134 | if (!serverlist) | |
135 | *errmsg = string_sprintf("no %s servers defined (%s option)", name, | |
136 | optionname); | |
137 | else | |
138 | for (int d = 0; (server = string_nextinlist(&serverlist, &d, NULL, 0)); ) | |
139 | { | |
140 | /* If not a full spec assume from options; scan main list for matching | |
141 | hostname */ | |
142 | ||
143 | if (!Ustrchr(server, '/')) | |
144 | { | |
145 | int len = Ustrlen(server); | |
146 | const uschar * slist = optserverlist; | |
147 | uschar * ele; | |
148 | for (int sep = 0; ele = string_nextinlist(&slist, &sep, NULL, 0); ) | |
149 | if (Ustrncmp(ele, server, len) == 0 && ele[len] == '/') | |
150 | break; | |
151 | if (!ele) | |
152 | { | |
153 | *errmsg = string_sprintf("%s server \"%s\" not found in %s", name, | |
154 | server, optionname); | |
155 | return DEFER; | |
156 | } | |
157 | server = ele; | |
158 | } | |
159 | ||
160 | if (is_tainted(server)) | |
161 | { | |
162 | *errmsg = string_sprintf("%s server \"%s\" is tainted", name, server); | |
163 | return DEFER; | |
164 | } | |
165 | ||
166 | rc = (*fn)(query, server, result, errmsg, &defer_break, do_cache, opts); | |
167 | if (rc != DEFER || defer_break) return rc; | |
168 | } | |
169 | } | |
170 | ||
b7670459 PH |
171 | return DEFER; |
172 | } | |
173 | ||
174 | /* End of lf_sqlperform.c */ |