~ubuntu-branches/ubuntu/trusty/rsyslog/trusty

« back to all changes in this revision

Viewing changes to plugins/sm_cust_bindcdr/sm_cust_bindcdr.c

  • Committer: Dave Walker (Daviey)
  • Author(s): Scott Moser
  • Date: 2011-06-17 20:59:38 UTC
  • mfrom: (36.1.8 oneiric.merge)
  • Revision ID: davewalker@ubuntu.com-20110617205938-pfkizxz2wsgzi2ot
Tags: 5.8.1-1ubuntu1
* Resynchronise with Debian (LP: #794230).  Remaining changes:
  - Run as rsyslog:rsyslog, set $FileOwner to syslog
  - Replace init script with debian/rsyslog.upstart.
  - debian/rsyslog.logrotate: Use reload command to restart rsyslog
  - debian/rsyslog.conf: enable $RepeatedMsgReduction 
    to avoid bloating the syslog file (LP #453444)
  - Add debian/rsyslog.dmesg.upstart to save initial dmesg into a file.
    Install it in debian/rules.
  - debian/50-default.conf: set of default rules for syslog (forwarded to
    Debian #603160). remove file in postrm on purge. manage with ucf.
  - debian/rules: build with LDFLAGS=""
* Dropped:
  - debian/control: Bump build-dependency on debhelper
    debian now depends on dh >= 8
* New upstream release.
* Bump Standards-Version to 3.9.2. No further changes.
* Enable and install impstats module. (Closes: #620114)
* Update logcheck rule. (Closes: #616659)
* debian/rsyslog.init: Set correct compat level (5).
* The way rsyslog processes SIGHUP has changed. It no longer does a reload
  of its configuration, but simply closes all open files. To apply a changed
  configuration, rsyslogd needs to be restarted now.
  - Drop "reload" action from debian/rsyslog.init, map "force-reload" to
    "restart". (Closes: #580897)
  - Add "rotate" action to debian/rsyslog.init which sends SIGHUP to
    rsyslogd. Use that in debian/rsyslog.logrotate. (Closes: #626365)
  - Update debian/rsyslog-mysql.postinst and rsyslog-pgsql.postinst to use
    restart instead of reload.
  - Add a NEWS file explaining the changed SIGHUP handling.
* New upstream stable release.
* New upstream release.
  - Properly handle ANSI SQL strings in ompgsql. (Closes: #600479)
* New upstream release.
* debian/patches/02-pmaixforwardedfrom_type_nokeep.patch
  - Remove, merged upstream.
* debian/patches/03-epoll_create1-fallback.patch
  - Remove, merged upstream.
* debian/patches/03-epoll_create1-fallback.patch
  - If epoll_create1() is not available during runtime, fall back to
    epoll_create(). This fixes remote syslog when runnig rsyslog on a
    lenny kernel. (Closes: #617996)
* New upstream release.
* debian/rsyslog.links
  - Create symlink for rsyslog.service in multi-user.target.wants so rsyslog
    is enabled by default when using systemd.
* debian/patches/02-pmaixforwardedfrom_type_nokeep.patch
  - Fix build failure in aixforwardedfrom parser module by setting the
    module type to NOKEEP.
* debian/rsyslog.preinst
  - Remove old rsyslog.socket symlink from sockets.target.wants on upgrades
    as rsyslog uses syslog.socket now which is provided by systemd.
* debian/rsyslog.install
  - Stop installing rsyslog.socket.
* New upstream release.
* New upstream release.
  - Fix regression in imuxsock plugin which did no longer sanitize received
    messages. This makes 02-cleanup-trailing-lf.patch obsolete and also
    fixes the SQL syntax errors in the mysql output if the input contained
    NUL bytes. Closes: #614061
* Enable and install omprog output plugin. Closes: #552095
* Improve package description. Closes: #612948
  Thanks to Justin B Rye for the patch.
* debian/patches/02-cleanup-trailing-lf.patch
  - Fix regression in imuxsock plugin which did not remove a trailing LF
    anymore. Patch cherry-picked from upstream Git. Closes: #612829
* New upstream release.
* Enable and install parser modules.
* New upstream release.
* Upload to unstable.
* debian/patches/02-typo_fix_equation_sign.patch
  - Removed, merged upstream.
* debian/patches/03-atomic_operations.patch
  - Removed, merged upstream.
* debian/patches/03-atomic_operations.patch
  - Fix build failures on platforms which don't have 64 bit atomic
    operations. Patch cherry-picked from upstream Git. Closes: #600930
* New upstream development release.
* Remove patches, merged upstream
  - debian/patches/02-install_also_rsyslog_socket.patch
  - debian/patches/02-tls_loop_fix.patch
* debian/patches/02-typo_fix_equation_sign.patch
  - Fix small typo ("equation sign"). Closes: #575589
* debian/rsyslog.postinst
  - Remove pre-lenny migration code to rotate old log files from sysklogd.
* New upstream development release.
* debian/rsyslog.install
  - Install omruleset.so plugin: http://www.rsyslog.com/doc/omruleset.html
* debian/rsyslog.default
  - Start rsyslogd with native -c5 mode.
* Install systemd unit files which allow to run rsyslog in socket activation
  mode when systemd is used.
* debian/patches/02-install_also_rsyslog_socket.patch
  - When enabling rsyslog.service also enable rsyslog.socket. Patch
    cherry-picked from upstream Git.
* Bump debhelper compatibility level to 8. Update Build-Depends accordingly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* sm_cust_bindcdr.c
 
2
 * This is a custom developed plugin to process bind information into
 
3
 * a specific SQL statement. While the actual processing may be too specific
 
4
 * to be of general use, this module serves as a template on how this type
 
5
 * of processing can be done.
 
6
 *
 
7
 * Format generated:
 
8
 * "%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n"
 
9
 * Note that this is the same as smtradfile.c, except that we do have a RFC3339 timestamp. However,
 
10
 * we have copied over the code from there, it is too simple to go through all the hassle
 
11
 * of having a single code base.
 
12
 *
 
13
 * NOTE: read comments in module-template.h to understand how this file
 
14
 *       works!
 
15
 *
 
16
 * File begun on 2011-03-17 by RGerhards
 
17
 *
 
18
 * Copyright 2011 Rainer Gerhards and Adiscon GmbH.
 
19
 *
 
20
 * This file is part of rsyslog.
 
21
 *
 
22
 * Rsyslog is free software: you can redistribute it and/or modify
 
23
 * it under the terms of the GNU General Public License as published by
 
24
 * the Free Software Foundation, either version 3 of the License, or
 
25
 * (at your option) any later version.
 
26
 *
 
27
 * Rsyslog is distributed in the hope that it will be useful,
 
28
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
29
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
30
 * GNU General Public License for more details.
 
31
 *
 
32
 * You should have received a copy of the GNU General Public License
 
33
 * along with Rsyslog.  If not, see <http://www.gnu.org/licenses/>.
 
34
 *
 
35
 * A copy of the GPL can be found in the file "COPYING" in this distribution.
 
36
 */
 
37
#include "config.h"
 
38
#include "rsyslog.h"
 
39
#include <stdlib.h>
 
40
#include <ctype.h>
 
41
#include <string.h>
 
42
#include <assert.h>
 
43
#include <errno.h>
 
44
#include "conf.h"
 
45
#include "syslogd-types.h"
 
46
#include "cfsysline.h"
 
47
#include "template.h"
 
48
#include "msg.h"
 
49
#include "module-template.h"
 
50
#include "unicode-helper.h"
 
51
#include "errmsg.h"
 
52
 
 
53
MODULE_TYPE_STRGEN
 
54
MODULE_TYPE_NOKEEP
 
55
STRGEN_NAME("Custom_BindCDR,sql")
 
56
 
 
57
/* internal structures
 
58
 */
 
59
DEF_SMOD_STATIC_DATA
 
60
DEFobjCurrIf(errmsg)
 
61
 
 
62
/* list of "allowed" IPs */
 
63
typedef struct allowedip_s {
 
64
        uchar *pszIP;
 
65
        struct allowedip_s *next;
 
66
} allowedip_t;
 
67
 
 
68
static allowedip_t *root;
 
69
 
 
70
 
 
71
/* config data */
 
72
 
 
73
/* check if the provided IP is (already) in the allowed list
 
74
 */
 
75
static int
 
76
isAllowed(uchar *pszIP)
 
77
{
 
78
        allowedip_t *pallow;
 
79
        int ret = 0;
 
80
 
 
81
        for(pallow = root ; pallow != NULL ; pallow = pallow->next) {
 
82
                if(!ustrcmp(pallow->pszIP, pszIP)) {
 
83
                        ret = 1;
 
84
                        goto finalize_it;
 
85
                }
 
86
        }
 
87
finalize_it: return ret;
 
88
}
 
89
 
 
90
/* This function is called to add an additional allowed IP. It adds
 
91
 * the IP to the linked list of them. An error is emitted if the IP
 
92
 * already exists.
 
93
 */
 
94
static rsRetVal addAllowedIP(void __attribute__((unused)) *pVal, uchar *pNewVal)
 
95
{
 
96
        allowedip_t *pNew;
 
97
        DEFiRet;
 
98
 
 
99
        if(isAllowed(pNewVal)) {
 
100
                errmsg.LogError(0, NO_ERRCODE, "error: allowed IP '%s' already configured "
 
101
                                "duplicate ignored", pNewVal);
 
102
                ABORT_FINALIZE(RS_RET_ERR);
 
103
        }
 
104
 
 
105
        CHKmalloc(pNew = malloc(sizeof(allowedip_t)));
 
106
        pNew->pszIP = pNewVal;
 
107
        pNew->next = root;
 
108
        root = pNew;
 
109
        DBGPRINTF("sm_cust_bindcdr: allowed IP '%s' added.\n", pNewVal);
 
110
 
 
111
finalize_it:
 
112
        if(iRet != RS_RET_OK) {
 
113
                free(pNewVal);
 
114
        }
 
115
 
 
116
        RETiRet;
 
117
}
 
118
 
 
119
/* This strgen tries to minimize the amount of reallocs be first obtaining pointers to all strings
 
120
 * needed (including their length) and then calculating the actual space required. So when we 
 
121
 * finally copy, we know exactly what we need. So we do at most one alloc.
 
122
 * An actual message sample for what we intend to parse is (one line):
 
123
  <30>Mar 24 13:01:51 named[6085]: 24-Mar-2011 13:01:51.865 queries: info: client 10.0.0.96#39762: view trusted: query: 8.6.0.9.9.4.1.4.6.1.8.3.mobilecrawler.com IN TXT + (10.0.0.96)
 
124
 */
 
125
//previos dev: #define SQL_STMT "INSERT INTO CDR(`Date`,`Time`, timeMS, client, view, query, ip) VALUES ('"
 
126
#define SQL_STMT "INSERT INTO CDR(`date`,ip,user,dest) VALUES ('"
 
127
#define ADD_SQL_DELIM \
 
128
        memcpy(*ppBuf + iBuf, "', '", sizeof("', '") - 1); \
 
129
        iBuf += sizeof("', '") - 1;
 
130
#define SQL_STMT_END "');\n"
 
131
BEGINstrgen
 
132
        int iBuf;
 
133
        uchar *psz;
 
134
        uchar szDate[64];
 
135
        unsigned lenDate;
 
136
        uchar szTime[64];
 
137
        unsigned lenTime;
 
138
        uchar szMSec[64];
 
139
        unsigned lenMSec;
 
140
        uchar szClient[64];
 
141
        unsigned lenClient;
 
142
        uchar szView[64];
 
143
        unsigned lenView;
 
144
        uchar szQuery[64];
 
145
        unsigned lenQuery;
 
146
        uchar szIP[64];
 
147
        unsigned lenIP;
 
148
        size_t lenTotal;
 
149
CODESTARTstrgen
 
150
        /* first create an empty statement. This is to be replaced if
 
151
         * we have better data to fill in.
 
152
         */
 
153
        /* now make sure buffer is large enough */
 
154
        if(*pLenBuf < 2)
 
155
                CHKiRet(ExtendBuf(ppBuf, pLenBuf, 2));
 
156
        memcpy(*ppBuf, ";", sizeof(";"));
 
157
 
 
158
        /* first obtain all strings and their length (if not fixed) */
 
159
        /* Note that there are two date fields present, one in the header
 
160
         * and one more in the actual message. We use the one from the message
 
161
         * and parse that our. We check validity based on some fixe fields. In-
 
162
         * depth verification is probably not worth the effort (CPU time), because
 
163
         * we do various other checks on the message format below).
 
164
         */
 
165
        psz = getMSG(pMsg);
 
166
        if(psz[0] == ' ' && psz[3] == '-' && psz[7] == '-') {
 
167
                memcpy(szDate, psz+8,  4);
 
168
                szDate[4] = '-';
 
169
                if(!strncmp((char*)psz+4, "Jan", 3)) {
 
170
                        szDate[5] = '0';
 
171
                        szDate[6] = '1';
 
172
                } else if(!strncmp((char*)psz+4, "Feb", 3)) {
 
173
                        szDate[5] = '0';
 
174
                        szDate[6] = '2';
 
175
                } else if(!strncmp((char*)psz+4, "Mar", 3)) {
 
176
                        szDate[5] = '0';
 
177
                        szDate[6] = '3';
 
178
                } else if(!strncmp((char*)psz+4, "Apr", 3)) {
 
179
                        szDate[5] = '0';
 
180
                        szDate[6] = '4';
 
181
                } else if(!strncmp((char*)psz+4, "May", 3)) {
 
182
                        szDate[5] = '0';
 
183
                        szDate[6] = '5';
 
184
                } else if(!strncmp((char*)psz+4, "Jun", 3)) {
 
185
                        szDate[5] = '0';
 
186
                        szDate[6] = '6';
 
187
                } else if(!strncmp((char*)psz+4, "Jul", 3)) {
 
188
                        szDate[5] = '0';
 
189
                        szDate[6] = '7';
 
190
                } else if(!strncmp((char*)psz+4, "Aug", 3)) {
 
191
                        szDate[5] = '0';
 
192
                        szDate[6] = '8';
 
193
                } else if(!strncmp((char*)psz+4, "Sep", 3)) {
 
194
                        szDate[5] = '0';
 
195
                        szDate[6] = '9';
 
196
                } else if(!strncmp((char*)psz+4, "Oct", 3)) {
 
197
                        szDate[5] = '1';
 
198
                        szDate[6] = '0';
 
199
                } else if(!strncmp((char*)psz+4, "Nov", 3)) {
 
200
                        szDate[5] = '1';
 
201
                        szDate[6] = '1';
 
202
                } else if(!strncmp((char*)psz+4, "Dec", 3)) {
 
203
                        szDate[5] = '1';
 
204
                        szDate[6] = '2';
 
205
                }
 
206
                szDate[7] = '-';
 
207
                szDate[8] = psz[1];
 
208
                szDate[9] = psz[2];
 
209
                szDate[10] = '\0';
 
210
                lenDate = 10;
 
211
        } else {
 
212
                dbgprintf("Custom_BindCDR: date part in msg missing\n");
 
213
                ABORT_FINALIZE(RS_RET_ERR);
 
214
        }
 
215
 
 
216
        /* now time (pull both regular time and ms) */
 
217
        if(psz[12] == ' ' && psz[15] == ':' && psz[18] == ':' && psz[21] == '.' && psz[25] == ' ') {
 
218
                memcpy(szTime, (char*)psz+13, 8);
 
219
                szTime[9] = '\0';
 
220
                lenTime = 8;
 
221
                memcpy(szMSec, (char*)psz+22, 3);
 
222
                szMSec[4] = '\0';
 
223
                lenMSec = 3;
 
224
        } else {
 
225
                dbgprintf("Custom_BindCDR: date part in msg missing\n");
 
226
                ABORT_FINALIZE(RS_RET_ERR);
 
227
        }
 
228
 
 
229
        /* "client" */
 
230
        psz = (uchar*) strstr((char*) getMSG(pMsg), "client ");
 
231
        if(psz == NULL) {
 
232
                dbgprintf("Custom_BindCDR: client part in msg missing\n");
 
233
                ABORT_FINALIZE(RS_RET_ERR);
 
234
        } else {
 
235
                psz += sizeof("client ") - 1; /* skip "label" */
 
236
                for(  lenClient = 0
 
237
                    ; *psz && *psz != '#' && lenClient < sizeof(szClient) - 1
 
238
                    ; ++lenClient) {
 
239
                        szClient[lenClient] = *psz++;
 
240
                }
 
241
                szClient[lenClient] = '\0';
 
242
        }
 
243
 
 
244
        /* "view" */
 
245
        psz = (uchar*) strstr((char*) getMSG(pMsg), "view ");
 
246
        if(psz == NULL) {
 
247
                dbgprintf("Custom_BindCDR: view part in msg missing\n");
 
248
                ABORT_FINALIZE(RS_RET_ERR);
 
249
        } else {
 
250
                psz += sizeof("view ") - 1; /* skip "label" */
 
251
                for(  lenView = 0
 
252
                    ; *psz && *psz != ':' && lenView < sizeof(szView) - 1
 
253
                    ; ++lenView) {
 
254
                        szView[lenView] = *psz++;
 
255
                }
 
256
                szView[lenView] = '\0';
 
257
        }
 
258
 
 
259
        /* "query" - we must extract just the number, and in reverse! */
 
260
        psz = (uchar*) strstr((char*) getMSG(pMsg), "query: ");
 
261
        if(psz == NULL) {
 
262
                dbgprintf("Custom_BindCDR: query part in msg missing\n");
 
263
                ABORT_FINALIZE(RS_RET_ERR);
 
264
        } else {
 
265
                psz += sizeof("query: ") - 1; /* skip "label" */
 
266
                /* first find end-of-strihttp://www.rsyslog.com/doc/omruleset.htmlng to process */
 
267
                while(*psz && (isdigit(*psz) || *psz == '.')) {
 
268
                        psz++;
 
269
                }
 
270
                /* now shuffle data */
 
271
                for(  lenQuery = 0
 
272
                    ; *psz && *psz != ' ' && lenQuery < sizeof(szQuery) - 1
 
273
                    ; --psz) {
 
274
                        if(isdigit(*psz))
 
275
                                szQuery[lenQuery++] = *psz;
 
276
                }
 
277
                szQuery[lenQuery] = '\0';
 
278
        }
 
279
 
 
280
        /* "ip" */
 
281
        psz = (uchar*) strstr((char*) getMSG(pMsg), "IN TXT + (");
 
282
        if(psz == NULL) {
 
283
                dbgprintf("Custom_BindCDR: ip part in msg missing\n");
 
284
                ABORT_FINALIZE(RS_RET_ERR);
 
285
        } else {
 
286
                psz += sizeof("IN TXT + (") - 1; /* skip "label" */
 
287
                for(  lenIP = 0
 
288
                    ; *psz && *psz != ')' && lenIP < sizeof(szIP) - 1
 
289
                    ; ++lenIP) {
 
290
                        szIP[lenIP] = *psz++;
 
291
                }
 
292
                szIP[lenIP] = '\0';
 
293
        }
 
294
 
 
295
 
 
296
        /* --- strings extracted ---- */
 
297
 
 
298
        /* now check if the IP is "allowed", in which case we should not
 
299
         * insert into the database.
 
300
         */
 
301
        if(isAllowed(szIP)) {
 
302
                DBGPRINTF("sm_cust_bindcdr: message from allowed IP, ignoring\n");
 
303
                ABORT_FINALIZE(RS_RET_ERR);
 
304
        }
 
305
 
 
306
        /* calculate len, constants for spaces and similar fixed strings */
 
307
        lenTotal = lenDate + lenTime + lenMSec + lenClient + lenView + lenQuery
 
308
                   + lenIP + 7 * 5 + sizeof(SQL_STMT) + sizeof(SQL_STMT_END) + 2;
 
309
 
 
310
        /* now make sure buffer is large enough */
 
311
        if(lenTotal  >= *pLenBuf)
 
312
                CHKiRet(ExtendBuf(ppBuf, pLenBuf, lenTotal));
 
313
 
 
314
        /* and concatenate the resulting string */
 
315
        memcpy(*ppBuf, SQL_STMT, sizeof(SQL_STMT) - 1);
 
316
        iBuf = sizeof(SQL_STMT) - 1;
 
317
 
 
318
        memcpy(*ppBuf + iBuf, szDate, lenDate);
 
319
        iBuf += lenDate;
 
320
        /* prviously: ADD_SQL_DELIM */
 
321
        *(*ppBuf + iBuf) = ' ';
 
322
        ++iBuf;
 
323
 
 
324
        memcpy(*ppBuf + iBuf, szTime, lenTime);
 
325
        iBuf += lenTime;
 
326
        ADD_SQL_DELIM
 
327
 
 
328
        /* we shall now discard this part
 
329
        memcpy(*ppBuf + iBuf, szMSec, lenMSec);
 
330
        iBuf += lenMSec;
 
331
        ADD_SQL_DELIM
 
332
        */
 
333
 
 
334
        /* Note that this seem to be the IP to use */
 
335
        memcpy(*ppBuf + iBuf, szClient, lenClient);
 
336
        iBuf += lenClient;
 
337
        ADD_SQL_DELIM
 
338
 
 
339
        memcpy(*ppBuf + iBuf, szView, lenView);
 
340
        iBuf += lenView;
 
341
        ADD_SQL_DELIM
 
342
 
 
343
        memcpy(*ppBuf + iBuf, szQuery, lenQuery);
 
344
        iBuf += lenQuery;
 
345
        /* this is now the last field, so we dont need: ADD_SQL_DELIM */
 
346
 
 
347
        /* no longer to be included
 
348
        memcpy(*ppBuf + iBuf, szIP, lenIP);
 
349
        iBuf += lenIP;
 
350
        */
 
351
 
 
352
        /* end of SQL statement/trailer (NUL is contained in string!) */
 
353
        memcpy(*ppBuf + iBuf, SQL_STMT_END, sizeof(SQL_STMT_END));
 
354
        iBuf += sizeof(SQL_STMT_END);
 
355
 
 
356
finalize_it:
 
357
ENDstrgen
 
358
 
 
359
 
 
360
BEGINmodExit
 
361
        allowedip_t *pallow, *pdel;
 
362
CODESTARTmodExit
 
363
        for(pallow = root ; pallow != NULL ; ) {
 
364
                pdel = pallow;
 
365
                pallow = pallow->next;
 
366
                free(pdel->pszIP);
 
367
                free(pdel);
 
368
        }
 
369
 
 
370
        objRelease(errmsg, CORE_COMPONENT);
 
371
ENDmodExit
 
372
 
 
373
 
 
374
BEGINqueryEtryPt
 
375
CODESTARTqueryEtryPt
 
376
CODEqueryEtryPt_STD_SMOD_QUERIES
 
377
ENDqueryEtryPt
 
378
 
 
379
 
 
380
BEGINmodInit()
 
381
CODESTARTmodInit
 
382
        *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
 
383
CODEmodInit_QueryRegCFSLineHdlr
 
384
        CHKiRet(objUse(errmsg, CORE_COMPONENT));
 
385
 
 
386
        root = NULL;
 
387
        CHKiRet(omsdRegCFSLineHdlr((uchar *)"sgcustombindcdrallowedip", 0, eCmdHdlrGetWord,
 
388
                addAllowedIP, NULL, STD_LOADABLE_MODULE_ID));
 
389
        dbgprintf("rsyslog sm_cust_bindcdr called, compiled with version %s\n", VERSION);
 
390
ENDmodInit