summaryrefslogtreecommitdiff
blob: 320cc9936da9cfda5020ce2361cf64cec6681085 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
Only in exim-4.95: dlopen.patch
diff -aur exim-4.95.orig/src/config.h.defaults exim-4.95/src/config.h.defaults
--- exim-4.95.orig/src/config.h.defaults	2021-09-28 10:24:46.000000000 +0200
+++ exim-4.95/src/config.h.defaults	2021-09-29 08:20:03.677883649 +0200
@@ -35,6 +35,8 @@
 
 #define AUTH_VARS                     4
 
+#define DLOPEN_LOCAL_SCAN
+
 #define BIN_DIRECTORY
 
 #define CONFIGURE_FILE
Only in exim-4.95/src: config.h.defaults.orig
diff -aur exim-4.95.orig/src/EDITME exim-4.95/src/EDITME
--- exim-4.95.orig/src/EDITME	2021-09-28 10:24:46.000000000 +0200
+++ exim-4.95/src/EDITME	2021-09-29 08:20:03.678883649 +0200
@@ -883,6 +883,24 @@
 
 
 #------------------------------------------------------------------------------
+# On systems which support dynamic loading of shared libraries, Exim can
+# load a local_scan function specified in its config file instead of having
+# to be recompiled with the desired local_scan function. For a full
+# description of the API to this function, see the Exim specification.
+
+#DLOPEN_LOCAL_SCAN=yes
+
+# If you set DLOPEN_LOCAL_SCAN, then you need to include -rdynamic in the
+# linker flags.  Without it, the loaded .so won't be able to access any
+# functions from exim.
+
+LFLAGS = -rdynamic
+ifeq ($(OSTYPE),Linux)
+LFLAGS += -ldl
+endif
+
+
+#------------------------------------------------------------------------------
 # The default distribution of Exim contains only the plain text form of the
 # documentation. Other forms are available separately. If you want to install
 # the documentation in "info" format, first fetch the Texinfo documentation
Only in exim-4.95/src: EDITME.orig
diff -aur exim-4.95.orig/src/globals.c exim-4.95/src/globals.c
--- exim-4.95.orig/src/globals.c	2021-09-28 10:24:46.000000000 +0200
+++ exim-4.95/src/globals.c	2021-09-29 08:20:03.679883649 +0200
@@ -42,6 +42,10 @@
 
 uschar *no_aliases             = NULL;
 
+#ifdef DLOPEN_LOCAL_SCAN
+uschar *local_scan_path        = NULL;
+#endif
+
 
 /* For comments on these variables, see globals.h. I'm too idle to
 duplicate them here... */
Only in exim-4.95/src: globals.c.orig
diff -aur exim-4.95.orig/src/globals.h exim-4.95/src/globals.h
--- exim-4.95.orig/src/globals.h	2021-09-28 10:24:46.000000000 +0200
+++ exim-4.95/src/globals.h	2021-09-29 08:20:03.680883648 +0200
@@ -170,6 +170,9 @@
 extern int (*receive_ferror)(void);
 extern BOOL (*receive_smtp_buffered)(void);
 
+#ifdef DLOPEN_LOCAL_SCAN
+extern uschar *local_scan_path;        /* Path to local_scan() library */
+#endif
 
 /* For clearing, saving, restoring address expansion variables. We have to have
 the size of this vector set explicitly, because it is referenced from more than
Only in exim-4.95/src: globals.h.orig
diff -aur exim-4.95.orig/src/local_scan.c exim-4.95/src/local_scan.c
--- exim-4.95.orig/src/local_scan.c	2021-09-28 10:24:46.000000000 +0200
+++ exim-4.95/src/local_scan.c	2021-09-29 08:23:33.756785663 +0200
@@ -54,10 +54,130 @@
                    is used in the rejection message.
 */
 
