1 /*
2 * This program is is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17 /**
18 * $Id: 65b7d9aba2527dddc7e2c49d6b2bb14db6013f29 $
19 * @file rlm_sql_sqlite.c
20 * @brief SQLite driver.
21 *
22 * @copyright 2013 Network RADIUS SARL <info@networkradius.com>
23 * @copyright 2007 Apple Inc.
24 */
25 RCSID("$Id: 65b7d9aba2527dddc7e2c49d6b2bb14db6013f29 $")
26
27 #include <freeradius-devel/radiusd.h>
28 #include <freeradius-devel/rad_assert.h>
29
30 #include <fcntl.h>
31 #include <sys/stat.h>
32
33 #include <sqlite3.h>
34
35 #include "rlm_sql.h"
36 #include "config.h"
37
38 #define BOOTSTRAP_MAX (1048576 * 10)
39
40 /*
41 * Allow us to use versions < 3.6.0 beta0
42 */
43 #ifndef SQLITE_OPEN_NOMUTEX
44 # define SQLITE_OPEN_NOMUTEX 0
45 #endif
46
47 #ifndef HAVE_SQLITE3_INT64
48 typedef sqlite_int64 sqlite3_int64;
49 #endif
50
51 typedef struct rlm_sql_sqlite_conn {
52 sqlite3 *db;
53 sqlite3_stmt *statement;
54 int col_count;
55 } rlm_sql_sqlite_conn_t;
56
57 typedef struct rlm_sql_sqlite_config {
58 char const *filename;
59 uint32_t busy_timeout;
60 } rlm_sql_sqlite_config_t;
61
62 static const CONF_PARSER driver_config[] = {
63 { "filename", FR_CONF_OFFSET(PW_TYPE_FILE_OUTPUT | PW_TYPE_REQUIRED, rlm_sql_sqlite_config_t, filename), NULL },
64 { "busy_timeout", FR_CONF_OFFSET(PW_TYPE_INTEGER, rlm_sql_sqlite_config_t, busy_timeout), "200" },
65 CONF_PARSER_TERMINATOR
66 };
67
68 /** Convert an sqlite status code to an sql_rcode_t
69 *
70 * @param status to convert.
71 * @return
72 * - RLM_SQL_OK - If no errors found.
73 * - RLM_SQL_ERROR - If a known, non-fatal, error occurred.
74 * - RLM_SQL_ALT_QUERY - If a constraints violation occurred.
75 * - RLM_SQL_RECONNECT - Anything else, we assume the connection can no longer be used.
76 */
sql_error_to_rcode(int status)77 static sql_rcode_t sql_error_to_rcode(int status)
78 {
79 /*
80 * Lowest byte is error category, other byte may contain
81 * the extended error, depending on version.
82 */
83 switch (status & 0xff) {
84 /*
85 * Not errors
86 */
87 case SQLITE_OK:
88 case SQLITE_DONE:
89 case SQLITE_ROW:
90 return RLM_SQL_OK;
91 /*
92 * User/transient errors
93 */
94 case SQLITE_ERROR: /* SQL error or missing database */
95 case SQLITE_FULL:
96 case SQLITE_MISMATCH:
97 case SQLITE_BUSY: /* Database file busy - can be caused by locking */
98 return RLM_SQL_ERROR;
99
100 /*
101 * Constraints violations
102 */
103 case SQLITE_CONSTRAINT:
104 return RLM_SQL_ALT_QUERY;
105
106 /*
107 * Errors with the handle, that probably require reinitialisation
108 */
109 default:
110 return RLM_SQL_RECONNECT;
111 }
112 }
113
114 /** Determine if an error occurred, and what type of error it was
115 *
116 * @param db handle to extract error from (may be NULL).
117 * @param status to check (if unused, set to SQLITE_OK).
118 * @return
119 * - RLM_SQL_OK - If no errors found.
120 * - RLM_SQL_ERROR - If a known, non-fatal, error occurred.
121 * - RLM_SQL_ALT_QUERY - If a constraints violation occurred.
122 * - RLM_SQL_RECONNECT - Anything else. We assume the connection can no longer be used.
123 */
sql_check_error(sqlite3 * db,int status)124 static sql_rcode_t sql_check_error(sqlite3 *db, int status)
125 {
126 int hstatus = SQLITE_OK;
127
128 if (db) {
129 hstatus = sqlite3_errcode(db);
130 switch (hstatus & 0xff) {
131 case SQLITE_OK:
132 case SQLITE_DONE:
133 case SQLITE_ROW:
134 hstatus = SQLITE_OK;
135 break;
136
137 default:
138 break;
139 }
140 }
141
142 switch (status & 0xff) {
143 case SQLITE_OK:
144 case SQLITE_DONE:
145 case SQLITE_ROW:
146 status = SQLITE_OK;
147 break;
148
149 default:
150 break;
151 }
152
153 if (status != SQLITE_OK) return sql_error_to_rcode(status);
154 if (hstatus != SQLITE_OK) return sql_error_to_rcode(status);
155
156 return RLM_SQL_OK;
157 }
158
159 /** Print an error to the global debug log
160 *
161 * If status does not indicate success, write an error to the global error log.
162 *
163 * @note The error code will be appended to the fmt string in the format ": code 0x<hex> (<int>)[: <string>]".
164 *
165 * @param db handle to extract error from (may be NULL).
166 * @param status to check (if unused, set to SQLITE_OK).
167 * @param fmt to preprend.
168 * @param ... arguments to fmt.
169 */
170 static void sql_print_error(sqlite3 *db, int status, char const *fmt, ...)
171 CC_HINT(format (printf, 3, 4)) CC_HINT(nonnull (3));
sql_print_error(sqlite3 * db,int status,char const * fmt,...)172 static void sql_print_error(sqlite3 *db, int status, char const *fmt, ...)
173 {
174 va_list ap;
175 char *p;
176 int hstatus = SQLITE_OK;
177
178 if (db) {
179 hstatus = sqlite3_errcode(db);
180 switch (hstatus & 0xff) {
181 case SQLITE_OK:
182 case SQLITE_DONE:
183 case SQLITE_ROW:
184 hstatus = SQLITE_OK;
185 break;
186
187 default:
188 break;
189 }
190 }
191
192 switch (status & 0xff) {
193 case SQLITE_OK:
194 case SQLITE_DONE:
195 case SQLITE_ROW:
196 status = SQLITE_OK;
197 break;
198
199 default:
200 break;
201 }
202
203 /*
204 * No errors!
205 */
206 if ((hstatus == SQLITE_OK) && (status == SQLITE_OK)) return;
207
208 /*
209 * At least one error...
210 */
211 va_start(ap, fmt);
212 MEM(p = talloc_vasprintf(NULL, fmt, ap));
213 va_end(ap);
214
215 /*
216 * Disagreement between handle, and function return code,
217 * print them both.
218 */
219 if ((status != SQLITE_OK) && (status != hstatus)) {
220 #ifdef HAVE_SQLITE3_ERRSTR
221 ERROR("rlm_sql_sqlite: %s: Code 0x%04x (%i): %s", p, status, status, sqlite3_errstr(status));
222 #else
223 ERROR("rlm_sql_sqlite: %s: Code 0x%04x (%i)", p, status, status);
224 #endif
225 }
226
227 if (hstatus != SQLITE_OK) ERROR("rlm_sql_sqlite: %s: Code 0x%04x (%i): %s",
228 p, hstatus, hstatus, sqlite3_errmsg(db));
229 }
230
231 #ifdef HAVE_SQLITE3_OPEN_V2
sql_loadfile(TALLOC_CTX * ctx,sqlite3 * db,char const * filename)232 static int sql_loadfile(TALLOC_CTX *ctx, sqlite3 *db, char const *filename)
233 {
234 ssize_t len;
235 int statement_cnt = 0;
236 char *buffer;
237 char *p, *q;
238 int cl;
239 FILE *f;
240 struct stat finfo;
241
242 int status;
243 sqlite3_stmt *statement;
244 char const *z_tail;
245
246 INFO("rlm_sql_sqlite: Executing SQL statements from file \"%s\"", filename);
247
248 f = fopen(filename, "r");
249 if (!f) {
250 ERROR("rlm_sql_sqlite: Failed opening SQL file \"%s\": %s", filename,
251 fr_syserror(errno));
252
253 return -1;
254 }
255
256 if (fstat(fileno(f), &finfo) < 0) {
257 ERROR("rlm_sql_sqlite: Failed stating SQL file \"%s\": %s", filename,
258 fr_syserror(errno));
259
260 fclose(f);
261
262 return -1;
263 }
264
265 if (finfo.st_size > BOOTSTRAP_MAX) {
266 too_big:
267 ERROR("rlm_sql_sqlite: Size of SQL (%zu) file exceeds limit (%uk)",
268 (size_t) finfo.st_size / 1024, BOOTSTRAP_MAX / 1024);
269
270 fclose(f);
271
272 return -1;
273 }
274
275 MEM(buffer = talloc_array(ctx, char, finfo.st_size + 1));
276 len = fread(buffer, sizeof(char), finfo.st_size + 1, f);
277 if (len > finfo.st_size) {
278 talloc_free(buffer);
279 goto too_big;
280 }
281
282 if (!len) {
283 if (ferror(f)) {
284 ERROR("rlm_sql_sqlite: Error reading SQL file: %s", fr_syserror(errno));
285
286 fclose(f);
287 talloc_free(buffer);
288
289 return -1;
290 }
291
292 DEBUG("rlm_sql_sqlite: Ignoring empty SQL file");
293
294 fclose(f);
295 talloc_free(buffer);
296
297 return 0;
298 }
299
300 buffer[len] = '\0';
301 fclose(f);
302
303 /*
304 * Check if input data is UTF-8. Allow CR/LF \t, too.
305 */
306 for (p = buffer; p < (buffer + len); p += cl) {
307 if (*p < ' ') {
308 if ((*p != 0x0a) && (*p != 0x0d) && (*p != '\t')) break;
309 cl = 1;
310 } else {
311 cl = fr_utf8_char((uint8_t *) p, -1);
312 if (!cl) break;
313 }
314 }
315
316 if ((p - buffer) != len) {
317 ERROR("rlm_sql_sqlite: Bootstrap file contains non-UTF8 char at offset %zu", p - buffer);
318 talloc_free(buffer);
319 return -1;
320 }
321
322 /*
323 * Statement delimiter is ;\n
324 */
325 p = buffer;
326 while ((q = strchr(p, ';'))) {
327 if ((q[1] != '\n') && (q[1] != '\0')) {
328 p = q + 1;
329 statement_cnt++;
330 continue;
331 }
332
333 #ifdef HAVE_SQLITE3_PREPARE_V2
334 status = sqlite3_prepare_v2(db, p, q - p, &statement, &z_tail);
335 #else
336 status = sqlite3_prepare(db, p, q - p, &statement, &z_tail);
337 #endif
338
339 if (sql_check_error(db, status) != RLM_SQL_OK) {
340 sql_print_error(db, status, "Failed preparing statement %i", statement_cnt);
341 talloc_free(buffer);
342 return -1;
343 }
344
345 status = sqlite3_step(statement);
346 if (sql_check_error(db, status) != RLM_SQL_OK) {
347 sql_print_error(db, status, "Failed executing statement %i", statement_cnt);
348 sqlite3_finalize(statement);
349 talloc_free(buffer);
350 return -1;
351 }
352
353 status = sqlite3_finalize(statement);
354 if (sql_check_error(db, status) != RLM_SQL_OK) {
355 sql_print_error(db, status, "Failed finalizing statement %i", statement_cnt);
356 talloc_free(buffer);
357 return -1;
358 }
359
360 statement_cnt++;
361 p = q + 1;
362 }
363
364 talloc_free(buffer);
365 return 0;
366 }
367 #endif
368
mod_instantiate(CONF_SECTION * conf,rlm_sql_config_t * config)369 static int mod_instantiate(CONF_SECTION *conf, rlm_sql_config_t *config)
370 {
371 static bool version_done;
372
373 bool exists;
374 rlm_sql_sqlite_config_t *driver;
375 struct stat buf;
376
377 if (!version_done) {
378 version_done = true;
379
380 if (sqlite3_libversion_number() != SQLITE_VERSION_NUMBER) {
381 WARN("rlm_sql_sqlite: libsqlite version changed since the server was built");
382 WARN("rlm_sql_sqlite: linked: %s built: %s", sqlite3_libversion(), SQLITE_VERSION);
383 }
384 INFO("rlm_sql_sqlite: libsqlite version: %s", sqlite3_libversion());
385 }
386
387 MEM(driver = config->driver = talloc_zero(config, rlm_sql_sqlite_config_t));
388 if (cf_section_parse(conf, driver, driver_config) < 0) {
389 return -1;
390 }
391 if (!driver->filename) {
392 MEM(driver->filename = talloc_typed_asprintf(driver, "%s/%s", get_radius_dir(), config->sql_db));
393 }
394
395 if (stat(driver->filename, &buf) == 0) {
396 exists = true;
397 } else if (errno == ENOENT) {
398 exists = false;
399 } else {
400 ERROR("rlm_sql_sqlite: Database exists, but couldn't be opened: %s", fr_syserror(errno));
401 return -1;
402 }
403
404 if (cf_pair_find(conf, "bootstrap") && !exists) {
405 # ifdef HAVE_SQLITE3_OPEN_V2
406 int status;
407 int ret;
408 char const *p;
409 char *buff;
410 sqlite3 *db = NULL;
411 CONF_PAIR *cp;
412
413 INFO("rlm_sql_sqlite: Database doesn't exist, creating it and loading schema");
414
415 p = strrchr(driver->filename, '/');
416 if (p) {
417 size_t len = (p - driver->filename) + 1;
418
419 buff = talloc_array(conf, char, len);
420 strlcpy(buff, driver->filename, len);
421 } else {
422 MEM(buff = talloc_typed_strdup(conf, driver->filename));
423 }
424
425 ret = rad_mkdir(buff, 0700, -1, -1);
426 talloc_free(buff);
427 if (ret < 0) {
428 ERROR("rlm_sql_sqlite: Failed creating directory for SQLite database: %s", fr_syserror(errno));
429
430 return -1;
431 };
432
433 status = sqlite3_open_v2(driver->filename, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
434 if (!db) {
435 # ifdef HAVE_SQLITE3_ERRSTR
436 ERROR("rlm_sql_sqlite: Failed creating opening/creating SQLite database: %s",
437 sqlite3_errstr(status));
438 # else
439 ERROR("rlm_sql_sqlite: Failed creating opening/creating SQLite database, got code (%i)",
440 status);
441 # endif
442
443 goto unlink;
444 }
445
446 if (sql_check_error(db, status) != RLM_SQL_OK) {
447 (void) sqlite3_close(db);
448
449 goto unlink;
450 }
451
452 /*
453 * Execute multiple bootstrap SQL files in order
454 */
455 for (cp = cf_pair_find(conf, "bootstrap");
456 cp;
457 cp = cf_pair_find_next(conf, cp, "bootstrap")) {
458 p = cf_pair_value(cp);
459 if (!p) continue;
460
461 ret = sql_loadfile(conf, db, p);
462 if (ret < 0) goto unlink;
463 }
464
465 status = sqlite3_close(db);
466 if (status != SQLITE_OK) {
467 /*
468 * Safer to use sqlite3_errstr here, just in case the handle is in a weird state
469 */
470 # ifdef HAVE_SQLITE3_ERRSTR
471 ERROR("rlm_sql_sqlite: Error closing SQLite handle: %s", sqlite3_errstr(status));
472 # else
473 ERROR("rlm_sql_sqlite: Error closing SQLite handle, got code (%i)", status);
474 # endif
475
476 goto unlink;
477 }
478
479 if (ret < 0) {
480 unlink:
481 if ((unlink(driver->filename) < 0) && (errno != ENOENT)) {
482 ERROR("rlm_sql_sqlite: Error removing partially initialised database: %s",
483 fr_syserror(errno));
484 }
485 return -1;
486 }
487 #else
488 WARN("rlm_sql_sqlite: sqlite3_open_v2() not available, cannot bootstrap database. "
489 "Upgrade to SQLite >= 3.5.1 if you need this functionality");
490 #endif
491 }
492
493 return 0;
494 }
495
_sql_socket_destructor(rlm_sql_sqlite_conn_t * conn)496 static int _sql_socket_destructor(rlm_sql_sqlite_conn_t *conn)
497 {
498 int status = 0;
499
500 DEBUG2("rlm_sql_sqlite: Socket destructor called, closing socket");
501
502 if (conn->db) {
503 status = sqlite3_close(conn->db);
504 if (status != SQLITE_OK) WARN("rlm_sql_sqlite: Got SQLite error code (%u) when closing socket", status);
505 }
506
507 return 0;
508 }
509
_sql_greatest(sqlite3_context * ctx,int num_values,sqlite3_value ** values)510 static void _sql_greatest(sqlite3_context *ctx, int num_values, sqlite3_value **values)
511 {
512 int i;
513 sqlite3_int64 value, max = 0;
514
515 for (i = 0; i < num_values; i++) {
516 value = sqlite3_value_int64(values[i]);
517 if (value > max) {
518 max = value;
519 }
520 }
521
522 sqlite3_result_int64(ctx, max);
523 }
524
sql_socket_init(rlm_sql_handle_t * handle,rlm_sql_config_t * config)525 static sql_rcode_t sql_socket_init(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
526 {
527 rlm_sql_sqlite_conn_t *conn;
528 rlm_sql_sqlite_config_t *driver = config->driver;
529
530 int status;
531
532 MEM(conn = handle->conn = talloc_zero(handle, rlm_sql_sqlite_conn_t));
533 talloc_set_destructor(conn, _sql_socket_destructor);
534
535 INFO("rlm_sql_sqlite: Opening SQLite database \"%s\"", driver->filename);
536 #ifdef HAVE_SQLITE3_OPEN_V2
537 status = sqlite3_open_v2(driver->filename, &(conn->db), SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX, NULL);
538 #else
539 status = sqlite3_open(driver->filename, &(conn->db));
540 #endif
541
542 if (!conn->db || (sql_check_error(conn->db, status) != RLM_SQL_OK)) {
543 sql_print_error(conn->db, status, "Error opening SQLite database \"%s\"", driver->filename);
544 return RLM_SQL_ERROR;
545 }
546 status = sqlite3_busy_timeout(conn->db, driver->busy_timeout);
547 if (sql_check_error(conn->db, status) != RLM_SQL_OK) {
548 sql_print_error(conn->db, status, "Error setting busy timeout");
549 return RLM_SQL_ERROR;
550 }
551
552 /*
553 * Enable extended return codes for extra debugging info.
554 */
555 #ifdef HAVE_SQLITE3_EXTENDED_RESULT_CODES
556 status = sqlite3_extended_result_codes(conn->db, 1);
557 if (sql_check_error(conn->db, status) != RLM_SQL_OK) {
558 sql_print_error(conn->db, status, "Error enabling extended result codes");
559 return RLM_SQL_ERROR;
560 }
561 #endif
562
563 #ifdef HAVE_SQLITE3_CREATE_FUNCTION_V2
564 status = sqlite3_create_function_v2(conn->db, "GREATEST", -1, SQLITE_ANY, NULL,
565 _sql_greatest, NULL, NULL, NULL);
566 #else
567 status = sqlite3_create_function(conn->db, "GREATEST", -1, SQLITE_ANY, NULL,
568 _sql_greatest, NULL, NULL);
569 #endif
570 if (sql_check_error(conn->db, status) != RLM_SQL_OK) {
571 sql_print_error(conn->db, status, "Failed registering 'GREATEST' sql function");
572 return RLM_SQL_ERROR;
573 }
574
575 return RLM_SQL_OK;
576 }
577
sql_select_query(rlm_sql_handle_t * handle,UNUSED rlm_sql_config_t * config,char const * query)578 static sql_rcode_t sql_select_query(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config, char const *query)
579 {
580 rlm_sql_sqlite_conn_t *conn = handle->conn;
581 char const *z_tail;
582 int status;
583
584 #ifdef HAVE_SQLITE3_PREPARE_V2
585 status = sqlite3_prepare_v2(conn->db, query, strlen(query), &conn->statement, &z_tail);
586 #else
587 status = sqlite3_prepare(conn->db, query, strlen(query), &conn->statement, &z_tail);
588 #endif
589
590 conn->col_count = 0;
591
592 return sql_check_error(conn->db, status);
593 }
594
595
sql_query(rlm_sql_handle_t * handle,UNUSED rlm_sql_config_t * config,char const * query)596 static sql_rcode_t sql_query(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config, char const *query)
597 {
598
599 sql_rcode_t rcode;
600 rlm_sql_sqlite_conn_t *conn = handle->conn;
601 char const *z_tail;
602 int status;
603
604 #ifdef HAVE_SQLITE3_PREPARE_V2
605 status = sqlite3_prepare_v2(conn->db, query, strlen(query), &conn->statement, &z_tail);
606 #else
607 status = sqlite3_prepare(conn->db, query, strlen(query), &conn->statement, &z_tail);
608 #endif
609 rcode = sql_check_error(conn->db, status);
610 if (rcode != RLM_SQL_OK) return rcode;
611
612 status = sqlite3_step(conn->statement);
613 return sql_check_error(conn->db, status);
614 }
615
sql_num_fields(rlm_sql_handle_t * handle,UNUSED rlm_sql_config_t * config)616 static int sql_num_fields(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
617 {
618 rlm_sql_sqlite_conn_t *conn = handle->conn;
619
620 if (conn->statement) {
621 return sqlite3_column_count(conn->statement);
622 }
623
624 return 0;
625 }
626
sql_num_rows(rlm_sql_handle_t * handle,UNUSED rlm_sql_config_t * config)627 static int sql_num_rows(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
628 {
629 rlm_sql_sqlite_conn_t *conn = handle->conn;
630
631 if (conn->statement) {
632 return sqlite3_data_count(conn->statement);
633 }
634
635 return 0;
636 }
637
sql_fetch_row(rlm_sql_handle_t * handle,rlm_sql_config_t * config)638 static sql_rcode_t sql_fetch_row(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
639 {
640 int status;
641 rlm_sql_sqlite_conn_t *conn = handle->conn;
642
643 int i = 0;
644
645 char **row;
646
647 TALLOC_FREE(handle->row);
648
649 /*
650 * Executes the SQLite query and interates over the results
651 */
652 status = sqlite3_step(conn->statement);
653
654 /*
655 * Error getting next row
656 */
657 if (sql_check_error(conn->db, status) != RLM_SQL_OK) return RLM_SQL_ERROR;
658
659 /*
660 * No more rows to process (were done)
661 */
662 if (status == SQLITE_DONE) return RLM_SQL_NO_MORE_ROWS;
663
664 /*
665 * We only need to do this once per result set, because
666 * the number of columns won't change.
667 */
668 if (conn->col_count == 0) {
669 conn->col_count = sql_num_fields(handle, config);
670 if (conn->col_count == 0) return RLM_SQL_ERROR;
671 }
672
673 MEM(row = handle->row = talloc_zero_array(handle->conn, char *, conn->col_count + 1));
674
675 for (i = 0; i < conn->col_count; i++) {
676 switch (sqlite3_column_type(conn->statement, i)) {
677 case SQLITE_INTEGER:
678 MEM(row[i] = talloc_typed_asprintf(row, "%d", sqlite3_column_int(conn->statement, i)));
679 break;
680
681 case SQLITE_FLOAT:
682 MEM(row[i] = talloc_typed_asprintf(row, "%f", sqlite3_column_double(conn->statement, i)));
683 break;
684
685 case SQLITE_TEXT:
686 {
687 char const *p;
688 p = (char const *) sqlite3_column_text(conn->statement, i);
689
690 if (p) MEM(row[i] = talloc_typed_strdup(row, p));
691 }
692 break;
693
694 case SQLITE_BLOB:
695 {
696 uint8_t const *p;
697 size_t len;
698
699 p = sqlite3_column_blob(conn->statement, i);
700 if (p) {
701 len = sqlite3_column_bytes(conn->statement, i);
702
703 MEM(row[i] = talloc_zero_array(row, char, len + 1));
704 memcpy(row[i], p, len);
705 }
706 }
707 break;
708
709 default:
710 break;
711 }
712 }
713
714 return RLM_SQL_OK;
715 }
716
sql_free_result(rlm_sql_handle_t * handle,UNUSED rlm_sql_config_t * config)717 static sql_rcode_t sql_free_result(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
718 {
719 rlm_sql_sqlite_conn_t *conn = handle->conn;
720
721 if (conn->statement) {
722 TALLOC_FREE(handle->row);
723
724 (void) sqlite3_finalize(conn->statement);
725 conn->statement = NULL;
726 conn->col_count = 0;
727 }
728
729 /*
730 * There's no point in checking the code returned by finalize
731 * as it'll have already been encountered elsewhere in the code.
732 *
733 * It's just the last error that occurred processing the
734 * statement.
735 */
736 return RLM_SQL_OK;
737 }
738
739 /** Retrieves any errors associated with the connection handle
740 *
741 * @note Caller will free any memory allocated in ctx.
742 *
743 * @param ctx to allocate temporary error buffers in.
744 * @param out Array of sql_log_entrys to fill.
745 * @param outlen Length of out array.
746 * @param handle rlm_sql connection handle.
747 * @param config rlm_sql config.
748 * @return number of errors written to the sql_log_entry array.
749 */
sql_error(UNUSED TALLOC_CTX * ctx,sql_log_entry_t out[],size_t outlen,rlm_sql_handle_t * handle,UNUSED rlm_sql_config_t * config)750 static size_t sql_error(UNUSED TALLOC_CTX *ctx, sql_log_entry_t out[], size_t outlen,
751 rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
752 {
753 rlm_sql_sqlite_conn_t *conn = handle->conn;
754 char const *error;
755
756 rad_assert(outlen > 0);
757
758 error = sqlite3_errmsg(conn->db);
759 if (!error) return 0;
760
761 out[0].type = L_ERR;
762 out[0].msg = error;
763
764 return 1;
765 }
766
sql_finish_query(rlm_sql_handle_t * handle,rlm_sql_config_t * config)767 static sql_rcode_t sql_finish_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
768 {
769 return sql_free_result(handle, config);
770 }
771
sql_affected_rows(rlm_sql_handle_t * handle,UNUSED rlm_sql_config_t * config)772 static int sql_affected_rows(rlm_sql_handle_t *handle,
773 UNUSED rlm_sql_config_t *config)
774 {
775 rlm_sql_sqlite_conn_t *conn = handle->conn;
776
777 if (conn->db) return sqlite3_changes(conn->db);
778
779 return -1;
780 }
781
782
783 /* Exported to rlm_sql */
784 extern rlm_sql_module_t rlm_sql_sqlite;
785 rlm_sql_module_t rlm_sql_sqlite = {
786 .name = "rlm_sql_sqlite",
787 .flags = RLM_SQL_RCODE_FLAGS_ALT_QUERY,
788 .mod_instantiate = mod_instantiate,
789 .sql_socket_init = sql_socket_init,
790 .sql_query = sql_query,
791 .sql_select_query = sql_select_query,
792 .sql_num_fields = sql_num_fields,
793 .sql_num_rows = sql_num_rows,
794 .sql_affected_rows = sql_affected_rows,
795 .sql_fetch_row = sql_fetch_row,
796 .sql_free_result = sql_free_result,
797 .sql_error = sql_error,
798 .sql_finish_query = sql_finish_query,
799 .sql_finish_select_query = sql_finish_query
800 };
801