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 as published by
4  *   the Free Software Foundation; either version 2 of the License, or (at
5  *   your option) any later version.
6  *
7  *   This program is distributed in the hope that it will be useful,
8  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *   GNU General Public License for more details.
11  *
12  *   You should have received a copy of the GNU General Public License
13  *   along with this program; if not, write to the Free Software
14  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: 5af8db40905fa83358081d70b1525090c77d8e1e $
19  * @file rlm_sql.h
20  * @brief Prototypes and functions for the SQL module
21  *
22  * @copyright 2012-2014  Arran Cudbard-Bell <a.cudbardb@freeradius.org>
23  * @copyright 2000,2006  The FreeRADIUS server project
24  * @copyright 2000  Mike Machado <mike@innercite.com>
25  * @copyright 2000  Alan DeKok <aland@ox.org>
26  */
27 #ifndef _RLM_SQL_H
28 #define _RLM_SQL_H
29 
30 RCSIDH(rlm_sql_h, "$Id: 5af8db40905fa83358081d70b1525090c77d8e1e $")
31 
32 #include <freeradius-devel/radiusd.h>
33 #include <freeradius-devel/connection.h>
34 #include <freeradius-devel/modpriv.h>
35 #include <freeradius-devel/exfile.h>
36 
37 #define MOD_PREFIX "rlm_sql"
38 
39 #define PW_ITEM_CHECK 0
40 #define PW_ITEM_REPLY 1
41 
42 
43 /* SQL Errors */
44 typedef enum {
45 	RLM_SQL_QUERY_INVALID = -3,	//!< Query syntax error.
46 	RLM_SQL_ERROR = -2,		//!< General connection/server error.
47 	RLM_SQL_OK = 0,			//!< Success.
48 	RLM_SQL_RECONNECT = 1,		//!< Stale connection, should reconnect.
49 	RLM_SQL_ALT_QUERY,		//!< Key constraint violation, use an alternative query.
50 	RLM_SQL_NO_MORE_ROWS,		//!< No more rows available
51 } sql_rcode_t;
52 
53 typedef enum {
54 	FALL_THROUGH_NO = 0,
55 	FALL_THROUGH_YES,
56 	FALL_THROUGH_DEFAULT,
57 } sql_fall_through_t;
58 
59 
60 typedef char **rlm_sql_row_t;
61 
62 typedef struct sql_log_entry {
63 	log_type_t	type;		//!< Type of log entry L_ERR, L_WARN, L_INFO, L_DBG etc..
64 	char const	*msg;		//!< Log message.
65 } sql_log_entry_t;
66 
67 /*
68  * Sections where we dynamically resolve the config entry to use,
69  * by xlating reference.
70  */
71 typedef struct sql_acct_section {
72 	CONF_SECTION		*cs;				//!< The CONF_SECTION representing the group
73 								//!< of queries to process.
74 
75 	char const		*reference;			//!< Reference string, expanded to point to
76 								//!< a group of queries.
77 	bool			reference_cp;
78 
79 	char const		*logfile;
80 
81 	char const		*query;	/* for xlat parsing */
82 } sql_acct_section_t;
83 
84 typedef struct sql_config {
85 	char const 		*sql_driver_name;		//!< SQL driver module name e.g. rlm_sql_sqlite.
86 	char const 		*sql_server;			//!< Server to connect to.
87 	uint32_t 		sql_port;			//!< Port to connect to.
88 	char const 		*sql_login;			//!< Login credentials to use.
89 	char const 		*sql_password;			//!< Login password to use.
90 	char const 		*sql_db;			//!< Database to run queries against.
91 
92 	char const		*query_user;			//!< xlat expansion used to specify the user
93 								//!< to use as the subject of queries.
94 
95 	char const		*default_profile;		//!< Default profile to use if no other
96 								//!< profiles were configured.
97 
98 	char const		*client_query;			//!< Query used to get FreeRADIUS client
99 								//!< definitions.
100 
101 	char const		*authorize_check_query;		//!< Query used get check VPs for a user.
102 	char const 		*authorize_reply_query;		//!< Query used get reply VPs for a user.
103 	char const		*authorize_group_check_query;	//!< Query used get check VPs for a group.
104 	char const		*authorize_group_reply_query;	//!< Query used get reply VPs for a group.
105 	char const		*simul_count_query;		//!< Query used get number of active sessions
106 								//!< for a user (basic simultaneous use check).
107 	char const		*simul_verify_query;		//!< Query to get active sessions for a user
108 								//!< the result is fed to session_zap.
109 	char const 		*groupmemb_query;		//!< Query to determine group membership.
110 
111 	bool			do_clients;			//!< Read clients from SQL database.
112 	bool			read_groups;			//!< Read user groups by default.
113 								//!< If false, Fall-Through = yes is required
114 								//!< in the previous reply list to process
115 								//!< groups.
116 	bool			read_profiles;			//!< Read user profiles by default.
117 								//!< If false, Fall-Through = yes is required
118 								//!< in the previous reply list to process
119 								//!< profiles.
120 	char const		*logfile;			//!< Keep a log of all SQL queries executed
121 								//!< Useful for batch insertion with the
122 								//!< NULL drivers.
123 
124 	bool			delete_stale_sessions;		//!< Whether we should use session_zap to create
125 								//!< a fake stop packet, to terminate any
126 								//!< stale sessions.
127 
128 	char const		*allowed_chars;			//!< Chars which done need escaping..
129 	bool			driver_specific_escape;		//!< Use the driver specific SQL escape method
130 	uint32_t		query_timeout;			//!< How long to allow queries to run for.
131 
132 	char const		*connect_query;			//!< Query executed after establishing
133 								//!< new connection.
134 	struct timeval		connect_timeout_tv;		//!< Connection timeout timeval.
135 	uint32_t		connect_timeout_ms;		//!< Connection timeout ms.
136 	uint32_t		connect_timeout_s;		//!< Connection timeout in seconds.
137 
138 	void			*driver;			//!< Where drivers should write a
139 								//!< pointer to their configurations.
140 
141 	/*
142 	 *	@todo The rest of the queries should also be moved into
143 	 *	their own sections.
144 	 */
145 
146 	/*
147 	 *	Section configurations
148 	 */
149 	sql_acct_section_t	postauth;
150 	sql_acct_section_t	accounting;
151 } rlm_sql_config_t;
152 
153 typedef struct sql_inst rlm_sql_t;
154 
155 typedef struct rlm_sql_handle {
156 	void			*conn;				//!< Database specific connection handle.
157 	rlm_sql_row_t		row;				//!< Row data from the last query.
158 	rlm_sql_t		*inst;				//!< The rlm_sql instance this connection belongs to.
159 	TALLOC_CTX		*log_ctx;			//!< Talloc pool used to avoid mallocing memory on
160 								//!< when log strings need to be copied.
161 } rlm_sql_handle_t;
162 
163 extern const FR_NAME_NUMBER sql_rcode_table[];
164 /*
165  *	Capabilities flags for drivers
166  */
167 #define RLM_SQL_RCODE_FLAGS_ALT_QUERY	1			//!< Can distinguish between other errors and those
168 								//!< resulting from a unique key violation.
169 
170 /** Retrieve errors from the last query operation
171  *
172  * @note Buffers allocated in the context provided will be automatically freed. The driver
173  *	should not free these buffers explicitly.
174  * @note If the driver uses its own buffers to aggregate messages, they should be cleared
175  *	on sql_query_finish, and after each call to sql_error, to prevent the same messages
176  *	being printed multiple times.
177  *
178  * @param[in,out] ctx to allocate any buffers required. If static buffers are provided by the
179  *	driver they need not be strduped, just write the pointer to those buffers to the .msg
180  *	field of a sql_log_entry_t element.
181  * @param[out] out a pre-allocated array of log entries to fill. Need not be NULL terminated.
182  * @param[in] outlen Number of log entries available for populating. Do not write to index
183  *	out[outlen] or higher.
184  * @param[in] handle to retrieve errors from.
185  * @param[in] config of the SQL instance.
186  * @return
187  *	0  - If no error messages are available.
188  *	>0 - Number of log entries
189  */
190 typedef size_t (*sql_error_t)(TALLOC_CTX *ctx, sql_log_entry_t out[], size_t outlen, rlm_sql_handle_t *handle,
191 			      rlm_sql_config_t *config);
192 
193 typedef struct rlm_sql_module_t {
194 	char const	*name;
195 	int		flags;
196 
197 	sql_rcode_t (*mod_instantiate)(CONF_SECTION *conf, rlm_sql_config_t *config);
198 	sql_rcode_t (*sql_socket_init)(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
199 
200 	sql_rcode_t (*sql_query)(rlm_sql_handle_t *handle, rlm_sql_config_t *config, char const *query);
201 	sql_rcode_t (*sql_select_query)(rlm_sql_handle_t *handle, rlm_sql_config_t *config, char const *query);
202 	sql_rcode_t (*sql_store_result)(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
203 
204 	int (*sql_num_fields)(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
205 	int (*sql_num_rows)(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
206 	int (*sql_affected_rows)(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
207 
208 	sql_rcode_t (*sql_fetch_row)(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
209 	sql_rcode_t (*sql_free_result)(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
210 
211 	sql_error_t	sql_error;				//!< Get any errors from the previous query.
212 
213 	sql_rcode_t (*sql_finish_query)(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
214 	sql_rcode_t (*sql_finish_select_query)(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
215 
216 	xlat_escape_t	sql_escape_func;
217 } rlm_sql_module_t;
218 
219 struct sql_inst {
220 	rlm_sql_config_t	myconfig; /* HACK */
221 	fr_connection_pool_t	*pool;
222 	rlm_sql_config_t	*config;
223 	CONF_SECTION		*cs;
224 
225 	DICT_ATTR const		*sql_user;		//!< Cached pointer to SQL-User-Name
226 							//!< dictionary attribute.
227 	exfile_t		*ef;
228 
229 	void			*handle;
230 	rlm_sql_module_t	*module;
231 
232 	int (*sql_set_user)(rlm_sql_t *inst, REQUEST *request, char const *username);
233 	size_t (*sql_escape_func)(REQUEST *, char *out, size_t outlen, char const *in, void *arg);
234 	sql_rcode_t (*sql_query)(rlm_sql_t *inst, REQUEST *request, rlm_sql_handle_t **handle, char const *query);
235 	sql_rcode_t (*sql_select_query)(rlm_sql_t *inst, REQUEST *request, rlm_sql_handle_t **handle, char const *query);
236 	sql_rcode_t (*sql_fetch_row)(rlm_sql_t *inst, REQUEST *request, rlm_sql_handle_t **handle);
237 
238 	char const		*name;			//!< Module instance name.
239 	DICT_ATTR const		*group_da;
240 };
241 
242 typedef struct sql_grouplist {
243 	char			*name;
244 	struct sql_grouplist	*next;
245 } rlm_sql_grouplist_t;
246 
247 int		sql_fr_pair_list_afrom_str(TALLOC_CTX *ctx, REQUEST *request, VALUE_PAIR **first_pair, rlm_sql_row_t row);
248 int		sql_read_realms(rlm_sql_handle_t *handle);
249 int		sql_getvpdata(TALLOC_CTX *ctx, rlm_sql_t *inst, REQUEST *request, rlm_sql_handle_t **handle, VALUE_PAIR **pair, char const *query);
250 int		sql_read_clients(rlm_sql_handle_t *handle);
251 int		sql_dict_init(rlm_sql_handle_t *handle);
252 void 		CC_HINT(nonnull (1, 2, 4)) rlm_sql_query_log(rlm_sql_t *inst, REQUEST *request, sql_acct_section_t *section, char const *query);
253 sql_rcode_t	CC_HINT(nonnull (1, 3, 4)) rlm_sql_select_query(rlm_sql_t *inst, REQUEST *request, rlm_sql_handle_t **handle, char const *query);
254 sql_rcode_t	CC_HINT(nonnull (1, 3, 4)) rlm_sql_query(rlm_sql_t *inst, REQUEST *request, rlm_sql_handle_t **handle, char const *query);
255 int		rlm_sql_fetch_row(rlm_sql_t *inst, REQUEST *request, rlm_sql_handle_t **handle);
256 void		rlm_sql_print_error(rlm_sql_t *inst, REQUEST *request, rlm_sql_handle_t *handle, bool force_debug);
257 int		sql_set_user(rlm_sql_t *inst, REQUEST *request, char const *username);
258 #endif
259