+#ifdef DLOPEN_LOCAL_SCAN
+# include <stdlib.h>
+# include <dlfcn.h>
+static int (*local_scan_fn)(int fd, uschar **return_text) = NULL;
+static int load_local_scan_library(void);
+extern uschar *local_scan_path;        /* Path to local_scan() library */
+#endif
+
 int
 local_scan(int fd, uschar **return_text)
 {
-return LOCAL_SCAN_ACCEPT;
+#ifdef DLOPEN_LOCAL_SCAN
+/* local_scan_path is defined AND not the empty string */
+if (local_scan_path && *local_scan_path)
+  {
+  if (!local_scan_fn)
+    {
+    if (!load_local_scan_library())
+      {
+        char *base_msg , *error_msg , *final_msg ;
+        int final_length = -1 ;
+
+        base_msg=US"Local configuration error - local_scan() library failure\n";
+        error_msg = dlerror() ;
+
+        final_length = strlen(base_msg) + strlen(error_msg) + 1 ;
+        final_msg = (char*)malloc( final_length*sizeof(char) ) ;
+        *final_msg = '\0' ;
+
+        strcat( final_msg , base_msg ) ;
+        strcat( final_msg , error_msg ) ;
+
+        *return_text = final_msg ;
+      return LOCAL_SCAN_TEMPREJECT;
+      }
+    }
+    return local_scan_fn(fd, return_text);
+  }
+else
+#endif
+  return LOCAL_SCAN_ACCEPT;
+}
+
+#ifdef DLOPEN_LOCAL_SCAN
+
+static int load_local_scan_library(void)
+{
+/* No point in keeping local_scan_lib since we'll never dlclose() anyway */
+void *local_scan_lib = NULL;
+int (*local_scan_version_fn)(void);
+int vers_maj;
+int vers_min;
+
+local_scan_lib = dlopen(local_scan_path, RTLD_NOW);
+if (!local_scan_lib)
+  {
+  log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library open failed - "
+    "message temporarily rejected");
+  return FALSE;
+  }
+
+local_scan_version_fn = dlsym(local_scan_lib, "local_scan_version_major");
+if (!local_scan_version_fn)
+  {
+  dlclose(local_scan_lib);
+  log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library doesn't contain "
+    "local_scan_version_major() function - message temporarily rejected");
+  return FALSE;
+  }
+
+/* The major number is increased when the ABI is changed in a non
+   backward compatible way. */
+vers_maj = local_scan_version_fn();
+
+local_scan_version_fn = dlsym(local_scan_lib, "local_scan_version_minor");
+if (!local_scan_version_fn)
+  {
+  dlclose(local_scan_lib);
+  log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library doesn't contain "
+    "local_scan_version_minor() function - message temporarily rejected");
+  return FALSE;
+  }
+
+/* The minor number is increased each time a new feature is added (in a
+   way that doesn't break backward compatibility) -- Marc */
+vers_min = local_scan_version_fn();
+
+
+if (vers_maj != LOCAL_SCAN_ABI_VERSION_MAJOR)
+  {
+  dlclose(local_scan_lib);
+  local_scan_lib = NULL;
+  log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() has an incompatible major"
+    "version number, you need to recompile your module for this version"
+    "of exim (The module was compiled for version %d.%d and this exim provides"
+    "ABI version %d.%d)", vers_maj, vers_min, LOCAL_SCAN_ABI_VERSION_MAJOR,
+    LOCAL_SCAN_ABI_VERSION_MINOR);
+  return FALSE;
+  }
+else if (vers_min > LOCAL_SCAN_ABI_VERSION_MINOR)
+  {
+  dlclose(local_scan_lib);
+  local_scan_lib = NULL;
+  log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() has an incompatible minor"
+    "version number, you need to recompile your module for this version"
+    "of exim (The module was compiled for version %d.%d and this exim provides"
+    "ABI version %d.%d)", vers_maj, vers_min, LOCAL_SCAN_ABI_VERSION_MAJOR,
+    LOCAL_SCAN_ABI_VERSION_MINOR);
+  return FALSE;
+  }
+
+local_scan_fn = dlsym(local_scan_lib, "local_scan");
+if (!local_scan_fn)
+  {
+  dlclose(local_scan_lib);
+  log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() library doesn't contain "
+    "local_scan() function - message temporarily rejected");
+  return FALSE;
+  }
+
+return TRUE;
 }
 
+#endif /* DLOPEN_LOCAL_SCAN */
+
+
 /* End of local_scan.c */
diff -aur exim-4.95.orig/src/readconf.c exim-4.95/src/readconf.c
--- exim-4.95.orig/src/readconf.c	2021-09-28 10:24:46.000000000 +0200
+++ exim-4.95/src/readconf.c	2021-09-29 08:20:03.682883647 +0200
@@ -215,6 +215,9 @@
   { "local_from_prefix",        opt_stringptr,   {&local_from_prefix} },
   { "local_from_suffix",        opt_stringptr,   {&local_from_suffix} },
   { "local_interfaces",         opt_stringptr,   {&local_interfaces} },
+#ifdef DLOPEN_LOCAL_SCAN
+  { "local_scan_path",          opt_stringptr,   {&local_scan_path} },
+#endif
 #ifdef HAVE_LOCAL_SCAN
   { "local_scan_timeout",       opt_time,        {&local_scan_timeout} },
 #endif
Only in exim-4.95/src: readconf.c.orig