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