]> git.pld-linux.org Git - packages/exim.git/blob - localscan_dlopen_exim_4.20_or_better.patch
10339dd94c3a825b9b1b212c560755d617f2bc0b
[packages/exim.git] / localscan_dlopen_exim_4.20_or_better.patch
1 Description: Allow one to use and switch between different local_scan functions
2  without recompiling exim.
3  http://marc.merlins.org/linux/exim/files/sa-exim-current/ Original patch from
4  David Woodhouse, modified first by Derrick 'dman' Hudson and then by Marc
5  MERLIN for SA-Exim and minor/major API version tracking
6 Author: David Woodhouse, Derrick 'dman' Hudson, Marc MERLIN
7 Origin: other, http://marc.merlins.org/linux/exim/files/sa-exim-current/
8 Forwarded: no
9 Last-Update: 2019-10-20
10
11 --- a/src/EDITME
12 +++ b/src/EDITME
13 @@ -868,6 +868,21 @@ HEADERS_CHARSET="ISO-8859-1"
14  
15  
16  #------------------------------------------------------------------------------
17 +# On systems which support dynamic loading of shared libraries, Exim can
18 +# load a local_scan function specified in its config file instead of having
19 +# to be recompiled with the desired local_scan function. For a full
20 +# description of the API to this function, see the Exim specification.
21 +
22 +DLOPEN_LOCAL_SCAN=yes
23 +
24 +# If you set DLOPEN_LOCAL_SCAN, then you need to include -rdynamic in the
25 +# linker flags.  Without it, the loaded .so won't be able to access any
26 +# functions from exim.
27 +
28 +LDFLAGS += -rdynamic
29 +CFLAGS += -fvisibility=hidden
30 +
31 +#------------------------------------------------------------------------------
32  # The default distribution of Exim contains only the plain text form of the
33  # documentation. Other forms are available separately. If you want to install
34  # the documentation in "info" format, first fetch the Texinfo documentation
35 --- a/src/config.h.defaults
36 +++ b/src/config.h.defaults
37 @@ -33,6 +33,8 @@ Do not put spaces between # and the 'def
38  
39  #define AUTH_VARS                     3
40  
41 +#define DLOPEN_LOCAL_SCAN
42 +
43  #define BIN_DIRECTORY
44  
45  #define CONFIGURE_FILE
46 --- a/src/globals.c
47 +++ b/src/globals.c
48 @@ -115,6 +115,10 @@ int     dsn_ret                = 0;
49  const pcre  *regex_DSN         = NULL;
50  uschar *dsn_advertise_hosts    = NULL;
51  
52 +#ifdef DLOPEN_LOCAL_SCAN
53 +uschar *local_scan_path        = NULL;
54 +#endif
55 +
56  #ifndef DISABLE_TLS
57  BOOL    gnutls_compat_mode     = FALSE;
58  BOOL    gnutls_allow_auto_pkcs11 = FALSE;
59 --- a/src/globals.h
60 +++ b/src/globals.h
61 @@ -144,6 +144,9 @@ extern int      dsn_ret;               /
62  extern const pcre  *regex_DSN;         /* For recognizing DSN settings */
63  extern uschar  *dsn_advertise_hosts;   /* host for which TLS is advertised */
64  
65 +#ifdef DLOPEN_LOCAL_SCAN
66 +extern uschar *local_scan_path;        /* Path to local_scan() library */
67 +#endif
68  /* Input-reading functions for messages, so we can use special ones for
69  incoming TCP/IP. */
70  
71 --- a/src/local_scan.c
72 +++ b/src/local_scan.c
73 @@ -6,22 +6,6 @@
74  /* See the file NOTICE for conditions of use and distribution. */
75  
76  
77 -/******************************************************************************
78 -This file contains a template local_scan() function that just returns ACCEPT.
79 -If you want to implement your own version, you should copy this file to, say
80 -Local/local_scan.c, and edit the copy. To use your version instead of the
81 -default, you must set
82 -
83 -HAVE_LOCAL_SCAN=yes
84 -LOCAL_SCAN_SOURCE=Local/local_scan.c
85 -
86 -in your Local/Makefile. This makes it easy to copy your version for use with
87 -subsequent Exim releases.
88 -
89 -For a full description of the API to this function, see the Exim specification.
90 -******************************************************************************/
91 -
92 -
93  /* This is the only Exim header that you should include. The effect of
94  including any other Exim header is not defined, and may change from release to
95  release. Use only the documented interface! */
96 @@ -29,37 +13,130 @@ release. Use only the documented interfa
97  #include "local_scan.h"
98  
99  
100 -/* This is a "do-nothing" version of a local_scan() function. The arguments
101 -are:
102 -
103 -  fd             The file descriptor of the open -D file, which contains the
104 -                   body of the message. The file is open for reading and
105 -                   writing, but modifying it is dangerous and not recommended.
106 -
107 -  return_text    A pointer to an unsigned char* variable which you can set in
108 -                   order to return a text string. It is initialized to NULL.
109 -
110 -The return values of this function are:
111 -
112 -  LOCAL_SCAN_ACCEPT
113 -                 The message is to be accepted. The return_text argument is
114 -                   saved in $local_scan_data.
115 -
116 -  LOCAL_SCAN_REJECT
117 -                 The message is to be rejected. The returned text is used
118 -                   in the rejection message.
119 -
120 -  LOCAL_SCAN_TEMPREJECT
121 -                 This specifies a temporary rejection. The returned text
122 -                   is used in the rejection message.
123 -*/
124 +#ifdef DLOPEN_LOCAL_SCAN
125 +#include <dlfcn.h>
126 +#include <stdlib.h>
127 +static int (*local_scan_fn)(int fd, uschar **return_text) = NULL;
128 +static int load_local_scan_library(void);
129 +#endif
130  
131  int
132  local_scan(int fd, uschar **return_text)
133  {
134  fd = fd;                      /* Keep picky compilers happy */
135  return_text = return_text;
136 -return LOCAL_SCAN_ACCEPT;
137 +#ifdef DLOPEN_LOCAL_SCAN
138 +/* local_scan_path is defined AND not the empty string */
139 +if (local_scan_path && *local_scan_path)
140 +  {
141 +  if (!local_scan_fn)
142 +    {
143 +    if (!load_local_scan_library())
144 +      {
145 +        char *base_msg , *error_msg , *final_msg ;
146 +        int final_length = -1 ;
147 +
148 +        base_msg=US"Local configuration error - local_scan() library failure\n";
149 +        error_msg = dlerror() ;
150 +
151 +        final_length = strlen(base_msg) + strlen(error_msg) + 1 ;
152 +        final_msg = (char*)malloc( final_length*sizeof(char) ) ;
153 +        *final_msg = '\0' ;
154 +
155 +        strcat( final_msg , base_msg ) ;
156 +        strcat( final_msg , error_msg ) ;
157 +
158 +        *return_text = final_msg ;
159 +      return LOCAL_SCAN_TEMPREJECT;
160 +      }
161 +    }
162 +    return local_scan_fn(fd, return_text);
163 +  }
164 +else
165 +#endif
166 +  return LOCAL_SCAN_ACCEPT;
167  }
168  
169 +#ifdef DLOPEN_LOCAL_SCAN
170 +
171 +static int load_local_scan_library(void)
172 +{
173 +/* No point in keeping local_scan_lib since we'll never dlclose() anyway */
174 +void *local_scan_lib = NULL;
175 +int (*local_scan_version_fn)(void);
176 +int vers_maj;
177 +int vers_min;
178 +
179 +local_scan_lib = dlopen(local_scan_path, RTLD_NOW);
180 +if (!local_scan_lib)
181 +  {
182 +  log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library open failed - "
183 +    "message temporarily rejected");
184 +  return FALSE;
185 +  }
186 +
187 +local_scan_version_fn = dlsym(local_scan_lib, "local_scan_version_major");
188 +if (!local_scan_version_fn)
189 +  {
190 +  dlclose(local_scan_lib);
191 +  log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library doesn't contain "
192 +    "local_scan_version_major() function - message temporarily rejected");
193 +  return FALSE;
194 +  }
195 +
196 +/* The major number is increased when the ABI is changed in a non
197 +   backward compatible way. */
198 +vers_maj = local_scan_version_fn();
199 +
200 +local_scan_version_fn = dlsym(local_scan_lib, "local_scan_version_minor");
201 +if (!local_scan_version_fn)
202 +  {
203 +  dlclose(local_scan_lib);
204 +  log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library doesn't contain "
205 +    "local_scan_version_minor() function - message temporarily rejected");
206 +  return FALSE;
207 +  }
208 +
209 +/* The minor number is increased each time a new feature is added (in a
210 +   way that doesn't break backward compatibility) -- Marc */
211 +vers_min = local_scan_version_fn();
212 +
213 +
214 +if (vers_maj != LOCAL_SCAN_ABI_VERSION_MAJOR)
215 +  {
216 +  dlclose(local_scan_lib);
217 +  local_scan_lib = NULL;
218 +  log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() has an incompatible major"
219 +    "version number, you need to recompile your module for this version"
220 +    "of exim (The module was compiled for version %d.%d and this exim provides"
221 +    "ABI version %d.%d)", vers_maj, vers_min, LOCAL_SCAN_ABI_VERSION_MAJOR,
222 +    LOCAL_SCAN_ABI_VERSION_MINOR);
223 +  return FALSE;
224 +  }
225 +else if (vers_min > LOCAL_SCAN_ABI_VERSION_MINOR)
226 +  {
227 +  dlclose(local_scan_lib);
228 +  local_scan_lib = NULL;
229 +  log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() has an incompatible minor"
230 +    "version number, you need to recompile your module for this version"
231 +    "of exim (The module was compiled for version %d.%d and this exim provides"
232 +    "ABI version %d.%d)", vers_maj, vers_min, LOCAL_SCAN_ABI_VERSION_MAJOR,
233 +    LOCAL_SCAN_ABI_VERSION_MINOR);
234 +  return FALSE;
235 +  }
236 +
237 +local_scan_fn = dlsym(local_scan_lib, "local_scan");
238 +if (!local_scan_fn)
239 +  {
240 +  dlclose(local_scan_lib);
241 +  log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library doesn't contain "
242 +    "local_scan() function - message temporarily rejected");
243 +  return FALSE;
244 +  }
245 +return TRUE;
246 +}
247 +
248 +#endif /* DLOPEN_LOCAL_SCAN */
249 +
250 +
251  /* End of local_scan.c */
252 --- a/src/local_scan.h
253 +++ b/src/local_scan.h
254 @@ -17,6 +17,7 @@ settings, and the store functions. */
255  
256  #include <stdarg.h>
257  #include <sys/types.h>
258 +#pragma GCC visibility push(default)
259  #include "config.h"
260  #include "mytypes.h"
261  #include "store.h"
262 @@ -149,6 +150,9 @@ extern header_line *header_list;       /
263  extern BOOL    host_checking;          /* Set when checking a host */
264  extern uschar *interface_address;      /* Interface for incoming call */
265  extern int     interface_port;         /* Port number for incoming call */
266 +#ifdef DLOPEN_LOCAL_SCAN
267 +extern uschar *local_scan_path;
268 +#endif
269  extern uschar *message_id;             /* Internal id of message being handled */
270  extern uschar *received_protocol;      /* Name of incoming protocol */
271  extern int     recipients_count;       /* Number of recipients */
272 @@ -207,4 +211,6 @@ extern uschar * string_copyn_function(co
273  extern uschar * string_copy_taint_function(const uschar *, BOOL tainted);
274  #endif
275  
276 +#pragma GCC visibility pop
277 +
278  /* End of local_scan.h */
279 --- a/src/readconf.c
280 +++ b/src/readconf.c
281 @@ -203,6 +203,9 @@ static optionlist optionlist_config[] =
282    { "local_from_prefix",        opt_stringptr,   {&local_from_prefix} },
283    { "local_from_suffix",        opt_stringptr,   {&local_from_suffix} },
284    { "local_interfaces",         opt_stringptr,   {&local_interfaces} },
285 +#ifdef DLOPEN_LOCAL_SCAN
286 +  { "local_scan_path",          opt_stringptr,   {&local_scan_path} },
287 +#endif
288  #ifdef HAVE_LOCAL_SCAN
289    { "local_scan_timeout",       opt_time,        {&local_scan_timeout} },
290  #endif
291 --- a/src/string.c
292 +++ b/src/string.c
293 @@ -413,6 +413,7 @@ return ss;
294  
295  #if (defined(HAVE_LOCAL_SCAN) || defined(EXPAND_DLFUNC)) \
296         && !defined(MACRO_PREDEF) && !defined(COMPILE_UTILITY)
297 +#pragma GCC visibility push(default)
298  /*************************************************
299  *            Copy and save string                *
300  *************************************************/
301 @@ -465,6 +466,7 @@ Ustrncpy(ss, s, n);
302  ss[n] = 0;
303  return ss;
304  }
305 +#pragma GCC visibility pop
306  #endif
307  
308  
309
This page took 0.048726 seconds and 2 git commands to generate.