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 #define CURL_NO_OLDIES 1
32 #include <curl/curl.h>
35 # if defined(HAVE_JSONMC_JSON_H)
36 # include <json-c/json.h>
37 # elif defined(HAVE_JSON_JSON_H)
38 # 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
48 HTTP_METHOD_UNKNOWN = 0,
54 HTTP_METHOD_CUSTOM //!< Must always come last, should not be in method table
58 HTTP_BODY_UNKNOWN = 0,
59 HTTP_BODY_UNSUPPORTED,
60 HTTP_BODY_UNAVAILABLE,
63 HTTP_BODY_CUSTOM_XLAT,
64 HTTP_BODY_CUSTOM_LITERAL,
75 HTTP_AUTH_UNKNOWN = 0,
81 HTTP_AUTH_GSSNEGOTIATE,
90 * Must be updated (in rest.c) if additional values are added to
93 extern const http_body_type_t http_body_type_supported[HTTP_BODY_NUM_ENTRIES];
95 extern const unsigned long http_curl_auth[HTTP_AUTH_NUM_ENTRIES];
97 extern const FR_NAME_NUMBER http_auth_table[];
99 extern const FR_NAME_NUMBER http_method_table[];
101 extern const FR_NAME_NUMBER http_body_type_table[];
103 extern const FR_NAME_NUMBER http_content_type_table[];
106 * Structure for section configuration
108 typedef struct rlm_rest_section_t {
109 char const *name; //!< Section name.
110 char const *uri; //!< URI to send HTTP request to.
112 char const *method_str; //!< The string version of the HTTP method.
113 http_method_t method; //!< What HTTP method should be used, GET, POST etc...
115 char const *body_str; //!< The string version of the encoding/content type.
116 http_body_type_t body; //!< What encoding type should be used.
118 char const *force_to_str; //!< Force decoding with this decoder.
119 http_body_type_t force_to; //!< Override the Content-Type header in the response
120 //!< to force decoding as a particular type.
122 char const *data; //!< Custom body data (optional).
124 char const *auth_str; //!< The string version of the Auth-Type.
125 http_auth_type_t auth; //!< HTTP auth type.
126 bool require_auth; //!< Whether HTTP-Auth is required or not.
127 char const *username; //!< Username used for HTTP-Auth
128 char const *password; //!< Password used for HTTP-Auth
130 char const *tls_certificate_file;
131 char const *tls_private_key_file;
132 char const *tls_private_key_password;
133 char const *tls_ca_file;
134 char const *tls_ca_path;
135 char const *tls_random_file;
137 bool tls_check_cert_cn;
139 struct timeval timeout_tv; //!< Timeout timeval.
140 long timeout; //!< Timeout in ms.
141 uint32_t chunk; //!< Max chunk-size (mainly for testing the encoders)
142 } rlm_rest_section_t;
145 * Structure for module configuration
147 typedef struct rlm_rest_t {
148 char const *xlat_name; //!< Instance name.
150 char const *connect_uri; //!< URI we attempt to connect to, to pre-establish
151 //!< TCP connections.
153 struct timeval connect_timeout_tv; //!< Connection timeout timeval.
154 long connect_timeout; //!< Connection timeout ms.
156 fr_connection_pool_t *pool; //!< Pointer to the connection pool.
158 rlm_rest_section_t authorize; //!< Configuration specific to authorisation.
159 rlm_rest_section_t authenticate; //!< Configuration specific to authentication.
160 rlm_rest_section_t accounting; //!< Configuration specific to accounting.
161 rlm_rest_section_t checksimul; //!< Configuration specific to simultaneous session
163 rlm_rest_section_t post_auth; //!< Configuration specific to Post-auth
165 rlm_rest_section_t recv_coa; //!< Configuration specific to recv-coa
170 * States for stream based attribute encoders
174 READ_STATE_ATTR_BEGIN,
175 READ_STATE_ATTR_CONT,
181 * States for the response parser
184 WRITE_STATE_INIT = 0,
185 WRITE_STATE_PARSE_HEADERS,
186 WRITE_STATE_PARSE_CONTENT,
191 * Outbound data context (passed to CURLOPT_READFUNCTION as CURLOPT_READDATA)
193 typedef struct rlm_rest_request_t {
194 rlm_rest_t *instance; //!< This instance of rlm_rest.
195 REQUEST *request; //!< Current request.
196 read_state_t state; //!< Encoder state
198 vp_cursor_t cursor; //!< Cursor pointing to the start of the list to encode.
200 size_t chunk; //!< Chunk size
202 void *encoder; //!< Encoder specific data.
203 } rlm_rest_request_t;
206 * Curl inbound data context (passed to CURLOPT_WRITEFUNCTION and
207 * CURLOPT_HEADERFUNCTION as CURLOPT_WRITEDATA and CURLOPT_HEADERDATA)
209 typedef struct rlm_rest_response_t {
210 rlm_rest_t *instance; //!< This instance of rlm_rest.
211 REQUEST *request; //!< Current request.
212 write_state_t state; //!< Decoder state.
214 char *buffer; //!< Raw incoming HTTP data.
215 size_t alloc; //!< Space allocated for buffer.
216 size_t used; //!< Space used in buffer.
218 int code; //!< HTTP Status Code.
219 http_body_type_t type; //!< HTTP Content Type.
220 http_body_type_t force_to; //!< Force decoding the body type as a particular encoding.
222 void *decoder; //!< Decoder specific data.
223 } rlm_rest_response_t;
228 typedef struct rlm_rest_curl_context_t {
229 struct curl_slist *headers; //!< Any HTTP headers which will be sent with the
232 char *body; //!< Pointer to the buffer which contains body data/
233 //!< Only used when not performing chunked encoding.
235 rlm_rest_request_t request; //!< Request context data.
236 rlm_rest_response_t response; //!< Response context data.
237 } rlm_rest_curl_context_t;
240 * Connection API handle
242 typedef struct rlm_rest_handle_t {
243 void *handle; //!< Real Handle.
244 rlm_rest_curl_context_t *ctx; //!< Context.
248 * Function prototype for rest_read_wrapper. Matches CURL's
249 * CURLOPT_READFUNCTION prototype.
251 typedef size_t (*rest_read_t)(void *ptr, size_t size, size_t nmemb,
255 * Connection API callbacks
257 int rest_init(rlm_rest_t *instance);
259 void rest_cleanup(void);
261 void *mod_conn_create(TALLOC_CTX *ctx, void *instance);
263 int mod_conn_alive(void *instance, void *handle);
266 * Request processing API
268 int rest_request_config(rlm_rest_t *instance,
269 rlm_rest_section_t *section, REQUEST *request,
270 void *handle, http_method_t method,
271 http_body_type_t type, char const *uri,
272 char const *username, char const *password) CC_HINT(nonnull (1,2,3,4,7));
274 int rest_request_perform(rlm_rest_t *instance,
275 rlm_rest_section_t *section, REQUEST *request,
278 int rest_response_decode(rlm_rest_t *instance,
279 UNUSED rlm_rest_section_t *section, REQUEST *request,
282 void rest_response_error(REQUEST *request, rlm_rest_handle_t *handle);
284 void rest_request_cleanup(rlm_rest_t *instance, rlm_rest_section_t *section,
287 #define rest_get_handle_code(handle)(((rlm_rest_curl_context_t*)((rlm_rest_handle_t*)handle)->ctx)->response.code)
289 #define rest_get_handle_type(handle)(((rlm_rest_curl_context_t*)((rlm_rest_handle_t*)handle)->ctx)->response.type)
291 size_t rest_get_handle_data(char const **out, rlm_rest_handle_t *handle);
296 size_t rest_uri_escape(UNUSED REQUEST *request, char *out, size_t outlen, char const *raw, UNUSED void *arg);
297 ssize_t rest_uri_build(char **out, rlm_rest_t *instance, REQUEST *request, char const *uri);
298 ssize_t rest_uri_host_unescape(char **out, UNUSED rlm_rest_t *instance, REQUEST *request,
299 void *handle, char const *uri);