Move more CC_HINTs to headers
[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_CUSTOM,
49         HTTP_METHOD_GET,
50         HTTP_METHOD_POST,
51         HTTP_METHOD_PUT,
52         HTTP_METHOD_DELETE
53 } http_method_t;
54
55 typedef enum {
56         HTTP_BODY_UNKNOWN = 0,
57         HTTP_BODY_UNSUPPORTED,
58         HTTP_BODY_UNAVAILABLE,
59         HTTP_BODY_INVALID,
60         HTTP_BODY_NONE,
61         HTTP_BODY_CUSTOM,
62         HTTP_BODY_POST,
63         HTTP_BODY_JSON,
64         HTTP_BODY_XML,
65         HTTP_BODY_YAML,
66         HTTP_BODY_HTML,
67         HTTP_BODY_PLAIN,
68         HTTP_BODY_NUM_ENTRIES
69 } http_body_type_t;
70
71 typedef enum {
72         HTTP_AUTH_UNKNOWN = 0,
73         HTTP_AUTH_NONE,
74         HTTP_AUTH_TLS_SRP,
75         HTTP_AUTH_BASIC,
76         HTTP_AUTH_DIGEST,
77         HTTP_AUTH_DIGEST_IE,
78         HTTP_AUTH_GSSNEGOTIATE,
79         HTTP_AUTH_NTLM,
80         HTTP_AUTH_NTLM_WB,
81         HTTP_AUTH_ANY,
82         HTTP_AUTH_ANY_SAFE,
83         HTTP_AUTH_NUM_ENTRIES
84 } http_auth_type_t;
85
86 /*
87  *      Must be updated (in rest.c) if additional values are added to
88  *      http_body_type_t
89  */
90 extern const http_body_type_t http_body_type_supported[HTTP_BODY_NUM_ENTRIES];
91
92 extern const unsigned long http_curl_auth[HTTP_AUTH_NUM_ENTRIES];
93
94 extern const FR_NAME_NUMBER http_auth_table[];
95
96 extern const FR_NAME_NUMBER http_method_table[];
97
98 extern const FR_NAME_NUMBER http_body_type_table[];
99
100 extern const FR_NAME_NUMBER http_content_type_table[];
101
102 /*
103  *      Structure for section configuration
104  */
105 typedef struct rlm_rest_section_t {
106         char const              *name;          //!< Section name.
107         char                    *uri;           //!< URI to send HTTP request to.
108
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...
111
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.
114
115         http_body_type_t        force_to;       //!< Override the Content-Type header in the response
116                                                 //!< to force decoding as a particular type.
117
118         char                    *data;          //!< Custom body data (optional).
119
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
125
126         char                    *tls_certificate_file;
127         char                    *tls_private_key_file;
128         char                    *tls_private_key_password;
129         char                    *tls_ca_file;
130         char                    *tls_ca_path;
131         char                    *tls_random_file;
132         bool                    tls_check_cert;
133         bool                    tls_check_cert_cn;
134
135         int                     timeout;        //!< Timeout passed to CURL.
136         size_t                  chunk;          //!< Max chunk-size (mainly for testing the encoders)
137 } rlm_rest_section_t;
138
139 /*
140  *      Structure for module configuration
141  */
142 typedef struct rlm_rest_t {
143         char const              *xlat_name;     //!< Instance name.
144
145         char                    *connect_uri;   //!< URI we attempt to connect to, to pre-establish
146                                                 //!< TCP connections.
147
148         fr_connection_pool_t    *conn_pool;     //!< Pointer to the connection pool.
149
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
154                                                 //!< checking.
155         rlm_rest_section_t      postauth;       //!< Configuration specific to Post-auth
156 } rlm_rest_t;
157
158 /*
159  *      States for stream based attribute encoders
160  */
161 typedef enum {
162         READ_STATE_INIT = 0,
163         READ_STATE_ATTR_BEGIN,
164         READ_STATE_ATTR_CONT,
165         READ_STATE_END,
166 } read_state_t;
167
168 /*
169  *      States for the response parser
170  */
171 typedef enum {
172         WRITE_STATE_INIT = 0,
173         WRITE_STATE_PARSE_HEADERS,
174         WRITE_STATE_PARSE_CONTENT,
175         WRITE_STATE_DISCARD,
176 } write_state_t;
177
178 /*
179  *      Outbound data context (passed to CURLOPT_READFUNCTION as CURLOPT_READDATA)
180  */
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
185
186         vp_cursor_t             cursor;         //!< Cursor pointing to the start of the list to encode.
187
188         size_t                  chunk;          //!< Chunk size
189
190         void                    *encoder;       //!< Encoder specific data.
191 } rlm_rest_request_t;
192
193 /*
194  *      Curl inbound data context (passed to CURLOPT_WRITEFUNCTION and
195  *      CURLOPT_HEADERFUNCTION as CURLOPT_WRITEDATA and CURLOPT_HEADERDATA)
196  */
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.
201
202         char                    *buffer;        //!< Raw incoming HTTP data.
203         size_t                  alloc;          //!< Space allocated for buffer.
204         size_t                  used;           //!< Space used in buffer.
205
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.
209
210         void                    *decoder;       //!< Decoder specific data.
211 } rlm_rest_response_t;
212
213 /*
214  *      Curl context data
215  */
216 typedef struct rlm_rest_curl_context_t {
217         struct curl_slist       *headers;       //!< Any HTTP headers which will be sent with the
218                                                 //!< request.
219
220         char                    *body;          //!< Pointer to the buffer which contains body data/
221                                                 //!< Only used when not performing chunked encoding.
222
223         rlm_rest_request_t      request;        //!< Request context data.
224         rlm_rest_response_t     response;       //!< Response context data.
225 } rlm_rest_curl_context_t;
226
227 /*
228  *      Connection API handle
229  */
230 typedef struct rlm_rest_handle_t {
231         void                    *handle;        //!< Real Handle.
232         rlm_rest_curl_context_t *ctx;           //!< Context.
233 } rlm_rest_handle_t;
234
235 /*
236  *      Function prototype for rest_read_wrapper. Matches CURL's
237  *      CURLOPT_READFUNCTION prototype.
238  */
239 typedef size_t (*rest_read_t)(void *ptr, size_t size, size_t nmemb,
240                               void *userdata);
241
242 /*
243  *      Connection API callbacks
244  */
245 int rest_init(rlm_rest_t *instance);
246
247 void rest_cleanup(void);
248
249 void *mod_conn_create(void *instance);
250
251 int mod_conn_alive(void *instance, void *handle);
252
253 int mod_conn_delete(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);