1 /* milter-callback - a sendmail milter to perform variuos sender verifications
2 Copyright (C) 2008 Eugene M. Zheganin, milter-callback@norma.perm.ru
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #ifdef WITH_PGSQL
19 #include <milter-callback.h>
20 #include <commonprocs.h>
21
22 extern char myHostName[MAXHOSTNAME];
23 struct connList connPool;
24
25 int
pushHistory(struct mlfiPriv * privData,char * action,char * formattedEmail)26 pushHistory(struct mlfiPriv *privData, char *action, char *formattedEmail){
27 #ifdef WITH_SPF
28 char *pgStatFormat = "insert into history (connectdate, connectfrom, helofrom, relaypresip, mxnum, mxesthatreject, mxesthataccept, mxesoutoforder, mxesthattempfail, gracefuldns, whitelisted, resolvedrelayip, receivinghost, envfrom, action, spf, reverserelay, fakerelay) values('%s','%s','%s','%s',%d,%d,%d,%d,%d,%s,%s,'%s','%s','%s', '%s',%d,%d,%d)";
29 #else
30 char *pgStatFormat = "insert into history (connectdate, connectfrom, helofrom, relaypresip, mxnum, mxesthatreject, mxesthataccept, mxesoutoforder, mxesthattempfail, gracefuldns, whitelisted, resolvedrelayip, receivinghost, envfrom, action, reverserelay, fakerelay) values('%s','%s','%s','%s',%d,%d,%d,%d,%d,%s,%s,'%s','%s','%s', '%s',%d,%d)";
31 #endif
32 char *pgStat = NULL;
33 int wantedSize = 0;
34 int wantedTimeSize = 0;
35 char *curTimePres = NULL;
36 char *curTimePresFormat = "%.2d/%.2d/%d %.2d:%.2d:%.2d";
37 int curYear, curMonth;
38 time_t now;
39 char whitelistedBool[6];
40 char gracefulDNSBool[6];
41 int pgConnId;
42 struct tm *curTime;
43 char tmpLog[MAXLOGLINE];
44
45 void
46 intToStrBool (int intBool, char *boolContainer, int boolContainerSize, struct mlfiPriv *privData) {
47 logNow("Entered intToStrBool().", 3, privData);
48 bzero(boolContainer, boolContainerSize);
49 if (intBool == 1) {
50 strncpy(boolContainer, "true", boolContainerSize);
51 } else {
52 strncpy(boolContainer, "false", boolContainerSize);
53 }
54 }
55
56 logNow("Entered pushHistory().", 3, privData);
57
58 pgConnId = getPgConn();
59
60 now = time(NULL);
61 curTime = localtime(&now);
62 curYear = curTime->tm_year + 1900;
63 curMonth = curTime->tm_mon + 1;
64 wantedTimeSize = snprintf(curTimePres, 0, curTimePresFormat,
65 curMonth, curTime->tm_mday, curYear,
66 curTime->tm_hour, curTime->tm_min, curTime->tm_sec);
67 wantedTimeSize++;
68 curTimePres = malloc(wantedTimeSize);
69 if (curTimePres == NULL) {
70 logNow("Cannot allocate memory.", 0, privData);
71 exit(EXIT_FAILURE);
72 }
73 bzero(curTimePres, wantedTimeSize);
74 snprintf(curTimePres, wantedTimeSize, curTimePresFormat,
75 curMonth, curTime->tm_mday, curYear,
76 curTime->tm_hour, curTime->tm_min, curTime->tm_sec);
77 snprintf(tmpLog, MAXLOGLINE, "Aquired current date, %s.", curTimePres);
78 logNow(&tmpLog[0], 3, privData);
79 logNow("Trying to get the size needed for DML statement.", 3, privData);
80 snprintf(tmpLog, MAXLOGLINE, "Sample of milter data [connectfrom]: \"%s\".", privData->mcfi_connectfrom);
81 logNow(&tmpLog[0], 3, privData);
82 snprintf(tmpLog, MAXLOGLINE, "Sample of milter data [helofrom]: \"%s\".", privData->mcfi_helofrom);
83 logNow(&tmpLog[0], 3, privData);
84 intToStrBool(privData->whitelisted, &whitelistedBool[0], 6, privData);
85 intToStrBool(privData->gracefulDNS, &gracefulDNSBool[0], 6, privData);
86 wantedSize = snprintf(pgStat, 0, pgStatFormat,
87 curTimePres, privData->mcfi_connectfrom,
88 privData->mcfi_helofrom, privData -> af == AF_INET ? privData->relayPresIP : privData->relayPresIP6,
89 privData->MXesNum, privData->MXesThatReject, privData->MXesThatAccept,
90 privData->MXesOutOfOrder, privData->MXesThatTempfail, gracefulDNSBool,
91 #ifdef WITH_SPF
92 whitelistedBool, privData->resolvedRelayIP, myHostName, formattedEmail, action, privData -> SPFResult, privData -> reverseRes, privData -> fakeRes);
93 #else
94 whitelistedBool, privData->resolvedRelayIP, myHostName, formattedEmail, action, privData -> reverseRes, privData -> fakeRes);
95 #endif
96 wantedSize++;
97 snprintf(tmpLog, MAXLOGLINE, "Got the size needed for DML statement, it's %d.", wantedSize);
98 logNow(&tmpLog[0], 3, privData);
99 pgStat = malloc(wantedSize);
100 bzero(pgStat, wantedSize);
101 if (pgStat == NULL) {
102 logNow("Cannot allocate memory.", 0, privData);
103 exit(EXIT_FAILURE);
104 }
105 snprintf(pgStat, wantedSize, pgStatFormat,
106 curTimePres, privData->mcfi_connectfrom,
107 privData->mcfi_helofrom, privData -> af == AF_INET ? privData->relayPresIP : privData->relayPresIP6,
108 privData->MXesNum, privData->MXesThatReject, privData->MXesThatAccept,
109 privData->MXesOutOfOrder, privData->MXesThatTempfail, gracefulDNSBool,
110 #ifdef WITH_SPF
111 whitelistedBool, privData->resolvedRelayIP, myHostName, formattedEmail, action, privData -> SPFResult, privData -> reverseRes, privData -> fakeRes);
112 #else
113 whitelistedBool, privData->resolvedRelayIP, myHostName, formattedEmail, action, privData -> reverseRes, privData -> fakeRes);
114 #endif
115 snprintf(tmpLog, MAXLOGLINE, "Got the DML statement for insert: \"%s\".", pgStat);
116 logNow(&tmpLog[0], 3, privData);
117
118 connPool.pgResArr[pgConnId] = PQexec(connPool.pgConnArr[pgConnId], pgStat);
119 if (PQresultStatus(connPool.pgResArr[pgConnId]) != PGRES_COMMAND_OK){
120 snprintf(tmpLog, MAXLOGLINE, "INSERT command failed: %s", PQerrorMessage(connPool.pgConnArr[pgConnId]));
121 logNow(&tmpLog[0], 0, privData);
122 snprintf(tmpLog, MAXLOGLINE, "The result status is: %s",PQresStatus(PQresultStatus(connPool.pgResArr[pgConnId])));
123 logNow(&tmpLog[0], 0, privData);
124 PQclear(connPool.pgResArr[pgConnId]);
125 return 1;
126 }
127 privData->SQLlogged = 1;
128 PQclear(connPool.pgResArr[pgConnId]);
129 /* freeing lock */
130 unlockPgConn(pgConnId);
131
132 logNow("Trying to free pgStat in pushHistory().", 3, privData);
133 free(pgStat);
134 logNow("Trying to free curTimePres in pushHistory().", 3, privData);
135 free(curTimePres);
136 return 0;
137 }
138 #endif
139