~ubuntu-branches/ubuntu/natty/freeradius/natty-updates

« back to all changes in this revision

Viewing changes to src/modules/rlm_sql_log/rlm_sql_log.c

  • Committer: Bazaar Package Importer
  • Author(s): Josip Rodin
  • Date: 2009-11-23 03:57:37 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 28.
  • Revision ID: james.westby@ubuntu.com-20091123035737-zsgtzhfych8hir68
Tags: 2.1.7+dfsg-1
* Adopting the package, closes: #536623.
* New upstream version, closes: #513484.
  + Fixes the blooper in unlang evaluation logic, closes: #526175.
* Used quilt (and added README.source), and moved upstream file patching
  into debian/patches/. The source is no longer in collab-maint git
  (to make it simpler for me to finally get this out the door), but
  kept the .gitignore should we need that again.
* Dropped the dialup_admin/bin/backup_radacct patch (integrated upstream).
* Dropped the raddb/Makefile patch (problem no longer exists upstream).
* Dropped the lib/packet.c lib/radius.c main/listen.c patches (was from
  upstream 2.0.5 anyway).
* Dropped references to otp.conf, it no longer exists upstream.
  Keep removing the conffile statoverride in prerm.
* Dropped references to snmp.conf, it no longer exists upstream.
  Keep removing the conffile statoverride in prerm.
* Ship /etc/freeradius/modules/* in the freeradius package.
* Stop shipping sites-enabled symlinks in the package and instead create
  them only on initial install, thanks to Matej Vela, closes: #533396.
* Add export PATH="${PATH:+$PATH:}/usr/sbin:/sbin" to the init script
  at the request of John Morrissey, closes: #550143.
* Stop installing /var/run/freeradius in the package to silence Lintian.
  The init script already recreates it at will.
* Remove executable bit from example.pl to silence Lintian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 *  rlm_sql_log.c       Append the SQL queries in a log file which
3
3
 *                      is read later by the radsqlrelay program
4
4
 *
5
 
 *  Version:    $Id: rlm_sql_log.c,v 1.12 2007/12/15 21:26:51 aland Exp $
 
5
 *  Version:    $Id$
6
6
 *
7
7
 *  Author:     Nicolas Baradakis <nicolas.baradakis@cegetel.net>
8
8
 *
25
25
 */
26
26
 
27
27
#include <freeradius-devel/ident.h>
28
 
RCSID("$Id: rlm_sql_log.c,v 1.12 2007/12/15 21:26:51 aland Exp $")
 
28
RCSID("$Id$")
29
29
 
30
30
#include <freeradius-devel/radiusd.h>
31
31
#include <freeradius-devel/modules.h>
 
32
#include <freeradius-devel/rad_assert.h>
32
33
 
33
34
#include <fcntl.h>
34
35
#include <sys/stat.h>
38
39
static int sql_log_accounting(void *instance, REQUEST *request);
39
40
static int sql_log_postauth(void *instance, REQUEST *request);
40
41
 
41
 
#ifndef HAVE_PTHREAD_H
42
 
/*
43
 
 *      This is a lot simpler than putting ifdef's around
44
 
 *      every use of the pthread functions.
45
 
 */
46
 
#define pthread_mutex_lock(a)
47
 
#define pthread_mutex_trylock(a) (0)
48
 
#define pthread_mutex_unlock(a)
49
 
#define pthread_mutex_init(a,b)
50
 
#define pthread_mutex_destroy(a)
51
 
#else
52
 
#include        <pthread.h>
53
 
#endif
54
 
 
55
42
#define MAX_QUERY_LEN 4096
56
43
 
57
44
/*
58
45
 *      Define a structure for our module configuration.
59
46
 */
60
47
typedef struct rlm_sql_log_t {
61
 
        char            *name;
62
48
        char            *path;
63
49
        char            *postauth_query;
64
50
        char            *sql_user_name;
 
51
        int             utf8;   
65
52
        char            *allowed_chars;
66
53
        CONF_SECTION    *conf_section;
67
 
#ifdef HAVE_PTHREAD_H
68
 
        pthread_mutex_t mutex;
69
 
#endif
70
54
} rlm_sql_log_t;
71
55
 
72
56
/*
79
63
         offsetof(rlm_sql_log_t,postauth_query), NULL, ""},
80
64
        {"sql_user_name", PW_TYPE_STRING_PTR,
81
65
         offsetof(rlm_sql_log_t,sql_user_name), NULL, ""},
 
66
        {"utf8", PW_TYPE_BOOLEAN,
 
67
         offsetof(rlm_sql_log_t,utf8), NULL, "no"},
82
68
        {"safe-characters", PW_TYPE_STRING_PTR,
83
69
         offsetof(rlm_sql_log_t,allowed_chars), NULL,
84
70
        "@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /"},
100
86
 */
