52550007e5eeb3d5d493986884b6185cfd32ad52
[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 buffer[2048];
53         
54         if (!sqlsocket->conn) {
55                 sqlsocket->conn = (rlm_sql_sqlite_sock *)rad_malloc(sizeof(rlm_sql_sqlite_sock));
56                 if (!sqlsocket->conn) {
57                         return -1;
58                 }
59         }
60         sqlite_sock = sqlsocket->conn;
61         memset(sqlite_sock, 0, sizeof(rlm_sql_sqlite_sock));
62         
63         snprintf(buffer, sizeof(buffer), "%s/sqlite_radius_client_database",
64                  radius_dir);
65         radlog(L_INFO, "rlm_sql_sqlite: Opening sqlite database %s for #%d",
66                         buffer, sqlsocket->id);
67         
68         status = sqlite3_open(buffer, &sqlite_sock->pDb);
69         radlog(L_INFO, "rlm_sql_sqlite: sqlite3_open() = %d\n", status);
70         return (status != SQLITE_OK) * -1;
71 }
72
73
74 /*************************************************************************
75  *
76  *      Function: sql_destroy_socket
77  *
78  *      Purpose: Free socket and any private connection data
79  *
80  *************************************************************************/
81 static int sql_destroy_socket(SQLSOCK *sqlsocket, UNUSED SQL_CONFIG *config)
82 {
83         int status = 0;
84         rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
85
86         if (sqlite_sock && sqlite_sock->pDb) {
87                 status = sqlite3_close(sqlite_sock->pDb);
88                 radlog(L_INFO, "rlm_sql_sqlite: sqlite3_close() = %d\n", status);
89         }
90         else {
91                 radlog(L_INFO, "rlm_sql_sqlite: sql_destroy_socket noop.\n");
92         }
93         
94         return 0;
95 }
96
97
98 /*************************************************************************
99  *
100  *      Function: sql_query
101  *
102  *      Purpose: Issue a query to the database
103  *
104  *************************************************************************/
105 static int sql_query(SQLSOCK * sqlsocket, SQL_CONFIG *config, char *querystr)
106 {
107         int status;
108         rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
109         const char *zTail;
110         
111         if (config->sqltrace)
112                 radlog(L_DBG,"rlm_sql_sqlite: query:  %s", querystr);
113         if (sqlite_sock->pDb == NULL) {
114                 radlog(L_ERR, "rlm_sql_sqlite: Socket not connected");
115                 return SQL_DOWN;
116         }
117         
118         status = sqlite3_prepare(sqlite_sock->pDb, querystr, strlen(querystr), &sqlite_sock->pStmt, &zTail);
119         radlog(L_DBG, "rlm_sql_sqlite: sqlite3_prepare() = %d\n", status);
120         sqlite_sock->columnCount = 0;
121         
122         return (status == SQLITE_OK) ? 0 : SQL_DOWN;
123 }
124
125
126 /*************************************************************************
127  *
128  *      Function: sql_select_query
129  *
130  *      Purpose: Issue a select query to the database
131  *
132  *************************************************************************/
133 static int sql_select_query(SQLSOCK *sqlsocket, SQL_CONFIG *config,
134                             char *querystr)
135 {
136         if (strstr(querystr, "nas") != NULL)
137                 return sql_query(sqlsocket, config, querystr);
138                 
139         return 0;
140 }
141
142
143 /*************************************************************************
144  *
145  *      Function: sql_store_result
146  *
147  *      Purpose: database specific store_result function. Returns a result
148  *               set for the query.
149  *
150  *************************************************************************/
151 static int sql_store_result(UNUSED SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
152 {
153         return 0;
154 }
155
156
157 /*************************************************************************
158  *
159  *      Function: sql_num_fields
160  *
161  *      Purpose: database specific num_fields function. Returns number
162  *               of columns from query
163  *
164  *************************************************************************/
165 static int sql_num_fields(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
166 {
167         rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
168         
169         if (sqlite_sock->pStmt)
170                 return sqlite3_column_count(sqlite_sock->pStmt);
171         
172         return 0;
173 }
174
175
176 /*************************************************************************
177  *
178  *      Function: sql_num_rows
179  *
180  *      Purpose: database specific num_rows. Returns number of rows in
181  *               query
182  *
183  *************************************************************************/
184 static int sql_num_rows(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
185 {
186         rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
187         
188         if (sqlite_sock->pStmt)
189                 return sqlite3_data_count(sqlite_sock->pStmt);
190         
191         return 0;
192 }
193
194
195 /*************************************************************************
196  *      Function: sql_free_rowdata
197  *************************************************************************/
198 static void sql_free_rowdata(SQLSOCK * sqlsocket, int colcount)
199 {
200         char **rowdata = sqlsocket->row;
201         int colindex;
202         
203         if (rowdata != NULL) {
204                 for (colindex = 0; colindex < colcount; colindex++) {
205                         if (rowdata[colindex] != NULL) {
206                                 free(rowdata[colindex]);
207                                 rowdata[colindex] = NULL;
208                         }
209                 }
210                 free(sqlsocket->row);
211                 sqlsocket->row = NULL;
212         }
213 }
214
215
216 /*************************************************************************
217  *
218  *      Function: sql_fetch_row
219  *
220  *      Purpose: database specific fetch_row. Returns a SQL_ROW struct
221  *               with all the data for the query in 'sqlsocket->row'. Returns
222  *               0 on success, -1 on failure, SQL_DOWN if database is down.
223  *
224  *************************************************************************/
225 static int sql_fetch_row(SQLSOCK * sqlsocket, SQL_CONFIG *config)
226 {
227         int returnCode = -1;
228         rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
229         const char *blob;
230         int blobLen;
231         int status;
232         int colindex = 0;
233         int colcount = 0;
234         int coltype = 0;
235         int colintvalue = 0;
236         int ret_blob_size = 0;
237         char **rowdata = NULL;
238         const unsigned char *textStr;
239         char intStr[256];
240         
241         status = sqlite3_step(sqlite_sock->pStmt);
242         radlog(L_DBG, "rlm_sql_sqlite: sqlite3_step = %d\n", status);
243         if (status == SQLITE_DONE) {
244                 sql_free_rowdata(sqlsocket, sqlite_sock->columnCount);
245                 return 0;
246         }
247         else if (status == SQLITE_ROW) {
248                 if (sqlite_sock->columnCount == 0) {
249                         sqlite_sock->columnCount = sql_num_fields(sqlsocket, config);
250                 }
251                 colcount = sqlite_sock->columnCount;
252                 if (colcount == 0)
253                         return -1;
254                 
255                 sql_free_rowdata(sqlsocket, colcount);
256                 
257                 ret_blob_size = sizeof(char *) * (colcount+1);
258                 rowdata = (char **)rad_malloc(ret_blob_size);           /* Space for pointers */
259                 if (rowdata != NULL) {
260                         memset(rowdata, 0, ret_blob_size);                              /* NULL-pad the pointers */
261                         sqlsocket->row = rowdata;
262                 }
263                 
264                 for (colindex = 0; colindex < colcount; colindex++)
265                 {
266                         coltype = sqlite3_column_type(sqlite_sock->pStmt, colindex);
267                         switch (coltype)
268                         {
269                                 case SQLITE_INTEGER:
270                                         colintvalue = sqlite3_column_int(sqlite_sock->pStmt, colindex);
271                                         snprintf(intStr, sizeof(intStr), "%d", colintvalue);
272                                         rowdata[colindex] = strdup(intStr);
273                                         break;
274                                         
275                                 case SQLITE_TEXT:
276                                         textStr = sqlite3_column_text(sqlite_sock->pStmt, colindex);
277                                         if (textStr != NULL)
278                                                 rowdata[colindex] = strdup((const char *)textStr);
279                                         break;
280                                         
281                                 case SQLITE_BLOB:
282                                         blob = sqlite3_column_blob(sqlite_sock->pStmt, colindex);
283                                         if (blob != NULL) {
284                                                 blobLen = sqlite3_column_bytes(sqlite_sock->pStmt, colindex);
285                                                 rowdata[colindex] = (char *)rad_malloc(blobLen + 1);
286                                                 if (rowdata[colindex] != NULL) {
287                                                         memcpy(rowdata[colindex], blob, blobLen);
288                                                 }
289                                         }
290                                         break;
291                                         
292                                 default:
293                                         break;
294                         }
295                 }
296                 
297                 returnCode = 0;
298         }
299         
300         return returnCode;
301 }
302
303
304 /*************************************************************************
305  *
306  *      Function: sql_free_result
307  *
308  *      Purpose: database specific free_result. Frees memory allocated
309  *               for a result set
310  *
311  *************************************************************************/
312 static int sql_free_result(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
313 {
314         int status = 0;
315         rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
316         
317         if (sqlite_sock->pStmt != NULL) {
318                 sql_free_rowdata(sqlsocket, sqlite_sock->columnCount);
319                 status = sqlite3_finalize(sqlite_sock->pStmt);
320                 sqlite_sock->pStmt = NULL;
321                 radlog(L_DBG, "rlm_sql_sqlite: sqlite3_finalize() = %d\n", status);
322         }
323         
324         return status;
325 }
326
327
328 /*************************************************************************
329  *
330  *      Function: sql_error
331  *
332  *      Purpose: database specific error. Returns error associated with
333  *               connection
334  *
335  *************************************************************************/
336 static const char *sql_error(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
337 {
338         return NULL;
339 }
340
341
342 /*************************************************************************
343  *
344  *      Function: sql_close
345  *
346  *      Purpose: database specific close. Closes an open database
347  *               connection
348  *
349  *************************************************************************/
350 static int sql_close(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
351 {
352         int status = 0;
353         rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
354         
355         if (sqlite_sock && sqlite_sock->pDb) {
356                 status = sqlite3_close(sqlite_sock->pDb);
357                 sqlite_sock->pDb = NULL;
358         }
359         
360         return status;
361 }
362
363
364 /*************************************************************************
365  *
366  *      Function: sql_finish_query
367  *
368  *      Purpose: End the query, such as freeing memory
369  *
370  *************************************************************************/
371 static int sql_finish_query(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
372 {
373         int status = 0;
374         rlm_sql_sqlite_sock *sqlite_sock = sqlsocket->conn;
375
376         if (sqlite_sock->pStmt) {
377                 status = sqlite3_finalize(sqlite_sock->pStmt);
378                 sqlite_sock->pStmt = NULL;
379                 radlog(L_DBG, "rlm_sql_sqlite: sqlite3_finalize() = %d\n", status);
380         }
381         
382         return status;
383 }
384
385
386 /*************************************************************************
387  *
388  *      Function: sql_finish_select_query
389  *
390  *      Purpose: End the select query, such as freeing memory or result
391  *
392  *************************************************************************/
393 static int sql_finish_select_query(SQLSOCK * sqlsocket, SQL_CONFIG *config)
394 {
395         return sql_finish_query(sqlsocket, config);
396 }
397
398
399 /*************************************************************************
400  *
401  *      Function: sql_affected_rows
402  *
403  *      Purpose: End the select query, such as freeing memory or result
404  *
405  *************************************************************************/
406 static int sql_affected_rows(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
407 {
408         return 0;
409 }
410
411
412 /* Exported to rlm_sql */
413 rlm_sql_module_t rlm_sql_sqlite = {
414         "rlm_sql_sqlite",
415         sql_init_socket,
416         sql_destroy_socket,
417         sql_query,
418         sql_select_query,
419         sql_store_result,
420         sql_num_fields,
421         sql_num_rows,
422         sql_fetch_row,
423         sql_free_result,
424         sql_error,
425         sql_close,
426         sql_finish_query,
427         sql_finish_select_query,
428         sql_affected_rows
429 };