25 RCSID(
"$Id: 4f367721ef891cec2f263af3bf1ede039d3db190 $")
27 #include <freeradius-devel/radiusd.h>
28 #include <freeradius-devel/rad_assert.h>
38 #define BOOTSTRAP_MAX (1048576 * 10)
43 #ifndef SQLITE_OPEN_NOMUTEX
44 # define SQLITE_OPEN_NOMUTEX 0
47 #ifndef HAVE_SQLITE3_INT64
48 typedef sqlite3_int64 sqlite_int64
83 switch (status & 0xff) {
102 case SQLITE_CONSTRAINT:
125 int hstatus = SQLITE_OK;
128 hstatus = sqlite3_errcode(db);
129 switch (hstatus & 0xff) {
141 switch (status & 0xff) {
169 static void sql_print_error(sqlite3 *db,
int status,
char const *fmt, ...)
175 int hstatus = SQLITE_OK;
178 hstatus = sqlite3_errcode(db);
179 switch (hstatus & 0xff) {
191 switch (status & 0xff) {
205 if ((hstatus == SQLITE_OK) && (status == SQLITE_OK))
return;
211 MEM(p = talloc_vasprintf(NULL, fmt, ap));
218 if ((status != SQLITE_OK) && (status != hstatus)) {
219 #ifdef HAVE_SQLITE3_ERRSTR
220 ERROR(
"rlm_sql_sqlite: %s: Code 0x%04x (%i): %s", p, status, status, sqlite3_errstr(status));
222 ERROR(
"rlm_sql_sqlite: %s: Code 0x%04x (%i)", p, status, status);
226 if (hstatus != SQLITE_OK)
ERROR(
"rlm_sql_sqlite: %s: Code 0x%04x (%i): %s",
227 p, hstatus, hstatus, sqlite3_errmsg(db));
230 #ifdef HAVE_SQLITE3_OPEN_V2
231 static int sql_loadfile(TALLOC_CTX *ctx, sqlite3 *db,
char const *filename)
234 int statement_cnt = 0;
242 sqlite3_stmt *statement;
245 INFO(
"rlm_sql_sqlite: Executing SQL statements from file \"%s\"", filename);
247 f = fopen(filename,
"r");
249 ERROR(
"rlm_sql_sqlite: Failed opening SQL file \"%s\": %s", filename,
255 if (fstat(fileno(f), &finfo) < 0) {
256 ERROR(
"rlm_sql_sqlite: Failed stating SQL file \"%s\": %s", filename,
266 ERROR(
"rlm_sql_sqlite: Size of SQL (%zu) file exceeds limit (%uk)",
274 MEM(buffer = talloc_array(ctx,
char, finfo.st_size + 1));
275 len = fread(buffer,
sizeof(
char), finfo.st_size + 1, f);
276 if (len > finfo.st_size) {
291 DEBUG(
"rlm_sql_sqlite: Ignoring empty SQL file");
305 for (p = buffer; p < (buffer + len); p += cl) {
307 if ((*p != 0x0a) && (*p != 0x0d) && (*p !=
'\t'))
break;
315 if ((p - buffer) != len) {
316 ERROR(
"rlm_sql_sqlite: Bootstrap file contains non-UTF8 char at offset %zu", p - buffer);
325 while ((q = strchr(p,
';'))) {
334 #ifdef HAVE_SQLITE3_PREPARE_V2
335 status = sqlite3_prepare_v2(db, s, len, &statement, &z_tail);
337 status = sqlite3_prepare(db, s, len, &statement, &z_tail);
341 sql_print_error(db, status,
"Failed preparing statement %i", statement_cnt);
346 status = sqlite3_step(statement);
348 sql_print_error(db, status,
"Failed executing statement %i", statement_cnt);
349 sqlite3_finalize(statement);
354 status = sqlite3_finalize(statement);
356 sql_print_error(db, status,
"Failed finalizing statement %i", statement_cnt);
372 static bool version_done;
381 if (sqlite3_libversion_number() != SQLITE_VERSION_NUMBER) {
382 WARN(
"rlm_sql_sqlite: libsqlite version changed since the server was built");
383 WARN(
"rlm_sql_sqlite: linked: %s built: %s", sqlite3_libversion(), SQLITE_VERSION);
385 INFO(
"rlm_sql_sqlite: libsqlite version: %s", sqlite3_libversion());
396 if (stat(driver->
filename, &buf) == 0) {
398 }
else if (errno == ENOENT) {
401 ERROR(
"rlm_sql_sqlite: Database exists, but couldn't be opened: %s",
fr_syserror(errno));
406 # ifdef HAVE_SQLITE3_OPEN_V2
414 INFO(
"rlm_sql_sqlite: Database doesn't exist, creating it and loading schema");
418 size_t len = (p - driver->
filename) + 1;
420 buff = talloc_array(conf,
char, len);
429 ERROR(
"rlm_sql_sqlite: Failed creating directory for SQLite database: %s",
fr_syserror(errno));
434 status = sqlite3_open_v2(driver->
filename, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
436 # ifdef HAVE_SQLITE3_ERRSTR
437 ERROR(
"rlm_sql_sqlite: Failed creating opening/creating SQLite database: %s",
438 sqlite3_errstr(status));
440 ERROR(
"rlm_sql_sqlite: Failed creating opening/creating SQLite database, got code (%i)",
448 (void) sqlite3_close(db);
462 ret = sql_loadfile(conf, db, p);
463 if (ret < 0)
goto unlink;
466 status = sqlite3_close(db);
467 if (status != SQLITE_OK) {
471 # ifdef HAVE_SQLITE3_ERRSTR
472 ERROR(
"rlm_sql_sqlite: Error closing SQLite handle: %s", sqlite3_errstr(status));
474 ERROR(
"rlm_sql_sqlite: Error closing SQLite handle, got code (%i)", status);
481 if ((unlink(driver->
filename) < 0) && (errno != ENOENT)) {
482 ERROR(
"rlm_sql_sqlite: Error removing partially initialised database: %s",
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");
500 DEBUG2(
"rlm_sql_sqlite: Socket destructor called, closing socket");
503 status = sqlite3_close(conn->db);
504 if (status != SQLITE_OK)
WARN(
"rlm_sql_sqlite: Got SQLite error when closing socket: %s",
505 sqlite3_errmsg(conn->db));
511 static void _sql_greatest(sqlite3_context *ctx,
int num_values, sqlite3_value **values)
514 sqlite3_int64 value, max = 0;
516 for (i = 0; i < num_values; i++) {
517 value = sqlite3_value_int64(values[i]);
523 sqlite3_result_int64(ctx, max);
537 INFO(
"rlm_sql_sqlite: Opening SQLite database \"%s\"", driver->
filename);
538 #ifdef HAVE_SQLITE3_OPEN_V2
541 status = sqlite3_open(driver->
filename, &(conn->db));
548 status = sqlite3_busy_timeout(conn->db, driver->
busy_timeout);
557 #ifdef HAVE_SQLITE3_EXTENDED_RESULT_CODES
558 status = sqlite3_extended_result_codes(conn->db, 1);
560 sql_print_error(conn->db, status,
"Error enabling extended result codes");
565 #ifdef HAVE_SQLITE3_CREATE_FUNCTION_V2
566 status = sqlite3_create_function_v2(conn->db,
"GREATEST", -1, SQLITE_ANY, NULL,
569 status = sqlite3_create_function(conn->db,
"GREATEST", -1, SQLITE_ANY, NULL,
573 sql_print_error(conn->db, status,
"Failed registering 'GREATEST' sql function");
586 #ifdef HAVE_SQLITE3_PREPARE_V2
587 status = sqlite3_prepare_v2(conn->db, query, strlen(query), &conn->statement, &z_tail);
589 status = sqlite3_prepare(conn->db, query, strlen(query), &conn->statement, &z_tail);
606 #ifdef HAVE_SQLITE3_PREPARE_V2
607 status = sqlite3_prepare_v2(conn->db, query, strlen(query), &conn->statement, &z_tail);
609 status = sqlite3_prepare(conn->db, query, strlen(query), &conn->statement, &z_tail);
614 status = sqlite3_step(conn->statement);
622 if (conn->statement)
return sqlite3_column_count(conn->statement);
634 fields = sqlite3_column_count(conn->statement);
637 MEM(names = talloc_array(handle,
char const *, fields));
639 for (i = 0; i < fields; i++) names[i] = sqlite3_column_name(conn->statement, i);
659 status = sqlite3_step(conn->statement);
675 if (conn->col_count == 0) {
683 talloc_free(handle->
row);
684 MEM(row = handle->
row = talloc_zero_array(handle->
conn,
char *, conn->col_count + 1));
686 for (i = 0; i < conn->col_count; i++) {
687 switch (sqlite3_column_type(conn->statement, i)) {
699 p = (
char const *) sqlite3_column_text(conn->statement, i);
710 p = sqlite3_column_blob(conn->statement, i);
712 len = sqlite3_column_bytes(conn->statement, i);
714 MEM(row[i] = talloc_zero_array(row,
char, len + 1));
715 memcpy(row[i], p, len);
734 if (conn->statement) {
735 TALLOC_FREE(handle->
row);
737 (void) sqlite3_finalize(conn->statement);
738 conn->statement = NULL;
771 error = sqlite3_errmsg(conn->db);
772 if (!error)
return 0;
791 return sqlite3_changes(conn->db);
801 .
name =
"rlm_sql_sqlite",
static sql_rcode_t sql_finish_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
static sql_rcode_t sql_check_error(sqlite3 *db, int status)
Determine if an error occurred, and what type of error it was.
General connection/server error.
Prototypes and functions for the SQL module.
log_type_t type
Type of log entry L_ERR, L_WARN, L_INFO, L_DBG etc..
#define RLM_SQL_RCODE_FLAGS_ALT_QUERY
Can distinguish between other errors and those.
char const * msg
Log message.
#define CONF_PARSER_TERMINATOR
#define SQLITE_OPEN_NOMUTEX
static sql_rcode_t sql_free_result(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
static sql_rcode_t sql_error_to_rcode(int status)
Convert an sqlite status code to an sql_rcode_t.
int rad_mkdir(char *directory, mode_t mode, uid_t uid, gid_t gid)
Create possibly many directories.
Defines a CONF_PAIR to C data type mapping.
static int mod_instantiate(CONF_SECTION *conf, rlm_sql_config_t *config)
CONF_PAIR * cf_pair_find(CONF_SECTION const *, char const *name)
char const * cf_pair_value(CONF_PAIR const *pair)
Key constraint violation.
typedef sqlite3_int64 sqlite_int64 struct rlm_sql_sqlite_conn rlm_sql_sqlite_conn_t
Stale connection, should reconnect.
static sql_rcode_t sql_fetch_row(rlm_sql_row_t *out, rlm_sql_handle_t *handle, rlm_sql_config_t *config)
static void CC_HINT(nonnull(3))
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
rlm_sql_module_t rlm_sql_sqlite
static void _sql_greatest(sqlite3_context *ctx, int num_values, sqlite3_value **values)
static int sql_num_fields(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
int cf_section_parse(CONF_SECTION *, void *base, CONF_PARSER const *variables)
Parse a configuration section into user-supplied variables.
static sql_rcode_t sql_query(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config, char const *query)
char * talloc_typed_asprintf(void const *t, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
CONF_PAIR * cf_pair_find_next(CONF_SECTION const *, CONF_PAIR const *, char const *name)
Find a pair with a name matching attr, after specified pair.
Configuration AVP similar to a VALUE_PAIR.
void * driver
Where drivers should write a pointer to their configurations.
void * conn
Database specific connection handle.
rlm_sql_row_t row
Row data from the last query.
static sql_rcode_t sql_socket_init(rlm_sql_handle_t *handle, rlm_sql_config_t *config, struct timeval const *timeout)
struct rlm_sql_sqlite_config rlm_sql_sqlite_config_t
#define PW_TYPE_FILE_OUTPUT
File matching value must exist, and must be writeable.
#define FR_CONF_OFFSET(_n, _t, _s, _f)
static size_t 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)
Retrieves any errors associated with the connection handle.
static const CONF_PARSER driver_config[]
char const * sql_db
Database to run queries against.
#define PW_TYPE_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
size_t strlcpy(char *dst, char const *src, size_t siz)
static sql_rcode_t sql_select_query(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config, char const *query)
static int _sql_socket_destructor(rlm_sql_sqlite_conn_t *conn)
int fr_utf8_char(uint8_t const *str, ssize_t inlen)
Checks for utf-8, taken from http://www.w3.org/International/questions/qa-forms-utf-8.
static int sql_affected_rows(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
char const * get_radius_dir(void)
Get the global radius config directory.
char * talloc_typed_strdup(void const *t, char const *p)
Call talloc strdup, setting the type on the new chunk correctly.
static void sql_print_error(sqlite3 *db, int status, char const *fmt,...) CC_HINT(format(printf
Print an error to the global debug log.
static sql_rcode_t sql_fields(char const **out[], rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)