101
87
static int sql_log_instantiate(CONF_SECTION *conf, void **instance)
102
88
{
103
 
        const char      *name;
104
89
        rlm_sql_log_t   *inst;
105
90
 
106
91
        /*
113
98
        }
114
99
 
115
100
        /*
116
 
         *      Get the name of the current section in the conf file.
117
 
         */
118
 
        name = cf_section_name2(conf);
119
 
        if (name == NULL)
120
 
                name = cf_section_name1(conf);
121
 
        if (name == NULL)
122
 
                name = "sql_log";
123
 
        inst->name = strdup(name);
124
 
 
125
 
        /*
126
101
         *      If the configuration parameters can't be parsed,
127
102
         *      then fail.
128
103
         */
129
104
        if (cf_section_parse(conf, inst, module_config) < 0) {
130
 
                radlog(L_ERR, "rlm_sql_log (%s): Unable to parse parameters",
131
 
                       inst->name);
 
105
                radlog(L_ERR, "rlm_sql_log: Unable to parse parameters");
132
106
                sql_log_detach(inst);
133
107
                return -1;
134
108
        }
148
122
        char **p;
149
123
        rlm_sql_log_t *inst = (rlm_sql_log_t *)instance;
150
124
 
151
 
        if (inst->name) {
152
 
                free(inst->name);
153
 
                inst->name = NULL;
154
 
        }
155
 
 
156
125
        /*
157
126
         *      Free up dynamically allocated string pointers.
158
127
         */
228
197
        return len;
229
198
}
230
199
 
 
200
static size_t sql_utf8_escape_func(char *out, size_t outlen, const char *in)
 
201
{
 
202
        int len = 0;
 
203
        int utf8 = 0;
 
204
 
 
205
        while (in[0]) {
 
206
                /* 
 
207
                 * Skip over UTF8 characters
 
208
                 */
 
209
                utf8 = fr_utf8_char((uint8_t *)in);
 
210
                if (utf8) {
 
211
                        if (outlen <= utf8) {
 
212
                                break;
 
213
                        }
 
214
                        while (utf8-- > 0) {
 
215
                                *out = *in;
 
216
                                out++;
 
217
                                in++;
 
218
                                outlen--;
 
219
                                len++;
 
220
                        }
 
221
                        continue;
 
222
                }
 
223
 
 
224
                /*
 
225
                 *      Non-printable characters get replaced with their
 
226
                 *      mime-encoded equivalents.
 
227
                 */
 
228
                if ((in[0] < 32) ||
 
229
                    strchr(allowed_chars, *in) == NULL) {
 
230
                        /*
 
231
                         *      Only 3 or less bytes available.
 
232
                         */
 
233
                        if (outlen <= 3) {
 
234
                                break;
 
235
                        }
 
236
 
 
237
                        snprintf(out, outlen, "=%02X", (unsigned char) in[0]);
 
238
                        in++;
 
239
                        out += 3;
 
240
                        outlen -= 3;
 
241
                        len += 3;
 
242
                        continue;
 
243
                }
 
244
 
 
245
                /*
 
246
                 *      Only one byte left.
 
247
                 */
 
248
                if (outlen <= 1) {
 
249
                        break;
 
250
                }
 
251
 
 
252
                /*
 
253
                 *      Allowed character.
 
254
                 */
 
255
                *out = *in;
 
256
                out++;
 
257
                in++;
 
258
                outlen--;
 
259
                len++;
 
260
        }
 
261
        *out = '\0';
 
262
        return len;
 
263
}
 
264
 
231
265
/*
232
266
 *      Add the 'SQL-User-Name' attribute to the packet.
233
267
 */
239
273
        tmpuser[0] = '\0';
240
274
        sqlusername[0] = '\0';
241
275
 
 
276
        rad_assert(request != NULL);
 
277
        rad_assert(request->packet != NULL);
 
278
 
242
279
        /* Remove any user attr we added previously */
243
280
        pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
244
281
 
253
290
 
