2 * This program 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
5 * (at your option) any later version.
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.
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
20 * @brief Function prototypes and datatypes for the REST (HTTP) transport.
23 * @copyright 2012-2014 Arran Cudbard-Bell <a.cudbard-bell@freeradius.org>
26 RCSIDH(other_h, "$Id$")
28 #include <freeradius-devel/connection.h>
31 #ifdef HAVE_JSON_JSONH
35 #define CURL_NO_OLDIES 1
36 #include <curl/curl.h>
39 #include <json/json.h>
42 #define REST_URI_MAX_LEN 2048
43 #define REST_BODY_MAX_LEN 8192
44 #define REST_BODY_INIT 1024
45 #define REST_BODY_MAX_ATTRS 256
56 HTTP_BODY_UNKNOWN = 0,
57 HTTP_BODY_UNSUPPORTED,
58 HTTP_BODY_UNAVAILABLE,
72 HTTP_AUTH_UNKNOWN = 0,
78 HTTP_AUTH_GSSNEGOTIATE,
87 * Must be updated (in rest.c) if additional values are added to
90 extern const http_body_type_t http_body_type_supported[HTTP_BODY_NUM_ENTRIES];
92 extern const unsigned long http_curl_auth[HTTP_AUTH_NUM_ENTRIES];
94 extern const FR_NAME_NUMBER http_auth_table[];
96 extern const FR_NAME_NUMBER http_method_table[];
98 extern const FR_NAME_NUMBER http_body_type_table[];
100 extern const FR_NAME_NUMBER http_content_type_table[];
103 * Structure for section configuration
105 typedef struct rlm_rest_section_t {
106 char const *name; //!< Section name.
107 char *uri; //!< URI to send HTTP request to.
109 char *method_str; //!< The string version of the HTTP method.
110 http_method_t method; //!< What HTTP method should be used, GET, POST etc...
112 char const *body_str; //!< The string version of the encoding/content type.
113 http_body_type_t body; //!< What encoding type should be used.
115 http_body_type_t force_to; //!< Override the Content-Type header in the response
116 //!< to force decoding as a particular type.
118 char *data; //!< Custom body data (optional).
120 char *auth_str; //!< The string version of the Auth-Type.
121 http_auth_type_t auth; //!< HTTP auth type.
122 bool require_auth; //!< Whether HTTP-Auth is required or not.
123 char *username; //!< Username used for HTTP-Auth
124 char *password; //!< Password used for HTTP-Auth
126 char *tls_certificate_file;
127 char *tls_private_key_file;
128 char *tls_private_key_password;
131 char *tls_random_file;
133 bool tls_check_cert_cn;
135 int timeout; //!< Timeout passed to CURL.
136 size_t chunk; //!< Max chunk-size (mainly for testing the encoders)
137 } rlm_rest_section_t;
140 * Structure for module configuration
142 typedef struct rlm_rest_t {
143 char const *xlat_name; //!< Instance name.
145 char *connect_uri; //!< URI we attempt to connect to, to pre-establish
146 //!< TCP connections.
148 fr_connection_pool_t *conn_pool; //!< Pointer to the connection pool.
150 rlm_rest_section_t authorize; //!< Configuration specific to authorisation.
151 rlm_rest_section_t authenticate; //!< Configuration specific to authentication.
152 rlm_rest_section_t accounting; //!< Configuration specific to accounting.
153 rlm_rest_section_t checksimul; //!< Configuration specific to simultaneous session
155 rlm_rest_section_t postauth; //!< Configuration specific to Post-auth
159 * States for stream based attribute encoders
163 READ_STATE_ATTR_BEGIN,
164 READ_STATE_ATTR_CONT,
169 * States for the response parser
172 WRITE_STATE_INIT = 0,
173 WRITE_STATE_PARSE_HEADERS,
174 WRITE_STATE_PARSE_CONTENT,
179 * Outbound data context (passed to CURLOPT_READFUNCTION as CURLOPT_READDATA)
181 typedef struct rlm_rest_request_t {
182 rlm_rest_t *instance; //!< This instance of rlm_rest.
183 REQUEST *request; //!< Current request.
184 read_state_t state; //!< Encoder state
186 vp_cursor_t cursor; //!< Cursor pointing to the start of the list to encode.
188 size_t chunk; //!< Chunk size
190 void *encoder; //!< Encoder specific data.
191 } rlm_rest_request_t;
194 * Curl inbound data context (passed to CURLOPT_WRITEFUNCTION and
195 * CURLOPT_HEADERFUNCTION as CURLOPT_WRITEDATA and CURLOPT_HEADERDATA)
197 typedef struct rlm_rest_response_t {
198 rlm_rest_t *instance; //!< This instance of rlm_rest.
199 REQUEST *request; //!< Current request.
200 write_state_t state; //!< Decoder state.
202 char *buffer; //!< Raw incoming HTTP data.
203 size_t alloc; //!< Space allocated for buffer.
204 size_t used; //!< Space used in buffer.
206 int code; //!< HTTP Status Code.
207 http_body_type_t type; //!< HTTP Content Type.
208 http_body_type_t force_to; //!< Force decoding the body type as a particular encoding.
210 void *decoder; //!< Decoder specific data.
211 } rlm_rest_response_t;
216 typedef struct rlm_rest_curl_context_t {
217 struct curl_slist *headers; //!< Any HTTP headers which will be sent with the
220 char *body; //!< Pointer to the buffer which contains body data/
221 //!< Only used when not performing chunked encoding.
223 rlm_rest_request_t request; //!< Request context data.
224 rlm_rest_response_t response; //!< Response context data.
225 } rlm_rest_curl_context_t;
228 * Connection API handle
230 typedef struct rlm_rest_handle_t {
231 void *handle; //!< Real Handle.
232 rlm_rest_curl_context_t *ctx; //!< Context.
236 * Function prototype for rest_read_wrapper. Matches CURL's
237 * CURLOPT_READFUNCTION prototype.
239 typedef size_t (*rest_read_t)(void *ptr, size_t size, size_t nmemb,
243 * Connection API callbacks
245 int rest_init(rlm_rest_t *instance);
247 void rest_cleanup(void);
249 void *mod_conn_create(void *instance);
251 int mod_conn_alive(void *instance, void *handle);
253 int mod_conn_delete(void *instance, void *handle);
256 * Request processing API
258 int rest_request_config(rlm_rest_t *instance,
259 rlm_rest_section_t *section, REQUEST *request,
260 void *handle, http_method_t method,
261 http_body_type_t type, char const *uri,
262 char const *username, char const *password) CC_HINT(nonnull (1,2,3,4,7));
264 int rest_request_perform(rlm_rest_t *instance,
265 rlm_rest_section_t *section, REQUEST *request,
268 int rest_response_decode(rlm_rest_t *instance,
269 UNUSED rlm_rest_section_t *section, REQUEST *request,
272 void rest_request_cleanup(rlm_rest_t *instance, rlm_rest_section_t *section,
275 #define rest_get_handle_code(handle)(((rlm_rest_curl_context_t*)((rlm_rest_handle_t*)handle)->ctx)->response.code)
277 #define rest_get_handle_type(handle)(((rlm_rest_curl_context_t*)((rlm_rest_handle_t*)handle)->ctx)->response.type)
279 size_t rest_get_handle_data(char const **out, rlm_rest_handle_t *handle);
284 size_t rest_uri_escape(UNUSED REQUEST *request, char *out, size_t outlen, char const *raw, UNUSED void *arg);
285 ssize_t rest_uri_build(char **out, rlm_rest_t *instance, REQUEST *request, char const *uri);
286 ssize_t rest_uri_host_unescape(char **out, UNUSED rlm_rest_t *instance, REQUEST *request,
287 void *handle, char const *uri);