aboutsummaryrefslogtreecommitdiff
path: root/src/json/json_mhd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/json/json_mhd.c')
-rw-r--r--src/json/json_mhd.c356
1 files changed, 180 insertions, 176 deletions
diff --git a/src/json/json_mhd.c b/src/json/json_mhd.c
index 2112d4646..0b4dcfee8 100644
--- a/src/json/json_mhd.c
+++ b/src/json/json_mhd.c
@@ -1,22 +1,22 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2014, 2015, 2016 GNUnet e.V. 3 Copyright (C) 2014, 2015, 2016 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License, 7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version. 8 or (at your option) any later version.
9 9
10 GNUnet is distributed in the hope that it will be useful, but 10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU Affero General Public License 15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 17
18 SPDX-License-Identifier: AGPL3.0-or-later 18 SPDX-License-Identifier: AGPL3.0-or-later
19*/ 19 */
20/** 20/**
21 * @file json/json_mhd.c 21 * @file json/json_mhd.c
22 * @brief functions to parse JSON snippets we receive via MHD 22 * @brief functions to parse JSON snippets we receive via MHD
@@ -40,8 +40,7 @@
40/** 40/**
41 * Buffer for POST requests. 41 * Buffer for POST requests.
42 */ 42 */
43struct Buffer 43struct Buffer {
44{
45 /** 44 /**
46 * Allocated memory 45 * Allocated memory
47 */ 46 */
@@ -75,19 +74,19 @@ struct Buffer
75 * @return a GNUnet result code 74 * @return a GNUnet result code
76 */ 75 */
77static int 76static int
78buffer_init (struct Buffer *buf, 77buffer_init(struct Buffer *buf,
79 const void *data, 78 const void *data,
80 size_t data_size, 79 size_t data_size,
81 size_t alloc_size, 80 size_t alloc_size,
82 size_t max_size) 81 size_t max_size)
83{ 82{
84 if ((data_size > max_size) || (alloc_size > max_size)) 83 if ((data_size > max_size) || (alloc_size > max_size))
85 return GNUNET_SYSERR; 84 return GNUNET_SYSERR;
86 if (data_size > alloc_size) 85 if (data_size > alloc_size)
87 alloc_size = data_size; 86 alloc_size = data_size;
88 buf->data = GNUNET_malloc (alloc_size); 87 buf->data = GNUNET_malloc(alloc_size);
89 buf->alloc = alloc_size; 88 buf->alloc = alloc_size;
90 GNUNET_memcpy (buf->data, data, data_size); 89 GNUNET_memcpy(buf->data, data, data_size);
91 buf->fill = data_size; 90 buf->fill = data_size;
92 buf->max = max_size; 91 buf->max = max_size;
93 return GNUNET_OK; 92 return GNUNET_OK;
@@ -101,9 +100,9 @@ buffer_init (struct Buffer *buf,
101 * @param buf buffer to de-initialize 100 * @param buf buffer to de-initialize
102 */ 101 */
103static void 102static void
104buffer_deinit (struct Buffer *buf) 103buffer_deinit(struct Buffer *buf)
105{ 104{
106 GNUNET_free (buf->data); 105 GNUNET_free(buf->data);
107 buf->data = NULL; 106 buf->data = NULL;
108} 107}
109 108
@@ -119,28 +118,28 @@ buffer_deinit (struct Buffer *buf)
119 * #GNUNET_NO if the buffer can't accomodate for the new data 118 * #GNUNET_NO if the buffer can't accomodate for the new data
120 */ 119 */
121static int 120static int
122buffer_append (struct Buffer *buf, 121buffer_append(struct Buffer *buf,
123 const void *data, 122 const void *data,
124 size_t data_size, 123 size_t data_size,
125 size_t max_size) 124 size_t max_size)
126{ 125{
127 if (buf->fill + data_size > max_size) 126 if (buf->fill + data_size > max_size)
128 return GNUNET_NO; 127 return GNUNET_NO;
129 if (buf->fill + data_size > buf->alloc) 128 if (buf->fill + data_size > buf->alloc)
130 { 129 {
131 char *new_buf; 130 char *new_buf;
132 size_t new_size = buf->alloc; 131 size_t new_size = buf->alloc;
133 while (new_size < buf->fill + data_size) 132 while (new_size < buf->fill + data_size)
134 new_size += 2; 133 new_size += 2;
135 if (new_size > max_size) 134 if (new_size > max_size)
136 return GNUNET_NO; 135 return GNUNET_NO;
137 new_buf = GNUNET_malloc (new_size); 136 new_buf = GNUNET_malloc(new_size);
138 GNUNET_memcpy (new_buf, buf->data, buf->fill); 137 GNUNET_memcpy(new_buf, buf->data, buf->fill);
139 GNUNET_free (buf->data); 138 GNUNET_free(buf->data);
140 buf->data = new_buf; 139 buf->data = new_buf;
141 buf->alloc = new_size; 140 buf->alloc = new_size;
142 } 141 }
143 GNUNET_memcpy (buf->data + buf->fill, data, data_size); 142 GNUNET_memcpy(buf->data + buf->fill, data, data_size);
144 buf->fill += data_size; 143 buf->fill += data_size;
145 return GNUNET_OK; 144 return GNUNET_OK;
146} 145}
@@ -153,89 +152,95 @@ buffer_append (struct Buffer *buf,
153 * @return result code indicating the status of the operation 152 * @return result code indicating the status of the operation
154 */ 153 */
155static enum GNUNET_JSON_PostResult 154static enum GNUNET_JSON_PostResult
156inflate_data (struct Buffer *buf) 155inflate_data(struct Buffer *buf)
157{ 156{
158 z_stream z; 157 z_stream z;
159 char *tmp; 158 char *tmp;
160 size_t tmp_size; 159 size_t tmp_size;
161 int ret; 160 int ret;
162 161
163 memset (&z, 0, sizeof (z)); 162 memset(&z, 0, sizeof(z));
164 z.next_in = (Bytef *) buf->data; 163 z.next_in = (Bytef *)buf->data;
165 z.avail_in = buf->fill; 164 z.avail_in = buf->fill;
166 tmp_size = GNUNET_MIN (buf->max, buf->fill * 4); 165 tmp_size = GNUNET_MIN(buf->max, buf->fill * 4);
167 tmp = GNUNET_malloc (tmp_size); 166 tmp = GNUNET_malloc(tmp_size);
168 z.next_out = (Bytef *) tmp; 167 z.next_out = (Bytef *)tmp;
169 z.avail_out = tmp_size; 168 z.avail_out = tmp_size;
170 ret = inflateInit (&z); 169 ret = inflateInit(&z);
171 switch (ret) 170 switch (ret)
172 {
173 case Z_MEM_ERROR:
174 GNUNET_break (0);
175 return GNUNET_JSON_PR_OUT_OF_MEMORY;
176 case Z_STREAM_ERROR:
177 GNUNET_break_op (0);
178 return GNUNET_JSON_PR_JSON_INVALID;
179 case Z_OK:
180 break;
181 }
182 while (1)
183 {
184 ret = inflate (&z, 0);
185 switch (ret)
186 { 171 {
187 case Z_MEM_ERROR: 172 case Z_MEM_ERROR:
188 GNUNET_break (0); 173 GNUNET_break(0);
189 GNUNET_break (Z_OK == inflateEnd (&z));
190 GNUNET_free (tmp);
191 return GNUNET_JSON_PR_OUT_OF_MEMORY; 174 return GNUNET_JSON_PR_OUT_OF_MEMORY;
192 case Z_DATA_ERROR: 175
193 GNUNET_break (0); 176 case Z_STREAM_ERROR:
194 GNUNET_break (Z_OK == inflateEnd (&z)); 177 GNUNET_break_op(0);
195 GNUNET_free (tmp);
196 return GNUNET_JSON_PR_JSON_INVALID;
197 case Z_NEED_DICT:
198 GNUNET_break (0);
199 GNUNET_break (Z_OK == inflateEnd (&z));
200 GNUNET_free (tmp);
201 return GNUNET_JSON_PR_JSON_INVALID; 178 return GNUNET_JSON_PR_JSON_INVALID;
179
202 case Z_OK: 180 case Z_OK:
203 if ((0 < z.avail_out) && (0 == z.avail_in)) 181 break;
204 {
205 /* truncated input stream */
206 GNUNET_break (0);
207 GNUNET_break (Z_OK == inflateEnd (&z));
208 GNUNET_free (tmp);
209 return GNUNET_JSON_PR_JSON_INVALID;
210 }
211 if (0 < z.avail_out)
212 continue; /* just call it again */
213 /* output buffer full, can we grow it? */
214 if (tmp_size == buf->max)
215 {
216 /* already at max */
217 GNUNET_break (0);
218 GNUNET_break (Z_OK == inflateEnd (&z));
219 GNUNET_free (tmp);
220 return GNUNET_JSON_PR_OUT_OF_MEMORY;
221 }
222 if (tmp_size * 2 < tmp_size)
223 tmp_size = buf->max;
224 else
225 tmp_size = GNUNET_MIN (buf->max, tmp_size * 2);
226 tmp = GNUNET_realloc (tmp, tmp_size);
227 z.next_out = (Bytef *) &tmp[z.total_out];
228 continue;
229 case Z_STREAM_END:
230 /* decompression successful, make 'tmp' the new 'data' */
231 GNUNET_free (buf->data);
232 buf->data = tmp;
233 buf->alloc = tmp_size;
234 buf->fill = z.total_out;
235 GNUNET_break (Z_OK == inflateEnd (&z));
236 return GNUNET_JSON_PR_SUCCESS; /* at least for now */
237 } 182 }
238 } /* while (1) */ 183 while (1)
184 {
185 ret = inflate(&z, 0);
186 switch (ret)
187 {
188 case Z_MEM_ERROR:
189 GNUNET_break(0);
190 GNUNET_break(Z_OK == inflateEnd(&z));
191 GNUNET_free(tmp);
192 return GNUNET_JSON_PR_OUT_OF_MEMORY;
193
194 case Z_DATA_ERROR:
195 GNUNET_break(0);
196 GNUNET_break(Z_OK == inflateEnd(&z));
197 GNUNET_free(tmp);
198 return GNUNET_JSON_PR_JSON_INVALID;
199
200 case Z_NEED_DICT:
201 GNUNET_break(0);
202 GNUNET_break(Z_OK == inflateEnd(&z));
203 GNUNET_free(tmp);
204 return GNUNET_JSON_PR_JSON_INVALID;
205
206 case Z_OK:
207 if ((0 < z.avail_out) && (0 == z.avail_in))
208 {
209 /* truncated input stream */
210 GNUNET_break(0);
211 GNUNET_break(Z_OK == inflateEnd(&z));
212 GNUNET_free(tmp);
213 return GNUNET_JSON_PR_JSON_INVALID;
214 }
215 if (0 < z.avail_out)
216 continue; /* just call it again */
217 /* output buffer full, can we grow it? */
218 if (tmp_size == buf->max)
219 {
220 /* already at max */
221 GNUNET_break(0);
222 GNUNET_break(Z_OK == inflateEnd(&z));
223 GNUNET_free(tmp);
224 return GNUNET_JSON_PR_OUT_OF_MEMORY;
225 }
226 if (tmp_size * 2 < tmp_size)
227 tmp_size = buf->max;
228 else
229 tmp_size = GNUNET_MIN(buf->max, tmp_size * 2);
230 tmp = GNUNET_realloc(tmp, tmp_size);
231 z.next_out = (Bytef *)&tmp[z.total_out];
232 continue;
233
234 case Z_STREAM_END:
235 /* decompression successful, make 'tmp' the new 'data' */
236 GNUNET_free(buf->data);
237 buf->data = tmp;
238 buf->alloc = tmp_size;
239 buf->fill = z.total_out;
240 GNUNET_break(Z_OK == inflateEnd(&z));
241 return GNUNET_JSON_PR_SUCCESS; /* at least for now */
242 }
243 } /* while (1) */
239} 244}
240 245
241 246
@@ -255,12 +260,12 @@ inflate_data (struct Buffer *buf)
255 * @return result code indicating the status of the operation 260 * @return result code indicating the status of the operation
256 */ 261 */
257enum GNUNET_JSON_PostResult 262enum GNUNET_JSON_PostResult
258GNUNET_JSON_post_parser (size_t buffer_max, 263GNUNET_JSON_post_parser(size_t buffer_max,
259 struct MHD_Connection *connection, 264 struct MHD_Connection *connection,
260 void **con_cls, 265 void **con_cls,
261 const char *upload_data, 266 const char *upload_data,
262 size_t *upload_data_size, 267 size_t *upload_data_size,
263 json_t **json) 268 json_t **json)
264{ 269{
265 struct Buffer *r = *con_cls; 270 struct Buffer *r = *con_cls;
266 const char *ce; 271 const char *ce;
@@ -268,72 +273,71 @@ GNUNET_JSON_post_parser (size_t buffer_max,
268 273
269 *json = NULL; 274 *json = NULL;
270 if (NULL == *con_cls) 275 if (NULL == *con_cls)
271 {
272
273 /* We are seeing a fresh POST request. */
274 r = GNUNET_new (struct Buffer);
275 if (GNUNET_OK != buffer_init (r,
276 upload_data,
277 *upload_data_size,
278 REQUEST_BUFFER_INITIAL,
279 buffer_max))
280 { 276 {
281 *con_cls = NULL; 277 /* We are seeing a fresh POST request. */
282 buffer_deinit (r); 278 r = GNUNET_new(struct Buffer);
283 GNUNET_free (r); 279 if (GNUNET_OK != buffer_init(r,
284 return GNUNET_JSON_PR_OUT_OF_MEMORY; 280 upload_data,
281 *upload_data_size,
282 REQUEST_BUFFER_INITIAL,
283 buffer_max))
284 {
285 *con_cls = NULL;
286 buffer_deinit(r);
287 GNUNET_free(r);
288 return GNUNET_JSON_PR_OUT_OF_MEMORY;
289 }
290 /* everything OK, wait for more POST data */
291 *upload_data_size = 0;
292 *con_cls = r;
293 return GNUNET_JSON_PR_CONTINUE;
285 } 294 }
286 /* everything OK, wait for more POST data */
287 *upload_data_size = 0;
288 *con_cls = r;
289 return GNUNET_JSON_PR_CONTINUE;
290 }
291 if (0 != *upload_data_size) 295 if (0 != *upload_data_size)
292 {
293 /* We are seeing an old request with more data available. */
294
295 if (GNUNET_OK !=
296 buffer_append (r, upload_data, *upload_data_size, buffer_max))
297 { 296 {
298 /* Request too long */ 297 /* We are seeing an old request with more data available. */
299 *con_cls = NULL; 298
300 buffer_deinit (r); 299 if (GNUNET_OK !=
301 GNUNET_free (r); 300 buffer_append(r, upload_data, *upload_data_size, buffer_max))
302 return GNUNET_JSON_PR_REQUEST_TOO_LARGE; 301 {
302 /* Request too long */
303 *con_cls = NULL;
304 buffer_deinit(r);
305 GNUNET_free(r);
306 return GNUNET_JSON_PR_REQUEST_TOO_LARGE;
307 }
308 /* everything OK, wait for more POST data */
309 *upload_data_size = 0;
310 return GNUNET_JSON_PR_CONTINUE;
303 } 311 }
304 /* everything OK, wait for more POST data */
305 *upload_data_size = 0;
306 return GNUNET_JSON_PR_CONTINUE;
307 }
308 312
309 /* We have seen the whole request. */ 313 /* We have seen the whole request. */
310 ce = MHD_lookup_connection_value (connection, 314 ce = MHD_lookup_connection_value(connection,
311 MHD_HEADER_KIND, 315 MHD_HEADER_KIND,
312 MHD_HTTP_HEADER_CONTENT_ENCODING); 316 MHD_HTTP_HEADER_CONTENT_ENCODING);
313 if ((NULL != ce) && (0 == strcasecmp ("deflate", ce))) 317 if ((NULL != ce) && (0 == strcasecmp("deflate", ce)))
314 {
315 ret = inflate_data (r);
316 if (GNUNET_JSON_PR_SUCCESS != ret)
317 { 318 {
318 buffer_deinit (r); 319 ret = inflate_data(r);
319 GNUNET_free (r); 320 if (GNUNET_JSON_PR_SUCCESS != ret)
320 *con_cls = NULL; 321 {
321 return ret; 322 buffer_deinit(r);
323 GNUNET_free(r);
324 *con_cls = NULL;
325 return ret;
326 }
322 } 327 }
323 }
324 328
325 *json = json_loadb (r->data, r->fill, 0, NULL); 329 *json = json_loadb(r->data, r->fill, 0, NULL);
326 if (NULL == *json) 330 if (NULL == *json)
327 { 331 {
328 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 332 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
329 "Failed to parse JSON request body\n"); 333 "Failed to parse JSON request body\n");
330 buffer_deinit (r); 334 buffer_deinit(r);
331 GNUNET_free (r); 335 GNUNET_free(r);
332 *con_cls = NULL; 336 *con_cls = NULL;
333 return GNUNET_JSON_PR_JSON_INVALID; 337 return GNUNET_JSON_PR_JSON_INVALID;
334 } 338 }
335 buffer_deinit (r); 339 buffer_deinit(r);
336 GNUNET_free (r); 340 GNUNET_free(r);
337 *con_cls = NULL; 341 *con_cls = NULL;
338 342
339 return GNUNET_JSON_PR_SUCCESS; 343 return GNUNET_JSON_PR_SUCCESS;
@@ -348,15 +352,15 @@ GNUNET_JSON_post_parser (size_t buffer_max,
348 * #GNUNET_JSON_post_parser(), to be cleaned up 352 * #GNUNET_JSON_post_parser(), to be cleaned up
349 */ 353 */
350void 354void
351GNUNET_JSON_post_parser_cleanup (void *con_cls) 355GNUNET_JSON_post_parser_cleanup(void *con_cls)
352{ 356{
353 struct Buffer *r = con_cls; 357 struct Buffer *r = con_cls;
354 358
355 if (NULL != r) 359 if (NULL != r)
356 { 360 {
357 buffer_deinit (r); 361 buffer_deinit(r);
358 GNUNET_free (r); 362 GNUNET_free(r);
359 } 363 }
360} 364}
361 365
362/* end of mhd_json.c */ 366/* end of mhd_json.c */