254
291
        if (tmpuser[0] != '\0') {
255
292
                strlcpy(sqlusername, tmpuser, sizeof(tmpuser));
256
 
                DEBUG2("rlm_sql_log (%s): sql_set_user escaped user --> '%s'",
257
 
                       inst->name, sqlusername);
 
293
                RDEBUG2("sql_set_user escaped user --> '%s'", sqlusername);
258
294
                vp = pairmake("SQL-User-Name", sqlusername, 0);
259
295
                if (vp == NULL) {
260
 
                        radlog(L_ERR, "%s", librad_errstr);
 
296
                        radlog(L_ERR, "%s", fr_strerror());
261
297
                        return -1;
262
298
                }
263
299
 
280
316
 
281
317
        /* Add attribute 'SQL-User-Name' */
282
318
        if (sql_set_user(inst, request, sqlusername, NULL) <0) {
283
 
                radlog(L_ERR, "rlm_sql_log (%s): Couldn't add SQL-User-Name attribute",
284
 
                               inst->name);
 
319
                radlog_request(L_ERR, 0, request, 
 
320
                               "Couldn't add SQL-User-Name attribute");
285
321
                return RLM_MODULE_FAIL;
286
322
        }
287
323
 
288
324
        /* Expand variables in the query */
289
325
        xlat_query[0] = '\0';
290
 
        radius_xlat(xlat_query, len, query, request, sql_escape_func);
 
326
        radius_xlat(xlat_query, len, query, request,
 
327
                    inst->utf8 ? sql_utf8_escape_func : sql_escape_func);
291
328
        if (xlat_query[0] == '\0') {
292
 
                radlog(L_ERR, "rlm_sql_log (%s): Couldn't xlat the query %s",
293
 
                       inst->name, query);
 
329
                radlog_request(L_ERR, 0, request, "Couldn't xlat the query %s",
 
330
                       query);
294
331
                return RLM_MODULE_FAIL;
295
332
        }
296
333
 
330
367
 
331
368
        while (!locked) {
332
369
                if ((fd = open(path, O_WRONLY | O_APPEND | O_CREAT, 0666)) < 0) {
333
 
                        radlog(L_ERR, "rlm_sql_log (%s): Couldn't open file %s: %s",
334
 
                               inst->name, path, strerror(errno));
 
370
                        radlog_request(L_ERR, 0, request, "Couldn't open file %s: %s",
 
371
                                       path, strerror(errno));
335
372
                        return RLM_MODULE_FAIL;
336
373
                }
337
374
                if (setlock(fd) != 0) {
338
 
                        radlog(L_ERR, "rlm_sql_log (%s): Couldn't lock file %s: %s",
339
 
                               inst->name, path, strerror(errno));
 
375
                        radlog_request(L_ERR, 0, request, "Couldn't lock file %s: %s",
 
376
                                       path, strerror(errno));
340
377
                        close(fd);
341
378
                        return RLM_MODULE_FAIL;
342
379
                }
343
380
                if (fstat(fd, &st) != 0) {
344
 
                        radlog(L_ERR, "rlm_sql_log (%s): Couldn't stat file %s: %s",
345
 
                               inst->name, path, strerror(errno));
 
381
                        radlog_request(L_ERR, 0, request, "Couldn't stat file %s: %s",
 
382
                                       path, strerror(errno));
346
383
                        close(fd);
347
384
                        return RLM_MODULE_FAIL;
348
385
                }
349
386
                if (st.st_nlink == 0) {
350
 
                        DEBUG("rlm_sql_log (%s): File %s removed by another program, retrying",
351
 
                              inst->name, path);
 
387
                        RDEBUG("File %s removed by another program, retrying",
 
388
                              path);
352
389
                        close(fd);
353
390
                        continue;
354
391
                }
356
393
        }
357
394
 
358
395
        if ((fp = fdopen(fd, "a")) == NULL) {
359
 
                radlog(L_ERR, "rlm_sql_log (%s): Couldn't associate a stream with file %s: %s",
360
 
                       inst->name, path, strerror(errno));
 
396
                radlog_request(L_ERR, 0, request, "Couldn't associate a stream with file %s: %s",
 
397
                               path, strerror(errno));
361
398
                close(fd);
362
399
                return RLM_MODULE_FAIL;
363
400
        }
380
417
        DICT_VALUE      *dval;
381
418
        CONF_PAIR       *cp;
382
419
 
383
 
        DEBUG("rlm_sql_log (%s): Processing sql_log_accounting", inst->name);
 
420
        rad_assert(request != NULL);
 
421
        rad_assert(request->packet != NULL);
 
422
 
 
423
        RDEBUG("Processing sql_log_accounting");
384
424
 
385
425
        /* Find the Acct Status Type. */
386
426
        if ((pair = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE)) == NULL) {
387
 
                radlog(L_ERR, "rlm_sql_log (%s): Packet has no account status type",
388
 
                       inst->name);
 
427
                radlog_request(L_ERR, 0, request, "Packet has no account status type");
389
428
                return RLM_MODULE_INVALID;
390
429
        }
391
430
 
392
431
        /* Search the query in conf section of the module */
393
432
        if ((dval = dict_valbyattr(PW_ACCT_STATUS_TYPE, pair->vp_integer)) == NULL) {
394
 
                radlog(L_ERR, "rlm_sql_log (%s): Unsupported Acct-Status-Type = %d",
395
 
                       inst->name, pair->vp_integer);
 
433
                radlog_request(L_ERR, 0, request, "Unsupported Acct-Status-Type = %d",
 
434
                               pair->vp_integer);
396
435
                return RLM_MODULE_NOOP;
397
436
        }
398
437
        if ((cp = cf_pair_find(inst->conf_section, dval->name)) == NULL) {
399
 
                DEBUG("rlm_sql_log (%s): Couldn't find an entry %s in the config section",
400
 
                      inst->name, dval->name);
 
438
                RDEBUG("Couldn't find an entry %s in the config section",
 
439
                       dval->name);
401
440
                return RLM_MODULE_NOOP;
402
441
        }
403
442
        cfquery = cf_pair_value(cp);
420
459
        char            querystr[MAX_QUERY_LEN];
421
460
        rlm_sql_log_t   *inst = (rlm_sql_log_t *)instance;
422
461
 
423
 
        DEBUG("rlm_sql_log (%s): Processing sql_log_postauth", inst->name);
 
462
        rad_assert(request != NULL);
 
463
 
 
464
        RDEBUG("Processing sql_log_postauth");
424
465
 
425
466
        /* Xlat the query */
426
467
        ret = sql_xlat_query(inst, request, inst->postauth_query,