Pass a threadsafe ctx into fr_connection_pool create callback
[freeradius.git] / src / modules / rlm_rest / rest.h
1 /*
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.
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$
19  *
20  * @brief Function prototypes and datatypes for the REST (HTTP) transport.
21  * @file rest.h
22  *
23  * @copyright 2012-2014  Arran Cudbard-Bell <a.cudbard-bell@freeradius.org>
24  */
25
26 RCSIDH(other_h, "$Id$")
27
28 #include <freeradius-devel/connection.h>
29 #include "config.h"
30
31 #ifdef HAVE_JSON_JSONH
32 #define HAVE_JSON
33 #endif
34
35 #define CURL_NO_OLDIES 1
36 #include <curl/curl.h>
37
38 #ifdef HAVE_JSON
39 #include <json/json.h>
40 #endif
41
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
46
47 typedef enum {
48         HTTP_METHOD_UNKNOWN = 0,
49         HTTP_METHOD_GET,
50         HTTP_METHOD_POST,
51         HTTP_METHOD_PUT,
52         HTTP_METHOD_DELETE,
53         HTTP_METHOD_CUSTOM              //!< Must always come last, should not be in method table
54 } http_method_t;
55
56 typedef enum {
57         HTTP_BODY_UNKNOWN = 0,
58         HTTP_BODY_UNSUPPORTED,
59         HTTP_BODY_UNAVAILABLE,
60         HTTP_BODY_INVALID,
61         HTTP_BODY_NONE,
62         HTTP_BODY_CUSTOM_XLAT,
63         HTTP_BODY_CUSTOM_LITERAL,
64         HTTP_BODY_POST,
65         HTTP_BODY_JSON,
66         HTTP_BODY_XML,
67         HTTP_BODY_YAML,
68         HTTP_BODY_HTML,
69         HTTP_BODY_PLAIN,
70         HTTP_BODY_NUM_ENTRIES
71 } http_body_type_t;
72
73 typedef enum {
74         HTTP_AUTH_UNKNOWN = 0,
75         HTTP_AUTH_NONE,
76         HTTP_AUTH_TLS_SRP,
77         HTTP_AUTH_BASIC,
78         HTTP_AUTH_DIGEST,
79         HTTP_AUTH_DIGEST_IE,
80         HTTP_AUTH_GSSNEGOTIATE,
81         HTTP_AUTH_NTLM,
82         HTTP_AUTH_NTLM_WB,
83         HTTP_AUTH_ANY,
84         HTTP_AUTH_ANY_SAFE,
85         HTTP_AUTH_NUM_ENTRIES
86 } http_auth_type_t;
87
88 /*
89  *      Must be updated (in rest.c) if additional values are added to
90  *      http_body_type_t
91  */
92 extern const http_body_type_t http_body_type_supported[HTTP_BODY_NUM_ENTRIES];
93
94 extern const unsigned long http_curl_auth[HTTP_AUTH_NUM_ENTRIES];
95
96 extern const FR_NAME_NUMBER http_auth_table[];
97
98 extern const FR_NAME_NUMBER http_method_table[];
99
100 extern const FR_NAME_NUMBER http_body_type_table[];
101
102 extern const FR_NAME_NUMBER http_content_type_table[];
103
104 /*
105  *      Structure for section configuration
106  */
107 typedef struct rlm_rest_section_t {
108         char const              *name;          //!< Section name.
109         char const              *uri;           //!< URI to send HTTP request to.
110
111         char const              *method_str;    //!< The string version of the HTTP method.
112         http_method_t           method;         //!< What HTTP method should be used, GET, POST etc...
113
114         char const              *body_str;      //!< The string version of the encoding/content type.
115         http_body_type_t        body;           //!< What encoding type should be used.
116
117         http_body_type_t        force_to;       //!< Override the Content-Type header in the response
118                                                 //!< to force decoding as a particular type.
119
120         char const              *data;          //!< Custom body data (optional).
121
122         char const              *auth_str;      //!< The string version of the Auth-Type.
123         http_auth_type_t        auth;           //!< HTTP auth type.
124         bool                    require_auth;   //!< Whether HTTP-Auth is required or not.
125         char const              *username;      //!< Username used for HTTP-Auth
126         char const              *password;      //!< Password used for HTTP-Auth
127
128         char const              *tls_certificate_file;
129         char const              *tls_private_key_file;
130         char const              *tls_private_key_password;
131         char const              *tls_ca_file;
132         char const              *tls_ca_path;
133         char const              *tls_random_file;
134         bool                    tls_check_cert;
135         bool                    tls_check_cert_cn;
136
137         uint32_t                timeout;        //!< Timeout passed to CURL.
138         uint32_t                chunk;          //!< Max chunk-size (mainly for testing the encoders)
139 } rlm_rest_section_t;
140
141 /*
142  *      Structure for module configuration
143  */
144 typedef struct rlm_rest_t {
145         char const              *xlat_name;     //!< Instance name.
146
147         char const              *connect_uri;   //!< URI we attempt to connect to, to pre-establish
148                                                 //!< TCP connections.
149
150         fr_connection_pool_t    *conn_pool;     //!< Pointer to the connection pool.
151
152         rlm_rest_section_t      authorize;      //!< Configuration specific to authorisation.
153         rlm_rest_section_t      authenticate;   //!< Configuration specific to authentication.
154         rlm_rest_section_t      accounting;     //!< Configuration specific to accounting.
155         rlm_rest_section_t      checksimul;     //!< Configuration specific to simultaneous session
156                                                 //!< checking.
157         rlm_rest_section_t      post_auth;      //!< Configuration specific to Post-auth
158 } rlm_rest_t;
159
160 /*
161  *      States for stream based attribute encoders
162  */
163 typedef enum {
164         READ_STATE_INIT = 0,
165         READ_STATE_ATTR_BEGIN,
166         READ_STATE_ATTR_CONT,
167         READ_STATE_END,
168 } read_state_t;
169
170 /*
171  *      States for the response parser
172  */
173 typedef enum {
174         WRITE_STATE_INIT = 0,
175         WRITE_STATE_PARSE_HEADERS,
176         WRITE_STATE_PARSE_CONTENT,
177         WRITE_STATE_DISCARD,
178 } write_state_t;
179
180 /*
181  *      Outbound data context (passed to CURLOPT_READFUNCTION as CURLOPT_READDATA)
182  */
183 typedef struct rlm_rest_request_t {
184         rlm_rest_t              *instance;      //!< This instance of rlm_rest.
185         REQUEST                 *request;       //!< Current request.
186         read_state_t            state;          //!< Encoder state
187
188         vp_cursor_t             cursor;         //!< Cursor pointing to the start of the list to encode.
189
190         size_t                  chunk;          //!< Chunk size
191
192         void                    *encoder;       //!< Encoder specific data.
193 } rlm_rest_request_t;
194
195 /*
196  *      Curl inbound data context (passed to CURLOPT_WRITEFUNCTION and
197  *      CURLOPT_HEADERFUNCTION as CURLOPT_WRITEDATA and CURLOPT_HEADERDATA)
198  */
199 typedef struct rlm_rest_response_t {
200         rlm_rest_t              *instance;      //!< This instance of rlm_rest.
201         REQUEST                 *request;       //!< Current request.
202         write_state_t           state;          //!< Decoder state.
203
204         char                    *buffer;        //!< Raw incoming HTTP data.
205         size_t                  alloc;          //!< Space allocated for buffer.
206         size_t                  used;           //!< Space used in buffer.
207
208         int                     code;           //!< HTTP Status Code.
209         http_body_type_t        type;           //!< HTTP Content Type.
210         http_body_type_t        force_to;       //!< Force decoding the body type as a particular encoding.
211
212         void                    *decoder;       //!< Decoder specific data.
213 } rlm_rest_response_t;
214
215 /*
216  *      Curl context data
217  */
218 typedef struct rlm_rest_curl_context_t {
219         struct curl_slist       *headers;       //!< Any HTTP headers which will be sent with the
220                                                 //!< request.
221
222         char                    *body;          //!< Pointer to the buffer which contains body data/
223                                                 //!< Only used when not performing chunked encoding.
224
225         rlm_rest_request_t      request;        //!< Request context data.
226         rlm_rest_response_t     response;       //!< Response context data.
227 } rlm_rest_curl_context_t;
228
229 /*
230  *      Connection API handle
231  */
232 typedef struct rlm_rest_handle_t {
233         void                    *handle;        //!< Real Handle.
234         rlm_rest_curl_context_t *ctx;           //!< Context.
235 } rlm_rest_handle_t;
236
237 /*
238  *      Function prototype for rest_read_wrapper. Matches CURL's
239  *      CURLOPT_READFUNCTION prototype.
240  */
241 typedef size_t (*rest_read_t)(void *ptr, size_t size, size_t nmemb,
242                               void *userdata);
243
244 /*
245  *      Connection API callbacks
246  */
247 int rest_init(rlm_rest_t *instance);
248
249 void rest_cleanup(void);
250
251 void *mod_conn_create(TALLOC_CTX *ctx, void *instance);
252
253 int mod_conn_alive(void *instance, void *handle);
254
255 /*
256  *      Request processing API
257  */
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));
263
264 int rest_request_perform(rlm_rest_t *instance,
265                          rlm_rest_section_t *section, REQUEST *request,
266                          void *handle);
267
268 int rest_response_decode(rlm_rest_t *instance,
269                         UNUSED rlm_rest_section_t *section, REQUEST *request,
270                         void *handle);
271
272 void rest_request_cleanup(rlm_rest_t *instance, rlm_rest_section_t *section,
273                           void *handle);
274
275 #define rest_get_handle_code(handle)(((rlm_rest_curl_context_t*)((rlm_rest_handle_t*)handle)->ctx)->response.code)
276
277 #define rest_get_handle_type(handle)(((rlm_rest_curl_context_t*)((rlm_rest_handle_t*)handle)->ctx)->response.type)
278
279 size_t rest_get_handle_data(char const **out, rlm_rest_handle_t *handle);
280
281 /*
282  *      Helper functions
283  */
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);