]> git.pld-linux.org Git - packages/sendmail.git/blame - bluelabs-smpgsql-8.14.3.patch
- updated to 8.16.1 (includes security fix)
[packages/sendmail.git] / bluelabs-smpgsql-8.14.3.patch
CommitLineData
229843d7
JB
1diff -ruN sendmail-8.14.3/cf/feature/pg_accessdb.m4 sendmail-8.14.3.pgsql/cf/feature/pg_accessdb.m4
2--- sendmail-8.14.3/cf/feature/pg_accessdb.m4 1969-12-31 16:00:00.000000000 -0800
3+++ sendmail-8.14.3.pgsql/cf/feature/pg_accessdb.m4 2007-03-26 13:19:46.000000000 -0700
4@@ -0,0 +1,19 @@
5+divert(-1)
6+# By using this file, you agree to be cool and share your knowledge
7+#
8+# David, http://blue-labs.org/software/sm-pgsql/sendmail.php
9+#
10+
11+divert(0)
12+VERSIONID(`$Id: pg_accessdb.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $')
13+divert(-1)
14+
15+define(`_ACCESS_TABLE_', `')
16+define(`_PG_ACCESS_TABLE_', `')
17+define(`_TAG_DELIM_', `:')dnl should be in OperatorChars
18+
19+LOCAL_CONFIG
20+# PostgreSQL based access list
21+Kaccess ifelse(defn(`_ARG_'), `',
22+ DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`access',
23+ `_ARG_')
24diff -ruN sendmail-8.14.3/cf/feature/pg_aliases.m4 sendmail-8.14.3.pgsql/cf/feature/pg_aliases.m4
25--- sendmail-8.14.3/cf/feature/pg_aliases.m4 1969-12-31 16:00:00.000000000 -0800
26+++ sendmail-8.14.3.pgsql/cf/feature/pg_aliases.m4 2007-03-26 13:19:46.000000000 -0700
27@@ -0,0 +1,19 @@
28+divert(-1)
29+# By using this file, you agree to be cool and share your knowledge
30+#
31+# David, http://blue-labs.org/software/sm-pgsql/sendmail.php
32+#
33+
34+divert(0)
35+VERSIONID(`$Id: pg_aliases.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $')
36+divert(-1)
37+
38+undefine(`ALIAS_FILE')
39+define(`_ALIASES_TABLE_', `')
40+define(`_PG_ALIASES_TABLE_', `')
41+
42+LOCAL_CONFIG
43+# PostgreSQL based local aliases
44+Kaliases ifelse(defn(`_ARG_'), `',
45+ DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`aliases',
46+ `_ARG_')
47diff -ruN sendmail-8.14.3/cf/feature/pg_domaintable.m4 sendmail-8.14.3.pgsql/cf/feature/pg_domaintable.m4
48--- sendmail-8.14.3/cf/feature/pg_domaintable.m4 1969-12-31 16:00:00.000000000 -0800
49+++ sendmail-8.14.3.pgsql/cf/feature/pg_domaintable.m4 2007-03-26 13:19:46.000000000 -0700
50@@ -0,0 +1,18 @@
51+divert(-1)
52+# By using this file, you agree to be cool and share your knowledge
53+#
54+# David, http://blue-labs.org/software/sm-pgsql/sendmail.php
55+#
56+
57+divert(0)
58+VERSIONID(`$Id: pg_domaintable.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $')
59+divert(-1)
60+
61+define(`_DOMAIN_TABLE_', `')
62+define(`_PG_DOMAIN_TABLE', `')
63+
64+LOCAL_CONFIG
65+# PostgreSQL based domain rewriting table
66+Kdomaintable ifelse(defn(`_ARG_'), `',
67+ DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`domaintable',
68+ `_ARG_')
69diff -ruN sendmail-8.14.3/cf/feature/pg_generics.m4 sendmail-8.14.3.pgsql/cf/feature/pg_generics.m4
70--- sendmail-8.14.3/cf/feature/pg_generics.m4 1969-12-31 16:00:00.000000000 -0800
71+++ sendmail-8.14.3.pgsql/cf/feature/pg_generics.m4 2007-03-26 13:19:46.000000000 -0700
72@@ -0,0 +1,18 @@
73+divert(-1)
74+# By using this file, you agree to be cool and share your knowledge
75+#
76+# David, http://blue-labs.org/software/sm-pgsql/sendmail.php
77+#
78+
79+divert(0)
80+VERSIONID(`$Id: pg_genericstable.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $')
81+divert(-1)
82+
83+define(`_GENERICS_TABLE_', `')
84+define(`_PG_GENERICS_TABLE', `')
85+
86+LOCAL_CONFIG
87+# PostgreSQL based generic domain mapping table, similar to userdb
88+Kgenerics ifelse(defn(`_ARG_'), `',
89+ DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`generics',
90+ `_ARG_')
91diff -ruN sendmail-8.14.3/cf/feature/pg_mailer.m4 sendmail-8.14.3.pgsql/cf/feature/pg_mailer.m4
92--- sendmail-8.14.3/cf/feature/pg_mailer.m4 1969-12-31 16:00:00.000000000 -0800
93+++ sendmail-8.14.3.pgsql/cf/feature/pg_mailer.m4 2007-03-26 13:19:46.000000000 -0700
94@@ -0,0 +1,18 @@
95+divert(-1)
96+# By using this file, you agree to be cool and share your knowledge
97+#
98+# David, http://blue-labs.org/software/sm-pgsql/sendmail.php
99+#
100+
101+divert(0)
102+VERSIONID(`$Id: pg_mailertable.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $')
103+divert(-1)
104+
105+define(`_MAILER_TABLE_', `')
106+define(`_PG_MAILER_TABLE', `')
107+
108+LOCAL_CONFIG
109+# PostgreSQL based mailer table, for overriding domain and MX
110+Kmailertable ifelse(defn(`_ARG_'), `',
111+ DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`mailertable',
112+ `_ARG_')
113diff -ruN sendmail-8.14.3/cf/feature/pg_usersdb.m4 sendmail-8.14.3.pgsql/cf/feature/pg_usersdb.m4
114--- sendmail-8.14.3/cf/feature/pg_usersdb.m4 1969-12-31 16:00:00.000000000 -0800
115+++ sendmail-8.14.3.pgsql/cf/feature/pg_usersdb.m4 2007-03-26 13:19:46.000000000 -0700
116@@ -0,0 +1,18 @@
117+divert(-1)
118+# By using this file, you agree to be cool and share your knowledge
119+#
120+# David, http://blue-labs.org/software/sm-pgsql/sendmail.php
121+#
122+
123+divert(0)
124+VERSIONID(`$Id: pg_usersdb.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $')
125+divert(-1)
126+
127+define(`_REWRITE_TABLE_', `')
128+define(`_PG_REWRITE_TABLE_', `')
129+
130+LOCAL_CONFIG
131+# PostgreSQL based user rewrite table (can turn "John.Doe" into "jdoe")
132+Kusersdb ifelse(defn(`_ARG_'), `',
133+ DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`usersdb',
134+ `_ARG_')
135diff -ruN sendmail-8.14.3/cf/feature/pg_virtualusers.m4 sendmail-8.14.3.pgsql/cf/feature/pg_virtualusers.m4
136--- sendmail-8.14.3/cf/feature/pg_virtualusers.m4 1969-12-31 16:00:00.000000000 -0800
137+++ sendmail-8.14.3.pgsql/cf/feature/pg_virtualusers.m4 2007-03-26 13:19:46.000000000 -0700
138@@ -0,0 +1,18 @@
139+divert(-1)
140+# By using this file, you agree to be cool and share your knowledge
141+#
142+# David, http://blue-labs.org/software/sm-pgsql/sendmail.php
143+#
144+
145+divert(0)
146+VERSIONID(`$Id: pg_virtusertable.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $')
147+divert(-1)
148+
149+define(`_VIRTUSER_TABLE_', `')
150+define(`_PG_VIRTUSER_TABLE_', `')
151+
152+LOCAL_CONFIG
153+# PostgreSQL based virtual user table (maps incoming users)
154+Kvirtuser ifelse(defn(`_ARG_'), `',
155+ DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`virtusertable',
156+ `_ARG_')
157diff -ruN sendmail-8.14.3/pgsql-build.mc sendmail-8.14.3.pgsql/pgsql-build.mc
158--- sendmail-8.14.3/pgsql-build.mc 1969-12-31 16:00:00.000000000 -0800
159+++ sendmail-8.14.3.pgsql/pgsql-build.mc 2007-03-26 13:19:46.000000000 -0700
160@@ -0,0 +1,32 @@
161+######################################################################
162+# This is the Blue Labs m4 file for the Sendmail w/ Postgres Tables patch.
163+#
164+# The website for building sendmail with this patch is at
165+# http://blue-labs.org/software/sm-pgsql/sendmail.php
166+#
167+# This patch may eventually be available to Gentoo (http://gentoo.org/)
168+# users with the "USE=postgres" use flag
169+#
170+# !!! EDIT THE CONFIGURATION SETTINGS TO MATCH YOUR NEEDS !!!
171+#
172+# NOTE: This is a specialised .cf for the postgresql patch only
173+#
174+VERSIONID(`(#) Blue Labs bluelabs.mc v 11.1 (Blue Labs) 12 Jan 2007')
175+######################################################################
176+
177+##
178+# See http://blue-labs.org/software/sm-pgsql/sendmail.php for detailed
179+# instructions
180+#
181+# TODO: replace 'newaliases' and 'makemap' targets with "don't run this"
182+# update man pages also
183+##
184+
185+# uncomment these two lines if you use /usr/local/pgsql
186+# APPENDDEF(`confINCDIRS',`-I/usr/local/pgsql/include')dnl
187+# APPENDDEF(`confLIBDIRS',`-L/usr/local/pgsql/lib')dnl
188+
189+APPENDDEF(`confLIBS',`-lpq')dnl
190+APPENDDEF(`confMAPDEF',`-DPGSQLMAP')dnl
191+APPENDDEF(`DATABASE_MAP_TYPE', `pgsql')dnl
192+
193diff -ruN sendmail-8.14.3/pgsql-config.mc sendmail-8.14.3.pgsql/pgsql-config.mc
194--- sendmail-8.14.3/pgsql-config.mc 1969-12-31 16:00:00.000000000 -0800
195+++ sendmail-8.14.3.pgsql/pgsql-config.mc 2007-03-26 13:19:46.000000000 -0700
196@@ -0,0 +1,51 @@
197+######################################################################
198+# This is the Blue Labs m4 file for the Sendmail w/ Postgres Tables patch.
199+#
200+# The website for building sendmail with this patch is at
201+# http://blue-labs.org/software/sm-pgsql/sendmail.php
202+#
203+# This patch may eventually be available to Gentoo (http://gentoo.org/)
204+# users with the "USE=postgres" use flag
205+#
206+# !!! EDIT THE CONFIGURATION SETTINGS TO MATCH YOUR NEEDS !!!
207+#
208+# NOTE: This is a specialised .cf for the postgresql patch only
209+#
210+VERSIONID(`(#) Blue Labs bluelabs.mc v 12.0 (Blue Labs) 12 Dec 2007')
211+######################################################################
212+
213+##
214+# See http://blue-labs.org/software/sm-pgsql/sendmail.php for detailed
215+# instructions
216+##
217+
218+dnl ##
219+dnl # example line:
220+dnl # pgsql [-h <pgsql server>] -c <connection string> -s <query string>
221+dnl ##
222+
223+#
224+# PgSql
225+#
226+# add the flag -f to force case sensitive queries, by default both the
227+# search and the value will be folded to lower case. by default %s will be
228+# rewritten to by lower('%s'). if -f is specified, then it will only be
229+# written as ('%s') and both the input value and the row value MUST match
230+# case exactly.
231+#
232+
233+define(`PG_CONNSTR', "host=localhost dbname=sendmail user=sendmail password=raisins")
234+define(`SELECT', "select distinct s_out from )
235+define(`WHERE', where ``lower'' (s_in) = %s")
236+FEATURE(`pg_aliases', pgsql -c `PG_CONNSTR' -s `SELECT' `aliases' `WHERE')dnl
237+FEATURE(`pg_virtualusers', pgsql -c `PG_CONNSTR' -s `SELECT' `virtualusers' `WHERE')dnl
238+FEATURE(`pg_usersdb', pgsql -c `PG_CONNSTR' -s `SELECT' `userrewrite' `WHERE')dnl
239+FEATURE(`pg_accessdb', pgsql -c `PG_CONNSTR' -s `SELECT' `access' `WHERE')dnl
240+FEATURE(`pg_domaintable', pgsql -c `PG_CONNSTR' -s `SELECT' `domaintable' `WHERE')dnl
241+FEATURE(`pg_generics', pgsql -c `PG_CONNSTR' -s `SELECT' `genericstable' `WHERE')dnl
242+FEATURE(`pg_mailer', pgsql -c `PG_CONNSTR' -s `SELECT' `mailertable' `WHERE')dnl
243+
244+define(`confPROCESS_TITLE_PREFIX', `[Blue-PgSQL]')dnl
245+define(`confSMTP_LOGIN_MSG', `Mail server\
246+ \
247+ Unauthorized use prohibited\
248+ \
249+ Spam is prohibited here and any detected spam may be used in prosecution\
250+ against the spammer. This setup uses PgSQL (postgresql) for most of it''`s\
251+ tables, for information on this, see\
252+ http://blue-labs.org/software/sm-pgsql/sendmail.php\
253+ Don''`t bitch if your MTA is busted and doesn''`t play well with others.\
254+ \
255+')dnl
256+
257+dnl # Don't attempt to rebuild an aliases file, sm-pgsql doesn't use files
258+dnl # however if you have multiple alias tables and DO use files, remove this
259+dnl # next line
260+define(`confALIAS_WAIT', `0')dnl
261diff -ruN sendmail-8.14.3/sendmail/README sendmail-8.14.3.pgsql/sendmail/README
262--- sendmail-8.14.3/sendmail/README 2006-11-13 14:27:27.000000000 -0800
263+++ sendmail-8.14.3.pgsql/sendmail/README 2007-03-26 13:19:46.000000000 -0700
264@@ -119,6 +119,11 @@
265 have to install the UMich or OpenLDAP
266 (http://www.openldap.org/) ldap and lber libraries to use
267 this flag.
268+PGSQLMAP PostgreSQL SQL query support. You will need to have
269+ PostgreSQL include files and libraries installed to use this
270+ feature. Information on PostgreSQL can be found at
271+ http://www.postgresql.org/ Support for this map may be
272+ found at http://blue-labs.org/software/sm-pgsql/sendmail.php
273 MAP_REGEX Regular Expression support. You will need to use an
274 operating system which comes with the POSIX regex()
275 routines or install a regexp library such as libregex from
276--- sendmail-8.16.1/sendmail/conf.c.orig 2020-06-04 08:27:49.000000000 +0200
277+++ sendmail-8.16.1/sendmail/conf.c 2020-08-29 10:15:17.896341069 +0200
278@@ -576,6 +576,12 @@
279 ldapmap_lookup, null_map_store);
280 #endif
281
282+#ifdef PGSQLMAP
283+ MAPDEF("pgsql", NULL, MCF_ALIASOK|MCF_NOTPERSIST,
284+ pgsql_map_parseargs, pgsql_map_open, pgsql_map_close,
285+ pgsql_map_lookup, null_map_store);
286+#endif
287+
288 #if PH_MAP
289 MAPDEF("ph", NULL, MCF_NOTPERSIST,
290 ph_map_parseargs, ph_map_open, ph_map_close,
291@@ -5864,6 +5870,9 @@
292 #if LDAP_REFERRALS
293 "LDAP_REFERRALS",
294 #endif
295+#if PGSQLMAP
296+ "PGSQLMAP",
297+#endif /* PGSQLMAP */
298 #if LOG
299 "LOG",
300 #endif
301--- sendmail-8.14.3/sendmail/map.c 2007-10-09 20:06:45.000000000 -0400
302+++ sendmail-8.14.3.pgsql/sendmail/map.c 2009-11-09 19:54:47.214965897 -0500
303@@ -4706,6 +4706,588 @@
304 }
305 }
306 #endif /* LDAPMAP */
307+
308+#ifdef PGSQLMAP
309+#include <libpq-fe.h>
310+
311+/*
312+ * PostgreSQL map functionality for Sendmail 8.14.3
313+ * Portions Copyright (C) 2000 Jonathan Yarden <jyarden@bluegrass.net>
314+ * Remainder copyright (c) 2000-2009 David Ford <david@blue-labs.org>
315+ *
316+ * For information on PostgreSQL, visit http://www.pgsql.com/
317+ * Information on this patch and setup is at
318+ * http://blue-labs.org/software/sm-pgsql/sendmail.php
319+ *
320+ * This patch, because it integrates with and is based on the existing
321+ * prior work of Sendmail, is considered by me to be a "derivative
322+ * work" subject to the Sendmail licensing terms. Sendmail, Inc. in not
323+ * responsible for this code.
324+ *
325+ * USE AT YOUR OWN RISK. NO WARRANTY OF ANY KIND IS PROVIDED. PLEASE
326+ * READ THE INSTRUCTIONS FOR USE OF THIS PATCH BEFORE CONTACTING THE
327+ * AUTHOR OR SENDMAIL, INC. NO SUPPORT OF ANY KIND WILL BE PROVIDED
328+ * BY SENDMAIL, INC. FOR THIS PATCH.
329+ */
330+
331+/*
332+struct pgsqlmap
333+{
334+ struct pgsqlmap *p,*n;
335+ char *connstr;
336+ PGconn *conn;
337+ pid_t opener_pid;
338+ char *mapname;
339+} *pgsqlmap = NULL; */
340+
341+char *pgsql_skip_quotes(char *p)
342+{
343+ p = strchr(p,'"');
344+ if (p)
345+ {
346+ p++;
347+ p = strchr(p,'"');
348+ if (p) p++;
349+ }
350+ return p;
351+}
352+
353+/*
354+ * Parse PostgreSQL map definition args.
355+ *
356+ * Nothing really special here, since to be perfectly honest, I have never
357+ * seen or used almost all of these options. Most of this code was taken
358+ * directly from existing Sendmail source code.
359+ */
360+bool pgsql_map_parseargs(MAP *map, char *args)
361+{
362+ register char *p = args;
363+ register int done;
364+
365+ map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL;
366+ for (;;)
367+ {
368+ while (isascii(*p) && isspace(*p))
369+ p++;
370+ if (*p != '-')
371+ break;
372+ switch (*++p)
373+ {
374+ case 'A':
375+ map->map_mflags |= MF_APPEND;
376+ break;
377+
378+ case 'N':
379+ map->map_mflags |= MF_INCLNULL;
380+ map->map_mflags &= ~MF_TRY0NULL;
381+ break;
382+
383+ case 'O':
384+ map->map_mflags &= ~MF_TRY1NULL;
385+ break;
386+
387+ case 'T':
388+ map->map_tapp = ++p;
389+ break;
390+
391+ case 'a':
392+ map->map_app = ++p;
393+ break;
394+
395+ case 'f':
396+ map->map_mflags |= MF_NOFOLDCASE;
397+ break;
398+
399+ case 'h':
400+ map->map_db2 = ++p;
401+ break;
402+
403+ case 'm':
404+ map->map_mflags |= MF_MATCHONLY;
405+ break;
406+
407+ case 'o':
408+ map->map_mflags |= MF_OPTIONAL;
409+ break;
410+
411+ case 'q':
412+ map->map_mflags |= MF_KEEPQUOTES;
413+ break;
414+
415+ case 't':
416+ map->map_mflags |= MF_NODEFER;
417+ break;
418+
419+/*
420+ * Start of PostgreSQL specific args. I cheat and use some existing
421+ * Sendmail variables here since this map class makes no other use of them.
422+ */
423+
424+ case 'c': /* connection string */
425+ map->map_keycolnm = ++p;
426+ p = pgsql_skip_quotes(p);
427+ break;
428+
429+ case 's': /* select statement */
430+ map->map_valcolnm = ++p;
431+ p = pgsql_skip_quotes(p);
432+ break;
433+ }
434+
435+ if (*p != '\0')
436+ *p++ = '\0';
437+ }
438+
439+ if (map->map_app != NULL)
440+ map->map_app = newstr(map->map_app);
441+
442+ if (map->map_tapp != NULL)
443+ map->map_tapp = newstr(map->map_tapp);
444+
445+ if (map->map_keycolnm != NULL) { /* database connect string */
446+ map->map_keycolnm = newstr(map->map_keycolnm);
447+ stripquotes(map->map_keycolnm);
448+ p = map->map_keycolnm;
449+ while(*p==' ')
450+ p++;
451+ map->map_keycolnm = p;
452+ } else {
453+ sm_syslog(LOG_WARNING, CurEnv->e_id, "No PostgreSQL connect string for %s map %s",
454+ map->map_class->map_cname, map->map_mname);
455+ syserr("451 4.3.5 No PostgreSQL connect string for map %s",
456+ map->map_mname);
457+ SM_SET_H_ERRNO(TRY_AGAIN);
458+ errno = DB_NOTFOUND;
459+ return false;
460+ }
461+
462+ if (map->map_valcolnm != NULL) { /* select statement */
463+ map->map_valcolnm = newstr(map->map_valcolnm);
464+ stripquotes(map->map_valcolnm);
465+ p = map->map_valcolnm;
466+ while(*p==' ')
467+ p++;
468+ map->map_valcolnm = p;
469+ } else {
470+ sm_syslog(LOG_WARNING, CurEnv->e_id, "No PostgreSQL select statement for %s map %s",
471+ map->map_class->map_cname, map->map_mname);
472+ syserr("451 5.3.5 No PostgreSQL select statement for map %s",
473+ map->map_mname);
474+ SM_SET_H_ERRNO(TRY_AGAIN);
475+ errno = DB_NOTFOUND;
476+ return false;
477+ }
478+
479+ return true;
480+}
481+
482+#if 0
483+/*
484+ * search our list of map connections for a entry that matches our
485+ * connection. it should have the same host and connection string, as well
486+ * as the same PID. someone can choose to put their maps on different
487+ * databases, so we cannot share a connection.
488+ */
489+
490+PGconn *pgsql_getconn(char *connstr, char *mapname)
491+{
492+ pid_t p = getpid();
493+
494+ // if no map has been allocated, return immediately
495+ if(!pgsqlmap) return NULL;
496+
497+ // rewind
498+ while(pgsqlmap->p) pgsqlmap = pgsqlmap->p;
499+
500+ #ifdef PGSQLDEBUG
501+ sm_syslog(LOG_INFO, CurEnv->e_id, "pgsql_getconn (connection string:%s, pid:%i)", connstr, p);
502+ #endif
503+
504+ // only return connections that match everything
505+ do
506+ {
507+ if(pgsqlmap->conn)
508+ if (!strncmp(connstr, pgsqlmap->connstr, strlen(connstr)+1))
509+ if (pgsqlmap->opener_pid == p)
510+ if (!strncmp(pgsqlmap->mapname, mapname, strlen(mapname))
511+ return pgsqlmap->conn;
512+
513+ // if there is more than one map and we're still searching, bump to the next one
514+ if (pgsqlmap->n)
515+ pgsqlmap = pgsqlmap->n;
516+ else
517+ break;
518+ } while(1);
519+
520+ return NULL;
521+}
522+
523+/*
524+ * add a new map entry structure and populate it
525+ */
526+void pgsql_addconn(char *host, char *connstr, PGconn *conn, mapname)
527+{
528+ int count=1;
529+
530+ if (!pgsqlmap)
531+ // create a brand new map structure
532+ pgsqlmap= (struct pgsqlmap *) xalloc(sizeof(struct pgsqlmap));
533+
534+ else
535+ {
536+ // fast-forward to the end of the list
537+ while(pgsqlmap->n)
538+ {
539+ count++;
540+ pgsqlmap = pgsqlmap->n;
541+ }
542+
543+ pgsqlmap->n = (struct pgsqlmap *) xalloc(sizeof(struct pgsqlmap));
544+ pgsqlmap->n->p = pgsqlmap;
545+ pgsqlmap = pgsqlmap->n;
546+ }
547+
548+ bzero(pgsqlmap, sizeof(struct pgsqlmap));
549+ pgsqlmap->connstr =connstr;
550+ pgsqlmap->conn =conn;
551+ pgsqlmap->opener_pid =getpid();
552+ pgsqlmap->mapname =mapname;
553+
554+ #ifdef PGSQLDEBUG
555+ sm_syslog(LOG_INFO, CurEnv->e_id, "pgsql_ add map connection (connection string:%s, connptr:%p, pid:%i), maplist size is %i",
556+ pgsqlmap->connstr, pgsqlmap->conn, pgsqlmap->opener_pid, count);
557+ #endif
558+}
559+
560+int psql_removeconn(PGconn *conn, char *mapname)
561+{
562+ if(!pgsqlmap) return 0;
563+
564+ while(pgsqlmap->p) pgsqlmap = pgsqlmap->p;
565+
566+ do
567+ {
568+ if (pgsqlmap->conn == conn && !strncmp(pgsqlmap->mapname, mapname, strlen(mapname))
569+ {
570+ // the map data doesn't belong to us, just deallocate the map pointer
571+ struct pgsqlmap *z = pgsqlmap;
572+
573+ #ifdef PGSQLDEBUG
574+ sm_syslog(LOG_INFO, CurEnv->e_id, "pgsql_ delete map connection (connection string:%s, connptr:%p, pid:%i)",
575+ pgsqlmap->connstr, pgsqlmap->conn, pgsqlmap->opener_pid);
576+ #endif
577+
578+ if (z->p && z->n)
579+ {
580+ z->p->n = z->n;
581+ z->n->p = z->p;
582+ free(z);
583+ pgsqlmap = pgsqlmap->n;
584+ return 1;
585+ }
586+
587+ else if (z->p)
588+ {
589+ z->p->n = NULL;
590+ free(z);
591+ pgsqlmap = pgsqlmap->p;
592+ return 1;
593+ }
594+
595+ else if (z->n)
596+ {
597+ z->n->p = NULL;
598+ free(z);
599+ pgsqlmap = pgsqlmap->n;
600+ return 1;
601+ }
602+
603+ // only return 1 if no map references are left so the pgsql connection can be shut down
604+ else
605+ {
606+ free(z);
607+ pgsqlmap = NULL;
608+ return 1;
609+ }
610+
611+ }
612+
613+ if (pgsqlmap->n)
614+ pgsqlmap = pgsqlmap->n;
615+ else
616+ break;
617+ } while(1);
618+
619+ // no maps found
620+ return 0;
621+}
622+#endif
623+
624+/*
625+ * Open a PostgreSQL database connection using the connection string, the
626+ * mode parameter is entirely ignored - it has no purpose in SQL.
627+ *
628+ * Returns TRUE if the database was opened or FALSE if it choked
629+ */
630+bool pgsql_map_open(MAP *map, int mode)
631+{
632+ char *s= NULL;
633+ int n, retries;
634+
635+ /*
636+ * each map can have a different connection, so we can't easily share
637+ * it. further, each connection is protected between thread instances.
638+ */
639+
640+ /*
641+ * this is the most likely test so it comes first. we have a connection
642+ * to the server, if the status appears good, return. note: the status
643+ * may be misleading, the server may have crashed underneath us or
644+ * terminated our connection for any of several reasons. we won't know
645+ * that until we actually use it however.
646+ */
647+ if (map->map_db1 && PQstatus(map->map_db1) == CONNECTION_OK)
648+ {
649+ // the connection is shared between all maps, we don't need to differentiate
650+ #ifdef PGSQLDEBUG
651+ sm_syslog(LOG_INFO, CurEnv->e_id, "Connection is good (connection string:%s, connptr:%p)",
652+ map->map_keycolnm, map->map_db1);
653+ #endif
654+
655+ return true;
656+ }
657+
658+ #ifdef PGSQLDEBUG
659+ if (!map->map_db1 || PQstatus(map->map_db1) == CONNECTION_BAD)
660+ sm_syslog(LOG_INFO, CurEnv->e_id, "Connection to SQL server not found or stale for map:%s, looking for a new one", map->map_mname);
661+ #endif
662+
663+ retries=10;
664+ while ((!map->map_db1 || PQstatus(map->map_db1) == CONNECTION_BAD) && retries-- >0)
665+ {
666+ /*
667+ * now either conn is still null (not yet allocated), or our connection
668+ * is bad. synchronous connections only have _OK or _BAD. looks like
669+ * we have to reset or make a new connection. allocate space and try to
670+ * connect
671+ */
672+ if (!map->map_db1)
673+ {
674+ map->map_db1 = PQconnectdb(map->map_keycolnm);
675+ PQsetErrorVerbosity(map->map_db1, PQERRORS_VERBOSE);
676+ //pgsql_addconn(map->map_keycolnm, map->map_db1, map->map_mname);
677+ map->map_pid = getpid(); /* save PID for check on close */
678+ }
679+
680+ else
681+ PQreset(map->map_db1);
682+
683+ if (!map->map_db1)
684+ {
685+ sm_syslog(LOG_WARNING, CurEnv->e_id, "Cannot open %s map %s using %s, attempt %i",
686+ map->map_class->map_cname, map->map_mname, map->map_keycolnm, 10-retries);
687+ }
688+
689+ if (PQstatus(map->map_db1) == CONNECTION_BAD)
690+ {
691+ sm_syslog(LOG_WARNING, CurEnv->e_id, "Cannot open %s map %s using %s (%s), attempt %i",
692+ map->map_class->map_cname, map->map_mname, map->map_keycolnm,
693+ PQerrorMessage(map->map_db1), 10-retries);
694+ }
695+ }
696+
697+ if (!map->map_db1 || PQstatus(map->map_db1) == CONNECTION_BAD)
698+ {
699+ syserr("451 4.3.5 Map database unreachable");
700+ if (map->map_db1)
701+ {
702+ //psql_removeconn(conn, map->map_mname);
703+ PQfinish(map->map_db1);
704+ map->map_db1 = NULL;
705+ }
706+
707+ errno = DB_NOTFOUND;
708+ SM_SET_H_ERRNO(TRY_AGAIN);
709+
710+ return false;
711+ }
712+
713+ return true;
714+}
715+
716+/*
717+ * Close the PostgreSQL database connection, check that the opening process
718+ * is the closing process; ignore if not.
719+ */
720+void pgsql_map_close(MAP *map)
721+{
722+ int r;
723+
724+ if (map->map_pid == getpid())
725+ {
726+ //conn = map->map_db1;
727+/*
728+ r = psql_removeconn(conn, map->map_mname);
729+ if(r)
730+ {
731+*/ PQfinish(map->map_db1);
732+ map->map_db1 = NULL;
733+ #ifdef PGSQLDEBUG
734+ sm_syslog(LOG_INFO, CurEnv->e_id, "Closed connection for map %s", map->map_mname);
735+ #endif
736+/* }
737+
738+ #ifdef PGSQLDEBUG
739+ else
740+ sm_syslog(LOG_INFO, CurEnv->e_id, "No connection found for map: %s", map->map_mname);
741+ #endif
742+*/ }
743+}
744+
745+/*
746+** PGSQL_MAP_LOOKUP -- look up a datum in a PGSQL map
747+**
748+** Attempt to map an incoming key value with a PostgreSQL query.
749+**
750+** This performs the query specified in the Sendmail config file and
751+** uses the value of the first row and column as the map data value.
752+** All other rows and columns are ignored.
753+*/
754+char *
755+pgsql_map_lookup(MAP *map, char *name, char **av, int *statp)
756+{
757+ int len,esc_len,ntuples,r,retries;
758+ char *format,*workingbuf,*trustedbuf;
759+ char sname[MAXNAME+1];
760+ char resbuf[MAXNAME+1];
761+ PGresult *res;
762+
763+ /*
764+ * Check the backend to make sure it's still valid. If it's not, try and
765+ * reset the connection.
766+ */
767+ if (!map->map_db1 || PQstatus(map->map_db1) == CONNECTION_BAD)
768+ {
769+ #ifdef PGSQLDEBUG
770+ sm_syslog(LOG_INFO, NOQID, "Connection bad for map: %s, reconnecting to SQL server using: %s", map->map_mname, map->map_keycolnm);
771+ #endif
772+ if (!pgsql_map_open(map, 0))
773+ {
774+ #ifdef PGSQLDEBUG
775+ sm_syslog(LOG_INFO, CurEnv->e_id, "dbg> aborting map lookup");
776+ #endif
777+ return NULL;
778+ }
779+ }
780+
781+ bzero(sname,sizeof sname);
782+ bzero(resbuf,sizeof resbuf);
783+
784+ /* Buffer overflow check. */
785+ len = strlen(name);
786+ if (len > MAXNAME)
787+ len = MAXNAME;
788+ bcopy(name,sname,len);
789+
790+ if (!bitset(MF_NOFOLDCASE, map->map_mflags))
791+ {
792+ //#ifdef PGSQLDEBUG
793+ //sm_syslog(LOG_INFO, CurEnv->e_id, "dbg> making querystring value lowercase");
794+ //#endif
795+ makelower(sname);
796+ }
797+
798+ /* Allocate query buffer (select statement + key value) */
799+ len = strlen(map->map_valcolnm);
800+ esc_len = strlen(sname);
801+ workingbuf = xalloc(esc_len*2+1+9);
802+ trustedbuf = xalloc(len+(esc_len*2)+1+9);
803+ bzero(trustedbuf,len);
804+
805+ // escape untrusted data passed to us from network
806+ PQescapeStringConn(map->map_db1, trustedbuf, sname, strlen(sname), NULL);
807+
808+ // if MF_NOFOLDCASE is set, don't wrap this in lower()
809+ if (!bitset(MF_NOFOLDCASE, map->map_mflags))
810+ format="lower('%s')";
811+ else
812+ format="'%s'";
813+
814+ sprintf(workingbuf, format, trustedbuf);
815+ sprintf(trustedbuf, map->map_valcolnm, workingbuf);
816+ free(workingbuf);
817+
818+ #ifdef PGSQLDEBUG
819+ sm_syslog(LOG_INFO, CurEnv->e_id, "dbg-sql> %s", trustedbuf);
820+ #endif
821+
822+ retries = 2;
823+ while (retries--)
824+ {
825+ res = PQexec(map->map_db1, trustedbuf);
826+ if (PQresultStatus(res) == PGRES_TUPLES_OK)
827+ break;
828+
829+ sm_syslog(LOG_WARNING, CurEnv->e_id, "Cannot query PGSQL database (attempt:%i) \"%s\" using \"%s\" because of: %s",
830+ 10-retries, map->map_keycolnm, trustedbuf, PQresultErrorMessage(res));
831+ PQclear(res);
832+
833+ // try to reset connection
834+ if (!pgsql_map_open(map, 0))
835+ {
836+ #ifdef PGSQLDEBUG
837+ sm_syslog(LOG_INFO, CurEnv->e_id, "dbg> aborting map lookup");
838+ #endif
839+ return NULL;
840+ }
841+ }
842+
843+ if (!map->map_db1 || PQresultStatus(res) != PGRES_TUPLES_OK)
844+ {
845+ syserr("451 4.3.1 Cannot query PGSQL database");
846+ SM_SET_H_ERRNO(TRY_AGAIN);
847+ errno = DB_NOTFOUND;
848+ free(trustedbuf);
849+ return NULL;
850+ }
851+
852+ /*
853+ * See if anything came back. If no rows were returned, nothing there for
854+ * this query.
855+ */
856+ ntuples = PQntuples(res);
857+ #ifdef PGSQLDEBUG
858+ sm_syslog(LOG_INFO, CurEnv->e_id, "dbg> finishing map lookup, ntuples:%i", ntuples);
859+ #endif
860+
861+ if (ntuples <= 0)
862+ {
863+ PQclear(res);
864+ return NULL;
865+ }
866+
867+ /*
868+ * Get the result from column 0 and clear the rest of the result.
869+ * If the result data is too big, then it's truncated.
870+ */
871+ len = PQgetlength(res,0,0);
872+ if (len > MAXNAME)
873+ len = MAXNAME;
874+ bcopy(PQgetvalue(res,0,0),resbuf,len);
875+ PQclear(res);
876+
877+ /* Process results like the other map classes do. */
878+
879+ #ifdef PGSQLDEBUG
880+ sm_syslog(LOG_INFO, CurEnv->e_id, "dbg> finishing map lookup, result:\"%s\"", resbuf);
881+ #endif
882+
883+ if (bitset(MF_MATCHONLY, map->map_mflags))
884+ return map_rewrite(map, name, strlen(name), NULL);
885+ else
886+ return map_rewrite(map, resbuf, len, av);
887+}
888+#endif /* PGSQLMAP */
889 /*
890 ** PH map
891 */
This page took 0.157302 seconds and 4 git commands to generate.