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