Allow sqlite filename to be specified in the configuration file.
[freeradius.git] / src / modules / rlm_sql / drivers / rlm_sql_sqlite / sql_sqlite.c
1 /*
2  *  sql_sqlite.c
3  *  freeradius
4  *
5  * Version:     $Id$
6  *
7  *   This program is free software; you can redistribute it and/or modify
8  *   it under the terms of the GNU General Public License version 2 only, as published by
9  *   the Free Software Foundation.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License version 2
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * Copyright 2007 Apple Inc.
21  */
22
23 #include <freeradius-devel/ident.h>
24 RCSID("$Id$")
25
26 #include <freeradius-devel/radiusd.h>
27
28 #include <sys/stat.h>
29
30 #include <sqlite3.h>
31
32 #include "rlm_sql.h"
33
34 typedef struct rlm_sql_sqlite_sock {
35         sqlite3 *pDb;
36         sqlite3_stmt *pStmt;
37         int columnCount;
38 } rlm_sql_sqlite_sock;
39
40
41 /*************************************************************************
42  *
43  *      Function: sql_create_socket
44  *
45  *      Purpose: Establish connection to the db
46  *
47  *************************************************************************/
48 static int sql_init_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config)
49 {
50         int status;
51         rlm_sql_sqlite_sock *sqlite_sock;
52         char *filename;
53         char buffer[2048];
54         
55         if (!sqlsocket->conn) {
56                 sqlsocket->conn = (rlm_sql_sqlite_sock *)rad_malloc(sizeof(rlm_sql_sqlite_sock));
57                 if (!sqlsocket->conn) {
58                         return -1;
59                 }
60         }
61         sqlite_sock = sqlsocket->conn;
62         memset(sqlite_sock, 0, sizeof(rlm_sql_sqlite_sock));
63         
64         filename = config->sql_file;
65         if (!filename) {
66                 snprintf(buffer, sizeof(buffer), "%s/sqlite_radius_client_database",
67                          radius_dir);
68                 filename = buffer;
69         }
70         radlog(L_INFO, "rlm_sql_sqlite: Opening sqlite database %s for #%d",
71                filename, sqlsocket->id);
72         
73         status = sqlite3_open(filename, &sqlite_sock->pDb);
74         radlog(L_INFO, "rlm_sql_sqlite: sqlite3_open() = %d\n", status);
75         return (status != SQLITE_OK) * -1;
76 }
77
78
79 /*************************************************************************
80  *
81  *      Function: sql_destroy_socket
82  *
83  *      Purpose: Free socket and any private connection data
84  *
85  *************************************************************************/
86 static int sql_destroy_socket(SQLSOCK *sqlsocket, UNUSED SQL_CONFIG *config)
87 {
88         int status = 0;
89         rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
90
91         if (sqlite_sock && sqlite_sock->pDb) {
92                 status = sqlite3_close(sqlite_sock->pDb);
93                 radlog(L_INFO, "rlm_sql_sqlite: sqlite3_close() = %d\n", status);
94         }
95         else {
96                 radlog(L_INFO, "rlm_sql_sqlite: sql_destroy_socket noop.\n");
97         }
98         
99         return 0;
100 }
101
102
103 /*************************************************************************
104  *
105  *      Function: sql_query
106  *
107  *      Purpose: Issue a query to the database
108  *
109  *************************************************************************/
110 static int sql_query(SQLSOCK * sqlsocket, SQL_CONFIG *config, char *querystr)
111 {
112         int status;
113         rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
114         const char *zTail;
115         
116         if (config->sqltrace)
117                 radlog(L_DBG,"rlm_sql_sqlite: query:  %s", querystr);
118         if (sqlite_sock->pDb == NULL) {
119                 radlog(L_ERR, "rlm_sql_sqlite: Socket not connected");
120                 return SQL_DOWN;
121         }
122         
123         status = sqlite3_prepare(sqlite_sock->pDb, querystr, strlen(querystr), &sqlite_sock->pStmt, &zTail);
124         radlog(L_DBG, "rlm_sql_sqlite: sqlite3_prepare() = %d\n", status);
125         sqlite_sock->columnCount = 0;
126         
127         return (status == SQLITE_OK) ? 0 : SQL_DOWN;
128 }
129
130
131 /*************************************************************************
132  *
133  *      Function: sql_select_query
134  *
135  *      Purpose: Issue a select query to the database
136  *
137  *************************************************************************/
138 static int sql_select_query(SQLSOCK *sqlsocket, SQL_CONFIG *config,
139                             char *querystr)
140 {
141         if (strstr(querystr, "nas") != NULL)
142                 return sql_query(sqlsocket, config, querystr);
143                 
144         return 0;
145 }
146
147
148 /*************************************************************************
149  *
150  *      Function: sql_store_result
151  *
152  *      Purpose: database specific store_result function. Returns a result
153  *               set for the query.
154  *
155  *************************************************************************/
156 static int sql_store_result(UNUSED SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
157 {
158         return 0;
159 }
160
161
162 /*************************************************************************
163  *
164  *      Function: sql_num_fields
165  *
166  *      Purpose: database specific num_fields function. Returns number
167  *               of columns from query
168  *
169  *************************************************************************/
170 static int sql_num_fields(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
171 {
172         rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
173         
174         if (sqlite_sock->pStmt)
175                 return sqlite3_column_count(sqlite_sock->pStmt);
176         
177         return 0;
178 }
179
180
181 /*************************************************************************
182  *
183  *      Function: sql_num_rows
184  *
185  *      Purpose: database specific num_rows. Returns number of rows in
186  *               query
187  *
188  *************************************************************************/
189 static int sql_num_rows(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
190 {
191         rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
192         
193         if (sqlite_sock->pStmt)
194                 return sqlite3_data_count(sqlite_sock->pStmt);
195         
196         return 0;
197 }
198
199
200 /*************************************************************************
201  *      Function: sql_free_rowdata
202  *************************************************************************/
203 static void sql_free_rowdata(SQLSOCK * sqlsocket, int colcount)
204 {
205         char **rowdata = sqlsocket->row;
206         int colindex;
207         
208         if (rowdata != NULL) {
209                 for (colindex = 0; colindex < colcount; colindex++) {
210                         if (rowdata[colindex] != NULL) {
211                                 free(rowdata[colindex]);
212                                 rowdata[colindex] = NULL;
213                         }
214                 }
215                 free(sqlsocket->row);
216                 sqlsocket->row = NULL;
217         }
218 }
219
220
221 /*************************************************************************
222  *
223  *      Function: sql_fetch_row
224  *
225  *      Purpose: database specific fetch_row. Returns a SQL_ROW struct
226  *               with all the data for the query in 'sqlsocket->row'. Returns
227  *               0 on success, -1 on failure, SQL_DOWN if database is down.
228  *
229  *************************************************************************/
230 static int sql_fetch_row(SQLSOCK * sqlsocket, SQL_CONFIG *config)
231 {
232         int returnCode = -1;
233         rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
234         const char *blob;
235         int blobLen;
236         int status;
237         int colindex = 0;
238         int colcount = 0;
239         int coltype = 0;
240         int colintvalue = 0;
241         int ret_blob_size = 0;
242         char **rowdata = NULL;
243         const unsigned char *textStr;
244         char intStr[256];
245         
246         status = sqlite3_step(sqlite_sock->pStmt);
247         radlog(L_DBG, "rlm_sql_sqlite: sqlite3_step = %d\n", status);
248         if (status == SQLITE_DONE) {
249                 sql_free_rowdata(sqlsocket, sqlite_sock->columnCount);
250                 return 0;
251         }
252         else if (status == SQLITE_ROW) {
253                 if (sqlite_sock->columnCount == 0) {
254                         sqlite_sock->columnCount = sql_num_fields(sqlsocket, config);
255                 }
256                 colcount = sqlite_sock->columnCount;
257                 if (colcount == 0)
258                         return -1;
259                 
260                 sql_free_rowdata(sqlsocket, colcount);
261                 
262                 ret_blob_size = sizeof(char *) * (colcount+1);
263                 rowdata = (char **)rad_malloc(ret_blob_size);           /* Space for pointers */
264                 if (rowdata != NULL) {
265                         memset(rowdata, 0, ret_blob_size);                              /* NULL-pad the pointers */
266                         sqlsocket->row = rowdata;
267                 }
268                 
269                 for (colindex = 0; colindex < colcount; colindex++)
270                 {
271                         coltype = sqlite3_column_type(sqlite_sock->pStmt, colindex);
272                         switch (coltype)
273                         {
274                                 case SQLITE_INTEGER:
275                                         colintvalue = sqlite3_column_int(sqlite_sock->pStmt, colindex);
276                                         snprintf(intStr, sizeof(intStr), "%d", colintvalue);
277                                         rowdata[colindex] = strdup(intStr);
278                                         break;
279                                         
280                                 case SQLITE_TEXT:
281                                         textStr = sqlite3_column_text(sqlite_sock->pStmt, colindex);
282                                         if (textStr != NULL)
283                                                 rowdata[colindex] = strdup((const char *)textStr);
284                                         break;
285                                         
286                                 case SQLITE_BLOB:
287                                         blob = sqlite3_column_blob(sqlite_sock->pStmt, colindex);
288                                         if (blob != NULL) {
289                                                 blobLen = sqlite3_column_bytes(sqlite_sock->pStmt, colindex);
290                                                 rowdata[colindex] = (char *)rad_malloc(blobLen + 1);
291                                                 if (rowdata[colindex] != NULL) {
292                                                         memcpy(rowdata[colindex], blob, blobLen);
293                                                 }
294                                         }
295                                         break;
296                                         
297                                 default:
298                                         break;
299                         }
300                 }
301                 
302                 returnCode = 0;
303         }
304         
305         return returnCode;
306 }
307
308
309 /*************************************************************************
310  *
311  *      Function: sql_free_result
312  *
313  *      Purpose: database specific free_result. Frees memory allocated
314  *               for a result set
315  *
316  *************************************************************************/
317 static int sql_free_result(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
318 {
319         int status = 0;
320         rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
321         
322         if (sqlite_sock->pStmt != NULL) {
323                 sql_free_rowdata(sqlsocket, sqlite_sock->columnCount);
324                 status = sqlite3_finalize(sqlite_sock->pStmt);
325                 sqlite_sock->pStmt = NULL;
326                 radlog(L_DBG, "rlm_sql_sqlite: sqlite3_finalize() = %d\n", status);
327         }
328         
329         return status;
330 }
331
332
333 /*************************************************************************
334  *
335  *      Function: sql_error
336  *
337  *      Purpose: database specific error. Returns error associated with
338  *               connection
339  *
340  *************************************************************************/
341 static const char *sql_error(UNUSED SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
342 {
343         return NULL;
344 }
345
346
347 /*************************************************************************
348  *
349  *      Function: sql_close
350  *
351  *      Purpose: database specific close. Closes an open database
352  *               connection
353  *
354  *************************************************************************/
355 static int sql_close(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
356 {
357         int status = 0;
358         rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
359         
360         if (sqlite_sock && sqlite_sock->pDb) {
361                 status = sqlite3_close(sqlite_sock->pDb);
362                 sqlite_sock->pDb = NULL;
363         }
364         
365         return status;
366 }
367
368
369 /*************************************************************************
370  *
371  *      Function: sql_finish_query
372  *
373  *      Purpose: End the query, such as freeing memory
374  *
375  *************************************************************************/
376 static int sql_finish_query(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
377 {
378         int status = 0;
379         rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
380
381         if (sqlite_sock->pStmt) {
382                 status = sqlite3_finalize(sqlite_sock->pStmt);
383                 sqlite_sock->pStmt = NULL;
384                 radlog(L_DBG, "rlm_sql_sqlite: sqlite3_finalize() = %d\n", status);
385         }
386         
387         return status;
388 }
389
390
391 /*************************************************************************
392  *
393  *      Function: sql_finish_select_query
394  *
395  *      Purpose: End the select query, such as freeing memory or result
396  *
397  *************************************************************************/
398 static int sql_finish_select_query(SQLSOCK * sqlsocket, SQL_CONFIG *config)
399 {
400         return sql_finish_query(sqlsocket, config);
401 }
402
403
404 /*************************************************************************
405  *
406  *      Function: sql_affected_rows
407  *
408  *      Purpose: End the select query, such as freeing memory or result
409  *
410  *************************************************************************/
411 static int sql_affected_rows(UNUSED SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
412 {
413         return 0;
414 }
415
416
417 /* Exported to rlm_sql */
418 rlm_sql_module_t rlm_sql_sqlite = {
419         "rlm_sql_sqlite",
420         sql_init_socket,
421         sql_destroy_socket,
422         sql_query,
423         sql_select_query,
424         sql_store_result,
425         sql_num_fields,
426         sql_num_rows,
427         sql_fetch_row,
428         sql_free_result,
429         sql_error,
430         sql_close,
431         sql_finish_query,
432         sql_finish_select_query,
433         sql_affected_rows
434 };