Merge pull request #212 from jahir/master
[freeradius.git] / src / modules / rlm_sql / drivers / rlm_sql_sqlite / rlm_sql_sqlite.c
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, version 2 if the
4  *   License as published by the Free Software Foundation.
5  *
6  *   This program is distributed in the hope that it will be useful,
7  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
8  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9  *   GNU General Public License for more details.
10  *
11  *   You should have received a copy of the GNU General Public License
12  *   along with this program; if not, write to the Free Software
13  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
14  */
15  
16 /**
17  * $Id$
18  * @file rlm_sql_sqlite.c
19  * @brief SQLite driver.
20  *
21  * @copyright 2013 Network RADIUS SARL <info@networkradius.com>
22  * @copyright 2007 Apple Inc.
23  */
24
25 #include <freeradius-devel/ident.h>
26 RCSID("$Id$")
27
28 #include <freeradius-devel/radiusd.h>
29
30 #include <sys/stat.h>
31
32 #include <sqlite3.h>
33
34 #include "rlm_sql.h"
35
36 typedef struct rlm_sql_conn {
37         sqlite3 *db;
38         sqlite3_stmt *statement;
39         int col_count;
40 } rlm_sql_conn_t;
41
42 typedef struct rlm_sql_sqlite_config {
43         const char *filename;
44 } rlm_sql_sqlite_config_t;
45
46 static const CONF_PARSER driver_config[] = {
47         {"filename", PW_TYPE_STRING_PTR,
48          offsetof(rlm_sql_sqlite_config_t, filename), NULL, NULL},
49         
50         {NULL, -1, 0, NULL, NULL}
51 };
52
53 static int sql_check_error(sqlite3 *db)
54 {
55         int error = sqlite3_errcode(db);
56         switch(error) {
57         /*
58          *      Not errors
59          */
60         case SQLITE_OK:
61         case SQLITE_DONE:
62         case SQLITE_ROW:
63                 return 0;
64         /*
65          *      User/transient errors
66          */
67         case SQLITE_ERROR:      /* SQL error or missing database */
68         case SQLITE_FULL:
69         case SQLITE_CONSTRAINT:
70         case SQLITE_MISMATCH:
71                 radlog(L_ERR, "rlm_sql_sqlite: Error (%d)", error);
72                 
73                 return -1;
74                 break;
75                 
76         /*
77          *      Errors with the handle, that probably require reinitialisation
78          */
79         default:
80                 radlog(L_ERR, "rlm_sql_sqlite: Handle is unusable, "
81                        "error (%d)", error);
82                 return SQL_DOWN;
83                 break;
84         }
85 }
86
87 static int sql_instantiate(CONF_SECTION *conf, rlm_sql_config_t *config)
88 {
89         rlm_sql_sqlite_config_t *driver;
90         
91         MEM(driver = config->driver = talloc_zero(config, rlm_sql_sqlite_config_t));
92         
93         if (cf_section_parse(conf, driver, driver_config) < 0) {
94                 return -1;
95         }
96         
97         if (!driver->filename) {
98                 MEM(driver->filename = talloc_asprintf(driver, "%s/%s",
99                                                        radius_dir,
100                                                        config->sql_db));
101         }
102         
103         return 0;
104 }
105
106 static int sql_init_socket(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
107 {
108         rlm_sql_conn_t *conn;
109         rlm_sql_sqlite_config_t *driver = config->driver;
110         
111         int status;
112
113         MEM(conn = handle->conn = talloc_zero(handle, rlm_sql_conn_t));
114
115         radlog(L_INFO, "rlm_sql_sqlite: Opening SQLite database \"%s\"",
116                driver->filename);
117         
118         status = sqlite3_open_v2(driver->filename, &(conn->db),
119                                  SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX,
120                                  NULL);
121         if (status != SQLITE_OK) {
122                 return sql_check_error(conn->db);
123         }
124         
125         /*
126          *      Enable extended return codes for extra debugging info.
127          */
128         status = sqlite3_extended_result_codes(conn->db, 1);
129         
130         return sql_check_error(conn->db);
131 }
132
133 static int sql_destroy_socket(rlm_sql_handle_t *handle,
134                               UNUSED rlm_sql_config_t *config)
135 {
136         if (!handle->conn) {
137                 return 0;
138         }
139
140         TALLOC_FREE(handle->conn);
141         
142         return 0;
143 }
144
145 static int sql_select_query(rlm_sql_handle_t * handle,
146                            UNUSED rlm_sql_config_t *config, char *querystr)
147 {
148         int status;
149         rlm_sql_conn_t *conn = handle->conn;
150         const char *z_tail;
151         
152         status = sqlite3_prepare_v2(conn->db, querystr,
153                                     strlen(querystr), &conn->statement,
154                                     &z_tail);
155                                  
156         conn->col_count = 0;
157                 
158         return sql_check_error(conn->db);
159 }
160
161
162 static int sql_query(rlm_sql_handle_t * handle, UNUSED rlm_sql_config_t *config,
163                      char *querystr)
164 {
165         int status;
166         rlm_sql_conn_t *conn = handle->conn;
167         const char *z_tail;
168         
169         status = sqlite3_prepare_v2(conn->db, querystr,
170                                     strlen(querystr), &conn->statement,
171                                     &z_tail);
172                                     
173         status = sqlite3_step(conn->statement);
174                 
175         return sql_check_error(conn->db);
176 }
177
178 static int sql_store_result(UNUSED rlm_sql_handle_t * handle,
179                             UNUSED rlm_sql_config_t *config)
180 {
181         return 0;
182 }
183
184 static int sql_num_fields(rlm_sql_handle_t * handle,
185                           UNUSED rlm_sql_config_t *config)
186 {
187         rlm_sql_conn_t *conn = handle->conn;
188         
189         if (conn->statement) {
190                 return sqlite3_column_count(conn->statement);
191         }
192         
193         return 0;
194 }
195
196 static int sql_num_rows(rlm_sql_handle_t * handle,
197                         UNUSED rlm_sql_config_t *config)
198 {
199         rlm_sql_conn_t *conn = handle->conn;
200         
201         if (conn->statement) {
202                 return sqlite3_data_count(conn->statement);
203         }
204         
205         return 0;
206 }
207
208 static int sql_fetch_row(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
209 {
210         int status;
211         rlm_sql_conn_t *conn = handle->conn;
212         
213         int i = 0;
214         
215         char **row;
216
217         /*
218          *      Executes the SQLite query and interates over the results
219          */
220         status = sqlite3_step(conn->statement);
221         
222         /*
223          *      Error getting next row
224          */
225         if (sql_check_error(conn->db)) {
226                 return -1;
227         }
228
229         /*
230          *      No more rows to process (were done)
231          */
232         if (status == SQLITE_DONE) {
233                 return 1;
234         }
235         
236         /*
237          *      We only need to do this once per result set, because
238          *      the number of columns won't change.
239          */
240         if (conn->col_count == 0) {
241                 conn->col_count = sql_num_fields(handle, config);
242                 if (conn->col_count == 0) {
243                         return -1;
244                 }
245         }
246
247         /*
248          *      Free the previous result (also gets called on finish_query)
249          */
250         talloc_free(handle->row);
251         
252         MEM(row = handle->row = talloc_zero_array(handle->conn, char *,
253                                                   conn->col_count + 1));
254         
255         for (i = 0; i < conn->col_count; i++)
256         {
257                 switch (sqlite3_column_type(conn->statement, i))
258                 {
259                 case SQLITE_INTEGER:       
260                         row[i] = talloc_asprintf(row, "%d",
261                                                  sqlite3_column_int(conn->statement, i));
262                         break;
263                         
264                 case SQLITE_FLOAT:
265                         row[i] = talloc_asprintf(row, "%f",
266                                                  sqlite3_column_double(conn->statement, i));
267                         break;
268                         
269                 case SQLITE_TEXT:
270                         {
271                                 const char *p;
272                                 p = (const char *) sqlite3_column_text(conn->statement, i);
273                                 
274                                 if (p) {
275                                         row[i] = talloc_strdup(row, p);
276                                 }
277                         }
278                         break;
279                         
280                 case SQLITE_BLOB:
281                         {
282                                 const uint8_t *p;
283                                 size_t len;
284
285                                 p = sqlite3_column_blob(conn->statement, i);
286                                 if (p) {
287                                         len = sqlite3_column_bytes(conn->statement, i);
288                                         
289                                         MEM(row[i] = talloc_zero_array(row, char, len + 1));
290                                         memcpy(row[i], p, len);                   
291                                 }
292                         }
293                         break;
294                         
295                 default:
296                         break;
297                 }
298         }
299         
300         return 0;
301 }
302
303 static int sql_free_result(rlm_sql_handle_t *handle,
304                            UNUSED rlm_sql_config_t *config)
305 {
306         rlm_sql_conn_t *conn = handle->conn;
307         
308         if (conn->statement) {
309                 TALLOC_FREE(handle->row);
310                 
311                 (void) sqlite3_finalize(conn->statement);
312                 conn->statement = NULL;
313                 conn->col_count = 0;
314         }
315         
316         /*
317          *      There's no point in checking the code returned by finalize
318          *      as it'll have already been encountered elsewhere in the code.
319          *
320          *      It's just the last error that occurred processing the
321          *      statement.
322          */
323         return 0;
324 }
325
326 static const char *sql_error(rlm_sql_handle_t *handle,
327                              UNUSED rlm_sql_config_t *config)
328 {
329         rlm_sql_conn_t *conn = handle->conn;
330
331         if (conn->db) {
332                 return sqlite3_errmsg(conn->db);
333         }
334
335         return "Invalid handle";
336 }
337
338 static int sql_close(rlm_sql_handle_t *handle,
339                      UNUSED rlm_sql_config_t *config)
340 {
341         int status = 0;
342         rlm_sql_conn_t *conn = handle->conn;
343         
344         if (conn && conn->db) {
345                 status = sqlite3_close(conn->db);
346                 conn->db = NULL;
347         }
348         
349         if (status != SQLITE_OK) {
350                 return -1;
351         }
352         
353         return 0;
354 }
355
356 static int sql_finish_query(rlm_sql_handle_t *handle,
357                             UNUSED rlm_sql_config_t *config)
358 {
359         return sql_free_result(handle, config);
360 }
361
362 static int sql_affected_rows(rlm_sql_handle_t *handle,
363                              UNUSED rlm_sql_config_t *config)
364 {
365         rlm_sql_conn_t *conn = handle->conn;
366   
367         if (conn->db) {
368                 return sqlite3_changes(conn->db);       
369         }  
370
371         return -1;
372 }
373
374
375 /* Exported to rlm_sql */
376 rlm_sql_module_t rlm_sql_sqlite = {
377         "rlm_sql_sqlite",
378         sql_instantiate,
379         sql_init_socket,
380         sql_destroy_socket,
381         sql_query,
382         sql_select_query,
383         sql_store_result,
384         sql_num_fields,
385         sql_num_rows,
386         sql_fetch_row,
387         sql_free_result,
388         sql_error,
389         sql_close,
390         sql_finish_query,
391         sql_finish_query,
392         sql_affected_rows
393 };