1 /* cvm/cvm-sqlite.c - SQLite CVM
2 * Copyright (C) 2010 Bruce Guenter <bruce@untroubled.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Placed into the public domain by Wayne Marshall <wcm@guinix.com>
19 */
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sqlite3.h>
24
25 #include <bglibs/str.h>
26 #include "module.h"
27 #include <bglibs/msg.h>
28
29 #include "sql.h"
30
31 const char program[] = "cvm-sqlite";
32
33 const char sql_query_var[] = "CVM_SQLITE_QUERY";
34 const char sql_pwcmp_var[] = "CVM_SQLITE_PWCMP";
35 const char sql_postq_var[] = "CVM_SQLITE_POSTQ";
36
37 #define MAX_NFIELDS 12
38
39 /* struct for one row of query result: */
40 struct sql_row {
41 int nfields;
42 const char* data[MAX_NFIELDS];
43 };
44
45 /* variables in scope of this file: */
46 static const char *dbfile;
47 static sqlite3 *db;
48 static int result_rows;
49 static struct sql_row row;
50
51 /*
52 ** sqlite3 query callback interface
53 **
54 ** * called for each row in query result
55 ** * cvm design assumes/requires only one row returned per query
56 ** * return of more than one row results in: error #100 (Credentials rejected)
57 **
58 */
my_callback(void * callback_arg,int nfields,char ** data,char ** field_names)59 static int my_callback(void *callback_arg, int nfields, char **data, char **field_names)
60 {
61 int i;
62 row.nfields = nfields;
63 for (i = 0; i < MAX_NFIELDS && i < nfields; ++i) {
64 if (row.data[i] != NULL)
65 free((char*)row.data[i]);
66 if (data[i] != NULL)
67 if ((data[i] = strdup(data[i])) == NULL)
68 return 1;
69 row.data[i] = data[i];
70 }
71 ++result_rows;
72 return 0;
73 (void)callback_arg;
74 (void)field_names;
75 }
76
77
sql_auth_init(void)78 int sql_auth_init(void)
79 {
80 int err = 0;
81
82 dbfile = getenv("CVM_SQLITE_DB");
83 if(dbfile == NULL)
84 return CVME_CONFIG;
85
86 err = sqlite3_open(dbfile, &db);
87 if(err != SQLITE_OK)
88 return CVME_IO;
89
90 err = sqlite3_busy_timeout(db, 1000);
91 if(err != SQLITE_OK)
92 return CVME_FATAL;
93
94 result_rows = 0;
95 return 0;
96 }
97
98
sql_auth_query(const str * query)99 int sql_auth_query(const str *query)
100 {
101 int err = 0;
102
103 result_rows = 0;
104 err = sqlite3_exec(db, query->s, &my_callback, NULL, NULL);
105 if(err != SQLITE_OK) return -(CVME_IO | CVME_FATAL);
106
107 return result_rows;
108 }
109
110
111 /* XXX, not sure how this might be used: */
sql_post_query(const str * query)112 int sql_post_query(const str *query)
113 {
114 return 0;
115 (void)query;
116 }
117
118
119 /*
120 ** NOTE:
121 **
122 ** cvm design assumes/requires credential query to select fields
123 ** in an exact specific order
124 **
125 ** that is, field names don't matter
126 ** what matters is field order in the result set
127 **
128 ** btw, defining CVM_SQLITE_QUERY in the module environment is *required*
129 ** that is, no default query is provided
130 **
131 */
sql_get_field(int n)132 const char * sql_get_field(int n)
133 {
134 return (n < row.nfields ? row.data[n] : NULL);
135 }
136
137
sql_auth_stop(void)138 void sql_auth_stop(void)
139 {
140 sqlite3_close(db);
141 return;
142 }
143
144
145 /* cvm-sqlite.c: EOF */
146