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