aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-01-16 13:50:07 +0100
committerChristian Grothoff <christian@grothoff.org>2015-01-16 13:50:07 +0100
commitf58fb4fc21be694096ae223fe0990ab93a52e815 (patch)
tree6bb6f4bec9d3f7ba8b4dc8a72d577f650c7d0211
parent0430d6fb031d1713a39a996068387c3ab2c36c2d (diff)
downloadexchange-f58fb4fc21be694096ae223fe0990ab93a52e815.tar.gz
exchange-f58fb4fc21be694096ae223fe0990ab93a52e815.zip
starting to separate out response generation API and parsing APIs
-rw-r--r--src/mint/Makefile.am3
-rw-r--r--src/mint/taler-mint-httpd.c3
-rw-r--r--src/mint/taler-mint-httpd_deposit.c29
-rw-r--r--src/mint/taler-mint-httpd_keys.c2
-rw-r--r--src/mint/taler-mint-httpd_mhd.c167
-rw-r--r--src/mint/taler-mint-httpd_mhd.h23
-rw-r--r--src/mint/taler-mint-httpd_parsing.c (renamed from src/mint/taler-mint-httpd_json.c)242
-rw-r--r--src/mint/taler-mint-httpd_parsing.h (renamed from src/mint/taler-mint-httpd_json.h)81
-rw-r--r--src/mint/taler-mint-httpd_refresh.c137
-rw-r--r--src/mint/taler-mint-httpd_responses.c146
-rw-r--r--src/mint/taler-mint-httpd_responses.h93
-rw-r--r--src/mint/taler-mint-httpd_withdraw.c71
12 files changed, 579 insertions, 418 deletions
diff --git a/src/mint/Makefile.am b/src/mint/Makefile.am
index eff126a07..4a2e775da 100644
--- a/src/mint/Makefile.am
+++ b/src/mint/Makefile.am
@@ -61,8 +61,9 @@ taler_mint_reservemod_LDFLAGS = \
61 61
62taler_mint_httpd_SOURCES = \ 62taler_mint_httpd_SOURCES = \
63 taler-mint-httpd.c \ 63 taler-mint-httpd.c \
64 taler-mint-httpd_parsing.c taler-mint-httpd_parsing.h \
65 taler-mint-httpd_responses.c taler-mint-httpd_responses.h \
64 taler-mint-httpd_mhd.c \ 66 taler-mint-httpd_mhd.c \
65 taler-mint-httpd_json.c taler-mint-httpd_json.h \
66 taler-mint-httpd_keys.c \ 67 taler-mint-httpd_keys.c \
67 taler-mint-httpd_deposit.c \ 68 taler-mint-httpd_deposit.c \
68 taler-mint-httpd_withdraw.c \ 69 taler-mint-httpd_withdraw.c \
diff --git a/src/mint/taler-mint-httpd.c b/src/mint/taler-mint-httpd.c
index 14dfa657c..61d0bbdce 100644
--- a/src/mint/taler-mint-httpd.c
+++ b/src/mint/taler-mint-httpd.c
@@ -32,7 +32,7 @@
32#include "taler_signatures.h" 32#include "taler_signatures.h"
33#include "taler_rsa.h" 33#include "taler_rsa.h"
34#include "taler_json_lib.h" 34#include "taler_json_lib.h"
35#include "taler-mint-httpd_json.h" 35#include "taler-mint-httpd_parsing.h"
36#include "taler-mint-httpd_mhd.h" 36#include "taler-mint-httpd_mhd.h"
37#include "taler-mint-httpd_keys.h" 37#include "taler-mint-httpd_keys.h"
38#include "taler-mint-httpd_deposit.h" 38#include "taler-mint-httpd_deposit.h"
@@ -372,4 +372,3 @@ main (int argc, char *const *argv)
372 MHD_stop_daemon (mydaemon); 372 MHD_stop_daemon (mydaemon);
373 return (GNUNET_OK == ret) ? 0 : 1; 373 return (GNUNET_OK == ret) ? 0 : 1;
374} 374}
375
diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c
index b8bcc87db..8c040b691 100644
--- a/src/mint/taler-mint-httpd_deposit.c
+++ b/src/mint/taler-mint-httpd_deposit.c
@@ -31,9 +31,10 @@
31#include "taler_signatures.h" 31#include "taler_signatures.h"
32#include "taler_rsa.h" 32#include "taler_rsa.h"
33#include "taler_json_lib.h" 33#include "taler_json_lib.h"
34#include "taler-mint-httpd_json.h" 34#include "taler-mint-httpd_parsing.h"
35#include "taler-mint-httpd_keys.h" 35#include "taler-mint-httpd_keys.h"
36#include "taler-mint-httpd_deposit.h" 36#include "taler-mint-httpd_deposit.h"
37#include "taler-mint-httpd_responses.h"
37 38
38 39
39/** 40/**
@@ -48,8 +49,11 @@ helper_deposit_send_response_success (struct MHD_Connection *connection,
48 struct Deposit *deposit) 49 struct Deposit *deposit)
49{ 50{
50 // FIXME: return more information here 51 // FIXME: return more information here
51 return request_send_json_pack (connection, MHD_HTTP_OK, 52 return TALER_MINT_reply_json_pack (connection,
52 "{s:s}", "status", "DEPOSIT_OK"); 53 MHD_HTTP_OK,
54 "{s:s}",
55 "status",
56 "DEPOSIT_OK");
53} 57}
54 58
55 59
@@ -199,9 +203,11 @@ TALER_MINT_handler_deposit (struct RequestHandler *rh,
199 // FIXME: in the future, check if there's enough credits 203 // FIXME: in the future, check if there's enough credits
200 // left on the coin. For now: refuse 204 // left on the coin. For now: refuse
201 // FIXME: return more information here 205 // FIXME: return more information here
202 return request_send_json_pack (connection, MHD_HTTP_FORBIDDEN, 206 return TALER_MINT_reply_json_pack (connection,
203 "{s:s}", 207 MHD_HTTP_FORBIDDEN,
204 "error", "double spending"); 208 "{s:s}",
209 "error",
210 "double spending");
205 } 211 }
206 212
207 if (GNUNET_SYSERR == res) 213 if (GNUNET_SYSERR == res)
@@ -221,9 +227,10 @@ TALER_MINT_handler_deposit (struct RequestHandler *rh,
221 // coin must have been refreshed 227 // coin must have been refreshed
222 // FIXME: check 228 // FIXME: check
223 // FIXME: return more information here 229 // FIXME: return more information here
224 return request_send_json_pack (connection, MHD_HTTP_FORBIDDEN, 230 return TALER_MINT_reply_json_pack (connection,
225 "{s:s}", 231 MHD_HTTP_FORBIDDEN,
226 "error", "coin was refreshed"); 232 "{s:s}",
233 "error", "coin was refreshed");
227 } 234 }
228 if (GNUNET_SYSERR == res) 235 if (GNUNET_SYSERR == res)
229 { 236 {
@@ -252,7 +259,9 @@ TALER_MINT_handler_deposit (struct RequestHandler *rh,
252 259
253 EXITIF_exit: 260 EXITIF_exit:
254 if (NULL != resp) 261 if (NULL != resp)
255 res = send_response_json (connection, resp, resp_code); 262 res = TALER_MINT_reply_json (connection,
263 resp,
264 resp_code);
256 else 265 else
257 res = MHD_NO; 266 res = MHD_NO;
258 if (NULL != wire) 267 if (NULL != wire)
diff --git a/src/mint/taler-mint-httpd_keys.c b/src/mint/taler-mint-httpd_keys.c
index 6d6e9468d..149e44d3f 100644
--- a/src/mint/taler-mint-httpd_keys.c
+++ b/src/mint/taler-mint-httpd_keys.c
@@ -31,7 +31,7 @@
31#include "taler_signatures.h" 31#include "taler_signatures.h"
32#include "taler_rsa.h" 32#include "taler_rsa.h"
33#include "taler_json_lib.h" 33#include "taler_json_lib.h"
34#include "taler-mint-httpd_json.h" 34#include "taler-mint-httpd_parsing.h"
35#include "taler-mint-httpd_keys.h" 35#include "taler-mint-httpd_keys.h"
36 36
37 37
diff --git a/src/mint/taler-mint-httpd_mhd.c b/src/mint/taler-mint-httpd_mhd.c
index d78f36d95..ed8a6eeda 100644
--- a/src/mint/taler-mint-httpd_mhd.c
+++ b/src/mint/taler-mint-httpd_mhd.c
@@ -16,7 +16,9 @@
16 16
17/** 17/**
18 * @file taler-mint-httpd_mhd.c 18 * @file taler-mint-httpd_mhd.c
19 * @brief helpers for MHD interaction 19 * @brief helpers for MHD interaction; these are TALER_MINT_handler_ functions
20 * that generate simple MHD replies that do not require any real operations
21 * to be performed (error handling, static pages, etc.)
20 * @author Florian Dold 22 * @author Florian Dold
21 * @author Benedikt Mueller 23 * @author Benedikt Mueller
22 * @author Christian Grothoff 24 * @author Christian Grothoff
@@ -27,9 +29,10 @@
27#include <microhttpd.h> 29#include <microhttpd.h>
28#include <libpq-fe.h> 30#include <libpq-fe.h>
29#include <pthread.h> 31#include <pthread.h>
30#include "taler-mint-httpd_json.h" 32#include "taler-mint-httpd_responses.h"
31#include "taler-mint-httpd.h" 33#include "taler-mint-httpd.h"
32#include "taler-mint-httpd_mhd.h" 34#include "taler-mint-httpd_mhd.h"
35#include "taler-mint-httpd_responses.h"
33 36
34 37
35/** 38/**
@@ -123,63 +126,6 @@ TALER_MINT_handler_agpl_redirect (struct RequestHandler *rh,
123 126
124/** 127/**
125 * Function to call to handle the request by building a JSON 128 * Function to call to handle the request by building a JSON
126 * reply from varargs.
127 *
128 * @param rh context of the handler
129 * @param connection the MHD connection to handle
130 * @param[IN|OUT] connection_cls the connection's closure (can be updated)
131 * @param response_code HTTP response code to use
132 * @param do_cache can the response be cached? (0: no, 1: yes)
133 * @param fmt format string for pack
134 * @param ... varargs
135 * @return MHD result code
136 */
137int
138TALER_MINT_helper_send_json_pack (struct RequestHandler *rh,
139 struct MHD_Connection *connection,
140 void *connection_cls,
141 int response_code,
142 int do_cache,
143 const char *fmt,
144 ...)
145{
146 int ret;
147 json_t *json;
148 va_list argp;
149 char *json_str;
150 struct MHD_Response *response;
151
152 va_start (argp, fmt);
153 json = json_vpack_ex (NULL, 0, fmt, argp);
154 va_end (argp);
155 if (NULL == json)
156 return MHD_NO;
157 json_str = json_dumps (json, JSON_INDENT(2));
158 json_decref (json);
159 if (NULL == json_str)
160 return MHD_NO;
161 response = MHD_create_response_from_buffer (strlen (json_str),
162 json_str,
163 MHD_RESPMEM_MUST_FREE);
164 if (NULL == response)
165 {
166 free (json_str);
167 return MHD_NO;
168 }
169 if (NULL != rh->mime_type)
170 (void) MHD_add_response_header (response,
171 MHD_HTTP_HEADER_CONTENT_TYPE,
172 rh->mime_type);
173 ret = MHD_queue_response (connection,
174 response_code,
175 response);
176 MHD_destroy_response (response);
177 return ret;
178}
179
180
181/**
182 * Function to call to handle the request by building a JSON
183 * reply with an error message from @a rh. 129 * reply with an error message from @a rh.
184 * 130 *
185 * @param rh context of the handler 131 * @param rh context of the handler
@@ -196,105 +142,12 @@ TALER_MINT_handler_send_json_pack_error (struct RequestHandler *rh,
196 const char *upload_data, 142 const char *upload_data,
197 size_t *upload_data_size) 143 size_t *upload_data_size)
198{ 144{
199 return TALER_MINT_helper_send_json_pack (rh, 145 return TALER_MINT_reply_json_pack (connection,
200 connection, 146 rh->response_code,
201 connection_cls, 147 "{s:s}",
202 1, /* caching enabled */ 148 "error",
203 rh->response_code, 149 rh->data);
204 "{s:s}",
205 "error",
206 rh->data);
207} 150}
208 151
209 152
210/**
211 * Send a response for an invalid argument.
212 *
213 * @param connection the MHD connection to use
214 * @param param_name the parameter that is missing
215 * @return a GNUnet result code
216 */
217static int
218request_arg_invalid (struct MHD_Connection *connection,
219 const char *param_name)
220{
221 json_t *json;
222 json = json_pack ("{ s:s, s:s }",
223 "error", "invalid parameter",
224 "parameter", param_name);
225 if (MHD_YES != send_response_json (connection, json, MHD_HTTP_BAD_REQUEST))
226 {
227 GNUNET_break (0);
228 return GNUNET_SYSERR;
229 }
230 return GNUNET_NO;
231}
232
233
234/**
235 * Get a GET paramater that is a string,
236 * or send an error response if the parameter is missing.
237 *
238 * @param connection the connection to get the parameter from /
239 * send the error response to
240 * @param param_name the parameter name
241 * @param str pointer to store the parameter string,
242 * must be freed by the caller
243 * @return GNUNET_YES if the parameter is present and valid,
244 * GNUNET_NO if the parameter is missing
245 * GNUNET_SYSERR on internal error
246 */
247static int
248request_arg_require_string (struct MHD_Connection *connection,
249 const char *param_name,
250 const char **str)
251{
252 *str = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, param_name);
253 if (NULL == *str)
254 {
255 if (MHD_NO ==
256 request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST,
257 "{ s:s, s:s }",
258 "error", "missing parameter",
259 "parameter", param_name))
260 return GNUNET_SYSERR;
261 return GNUNET_NO;
262 }
263 return GNUNET_OK;
264}
265
266
267/**
268 * Extraxt base32crockford encoded data from request.
269 *
270 * Queues an error response to the connection if the parameter is missing or
271 * invalid.
272 *
273 * @param connection the MHD connection
274 * @param param_name the name of the parameter with the key
275 * @param[out] out_data pointer to store the result
276 * @param out_size expected size of data
277 * @return
278 * GNUNET_YES if the the argument is present
279 * GNUNET_NO if the argument is absent or malformed
280 * GNUNET_SYSERR on internal error (error response could not be sent)
281 */
282int
283TALER_MINT_mhd_request_arg_data (struct MHD_Connection *connection,
284 const char *param_name,
285 void *out_data,
286 size_t out_size)
287{
288 const char *str;
289 int ret;
290
291 if (GNUNET_OK != (ret = request_arg_require_string (connection, param_name, &str)))
292 return ret;
293 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (str, strlen (str), out_data, out_size))
294 return request_arg_invalid (connection, param_name);
295 return GNUNET_OK;
296}
297
298
299
300/* end of taler-mint-httpd_mhd.c */ 153/* end of taler-mint-httpd_mhd.c */
diff --git a/src/mint/taler-mint-httpd_mhd.h b/src/mint/taler-mint-httpd_mhd.h
index 29ab7f64b..1390a2753 100644
--- a/src/mint/taler-mint-httpd_mhd.h
+++ b/src/mint/taler-mint-httpd_mhd.h
@@ -16,7 +16,7 @@
16 16
17/** 17/**
18 * @file taler-mint-httpd_mhd.h 18 * @file taler-mint-httpd_mhd.h
19 * @brief helpers for MHD interaction 19 * @brief helpers for MHD interaction, used to generate simple responses
20 * @author Florian Dold 20 * @author Florian Dold
21 * @author Benedikt Mueller 21 * @author Benedikt Mueller
22 * @author Christian Grothoff 22 * @author Christian Grothoff
@@ -108,25 +108,4 @@ TALER_MINT_handler_send_json_pack_error (struct RequestHandler *rh,
108 size_t *upload_data_size); 108 size_t *upload_data_size);
109 109
110 110
111/**
112 * Extraxt base32crockford encoded data from request.
113 *
114 * Queues an error response to the connection if the parameter is missing or
115 * invalid.
116 *
117 * @param connection the MHD connection
118 * @param param_name the name of the parameter with the key
119 * @param[out] out_data pointer to store the result
120 * @param out_size expected size of data
121 * @return
122 * GNUNET_YES if the the argument is present
123 * GNUNET_NO if the argument is absent or malformed
124 * GNUNET_SYSERR on internal error (error response could not be sent)
125 */
126int
127TALER_MINT_mhd_request_arg_data (struct MHD_Connection *connection,
128 const char *param_name,
129 void *out_data,
130 size_t out_size);
131
132#endif 111#endif
diff --git a/src/mint/taler-mint-httpd_json.c b/src/mint/taler-mint-httpd_parsing.c
index e9183073f..a976c0c06 100644
--- a/src/mint/taler-mint-httpd_json.c
+++ b/src/mint/taler-mint-httpd_parsing.c
@@ -1,7 +1,31 @@
1/*
2 This file is part of TALER
3 (C) 2014 GNUnet e.V.
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16
17/**
18 * @file taler-mint-httpd_parsing.c
19 * @brief functions to parse incoming requests (MHD arguments and JSON snippets)
20 * @author Florian Dold
21 * @author Benedikt Mueller
22 * @author Christian Grothoff
23 */
24
1#include "platform.h" 25#include "platform.h"
2#include <gnunet/gnunet_util_lib.h> 26#include <gnunet/gnunet_util_lib.h>
3#include "taler-mint-httpd_json.h" 27#include "taler-mint-httpd_parsing.h"
4 28#include "taler-mint-httpd_responses.h"
5 29
6 30
7/** 31/**
@@ -49,7 +73,11 @@ struct Buffer
49 * @return a GNUnet result code 73 * @return a GNUnet result code
50 */ 74 */
51static int 75static int
52buffer_init (struct Buffer *buf, const void *data, size_t data_size, size_t alloc_size, size_t max_size) 76buffer_init (struct Buffer *buf,
77 const void *data,
78 size_t data_size,
79 size_t alloc_size,
80 size_t max_size)
53{ 81{
54 if (data_size > max_size || alloc_size > max_size) 82 if (data_size > max_size || alloc_size > max_size)
55 return GNUNET_SYSERR; 83 return GNUNET_SYSERR;
@@ -87,7 +115,10 @@ buffer_deinit (struct Buffer *buf)
87 * GNUNET_SYSERR on fatal error (out of memory?) 115 * GNUNET_SYSERR on fatal error (out of memory?)
88 */ 116 */
89static int 117static int
90buffer_append (struct Buffer *buf, const void *data, size_t data_size, size_t max_size) 118buffer_append (struct Buffer *buf,
119 const void *data,
120 size_t data_size,
121 size_t max_size)
91{ 122{
92 if (buf->fill + data_size > max_size) 123 if (buf->fill + data_size > max_size)
93 return GNUNET_NO; 124 return GNUNET_NO;
@@ -111,63 +142,6 @@ buffer_append (struct Buffer *buf, const void *data, size_t data_size, size_t ma
111 142
112 143
113/** 144/**
114 * Send JSON object as response. Decreases the reference count of the
115 * JSON object.
116 *
117 * @param connection the MHD connection
118 * @param json the json object
119 * @param status_code the http status code
120 * @return MHD result code
121 */
122int
123send_response_json (struct MHD_Connection *connection,
124 json_t *json,
125 unsigned int status_code)
126{
127 struct MHD_Response *resp;
128 char *json_str;
129
130 json_str = json_dumps (json, JSON_INDENT(2));
131 json_decref (json);
132 resp = MHD_create_response_from_buffer (strlen (json_str), json_str,
133 MHD_RESPMEM_MUST_FREE);
134 if (NULL == resp)
135 return MHD_NO;
136 return MHD_queue_response (connection, status_code, resp);
137}
138
139
140/**
141 * Send a JSON object via an MHD connection,
142 * specified with the JANSSON pack syntax (see json_pack).
143 *
144 * @param connection connection to send the JSON over
145 * @param http_code HTTP status for the response
146 * @param fmt format string for pack
147 * @param ... varargs
148 * @return MHD_YES on success or MHD_NO on error
149 */
150int
151request_send_json_pack (struct MHD_Connection *connection,
152 unsigned int http_code,
153 const char *fmt, ...)
154{
155 json_t *msg;
156 va_list argp;
157 int ret;
158
159 va_start(argp, fmt);
160 msg = json_vpack_ex (NULL, 0, fmt, argp);
161 va_end(argp);
162 if (NULL == msg)
163 return MHD_NO;
164 ret = send_response_json (connection, msg, http_code);
165 json_decref (msg);
166 return ret;
167}
168
169
170/**
171 * Process a POST request containing a JSON object. 145 * Process a POST request containing a JSON object.
172 * 146 *
173 * @param connection the MHD connection 147 * @param connection the MHD connection
@@ -195,8 +169,12 @@ process_post_json (struct MHD_Connection *connection,
195 /* We are seeing a fresh POST request. */ 169 /* We are seeing a fresh POST request. */
196 170
197 r = GNUNET_new (struct Buffer); 171 r = GNUNET_new (struct Buffer);
198 if (GNUNET_OK != buffer_init (r, upload_data, *upload_data_size, 172 if (GNUNET_OK !=
199 REQUEST_BUFFER_INITIAL, REQUEST_BUFFER_MAX)) 173 buffer_init (r,
174 upload_data,
175 *upload_data_size,
176 REQUEST_BUFFER_INITIAL,
177 REQUEST_BUFFER_MAX))
200 { 178 {
201 *con_cls = NULL; 179 *con_cls = NULL;
202 buffer_deinit (r); 180 buffer_deinit (r);
@@ -211,8 +189,11 @@ process_post_json (struct MHD_Connection *connection,
211 { 189 {
212 /* We are seeing an old request with more data available. */ 190 /* We are seeing an old request with more data available. */
213 191
214 if (GNUNET_OK != buffer_append (r, upload_data, *upload_data_size, 192 if (GNUNET_OK !=
215 REQUEST_BUFFER_MAX)) 193 buffer_append (r,
194 upload_data,
195 *upload_data_size,
196 REQUEST_BUFFER_MAX))
216 { 197 {
217 /* Request too long or we're out of memory. */ 198 /* Request too long or we're out of memory. */
218 199
@@ -232,11 +213,14 @@ process_post_json (struct MHD_Connection *connection,
232 GNUNET_free (r); 213 GNUNET_free (r);
233 if (NULL == *json) 214 if (NULL == *json)
234 { 215 {
235 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Can't parse JSON request body\n"); 216 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
236 return request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST, 217 "Can't parse JSON request body\n");
237 GNUNET_NO, GNUNET_SYSERR, 218 return (MHD_YES ==
238 "{s:s}", 219 TALER_MINT_reply_json_pack (connection,
239 "error", "invalid json"); 220 MHD_HTTP_BAD_REQUEST,
221 "{s:s}",
222 "error", "invalid json"))
223 ? GNUNET_NO : GNUNET_SYSERR;
240 } 224 }
241 *con_cls = NULL; 225 *con_cls = NULL;
242 226
@@ -284,12 +268,14 @@ request_json_require_nav (struct MHD_Connection *connection,
284 root = json_object_get (root, fname); 268 root = json_object_get (root, fname);
285 if (NULL == root) 269 if (NULL == root)
286 { 270 {
287 271 /* FIXME: can't IGNORE this return value! */
288 (void) request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST, 272 (void) TALER_MINT_reply_json_pack (connection,
289 0, 0, 273 MHD_HTTP_BAD_REQUEST,
290 "{s:s,s:o}", 274 "{s:s,s:o}",
291 "error", "missing field in JSON", 275 "error",
292 "path", path); 276 "missing field in JSON",
277 "path",
278 path);
293 ignore = GNUNET_YES; 279 ignore = GNUNET_YES;
294 break; 280 break;
295 } 281 }
@@ -304,11 +290,12 @@ request_json_require_nav (struct MHD_Connection *connection,
304 root = json_array_get (root, fnum); 290 root = json_array_get (root, fnum);
305 if (NULL == root) 291 if (NULL == root)
306 { 292 {
307 (void) request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST, 293 /* FIXME: can't IGNORE this return value! */
308 0, 0, 294 (void) TALER_MINT_reply_json_pack (connection,
309 "{s:s, s:o}", 295 MHD_HTTP_BAD_REQUEST,
310 "error", "missing index in JSON", 296 "{s:s, s:o}",
311 "path", path); 297 "error", "missing index in JSON",
298 "path", path);
312 ignore = GNUNET_YES; 299 ignore = GNUNET_YES;
313 break; 300 break;
314 } 301 }
@@ -327,22 +314,27 @@ request_json_require_nav (struct MHD_Connection *connection,
327 str = json_string_value (root); 314 str = json_string_value (root);
328 if (NULL == str) 315 if (NULL == str)
329 { 316 {
330 (void) request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST, 317 /* FIXME: can't IGNORE this return value! */
331 0, 0, 318 (void) TALER_MINT_reply_json_pack (connection,
332 "{s:s, s:o}", 319 MHD_HTTP_BAD_REQUEST,
333 "error", "string expected", 320 "{s:s, s:o}",
334 "path", path); 321 "error",
322 "string expected",
323 "path",
324 path);
335 return GNUNET_NO; 325 return GNUNET_NO;
336 } 326 }
337 res = GNUNET_STRINGS_string_to_data (str, strlen (str), 327 res = GNUNET_STRINGS_string_to_data (str, strlen (str),
338 where, len); 328 where, len);
339 if (GNUNET_OK != res) 329 if (GNUNET_OK != res)
340 { 330 {
341 (void) request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST, 331 /* FIXME: can't IGNORE this return value! */
342 0, 0, 332 (void) TALER_MINT_reply_json_pack (connection,
343 "{s:s,s:o}", 333 MHD_HTTP_BAD_REQUEST,
344 "error", "malformed binary data in JSON", 334 "{s:s,s:o}",
345 "path", path); 335 "error",
336 "malformed binary data in JSON",
337 "path", path);
346 return GNUNET_NO; 338 return GNUNET_NO;
347 } 339 }
348 return GNUNET_YES; 340 return GNUNET_YES;
@@ -372,11 +364,13 @@ request_json_require_nav (struct MHD_Connection *connection,
372 *where, *len); 364 *where, *len);
373 if (GNUNET_OK != res) 365 if (GNUNET_OK != res)
374 { 366 {
375 (void) request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST, 367 /* FIXME: can't IGNORE this return value! */
376 0, 0, 368 (void) TALER_MINT_reply_json_pack (connection,
377 "{s:s, s:o}", 369 MHD_HTTP_BAD_REQUEST,
378 "error", "malformed binary data in JSON", 370 "{s:s, s:o}",
379 "path", path); 371 "error",
372 "malformed binary data in JSON",
373 "path", path);
380 return GNUNET_NO; 374 return GNUNET_NO;
381 } 375 }
382 } 376 }
@@ -393,13 +387,14 @@ request_json_require_nav (struct MHD_Connection *connection,
393 return GNUNET_NO; 387 return GNUNET_NO;
394 if (typ != -1 && json_typeof (root) != typ) 388 if (typ != -1 && json_typeof (root) != typ)
395 { 389 {
396 (void) request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST, 390 /* FIXME: can't IGNORE this return value! */
397 0, 0, 391 (void) TALER_MINT_reply_json_pack (connection,
398 "{s:s, s:i, s:i s:o}", 392 MHD_HTTP_BAD_REQUEST,
399 "error", "wrong JSON field type", 393 "{s:s, s:i, s:i s:o}",
400 "type_expected", typ, 394 "error", "wrong JSON field type",
401 "type_actual", json_typeof (root), 395 "type_expected", typ,
402 "path", path); 396 "type_actual", json_typeof (root),
397 "path", path);
403 return GNUNET_NO; 398 return GNUNET_NO;
404 } 399 }
405 *r_json = root; 400 *r_json = root;
@@ -414,4 +409,45 @@ request_json_require_nav (struct MHD_Connection *connection,
414} 409}
415 410
416 411
412/**
413 * Extract base32crockford encoded data from request.
414 *
415 * Queues an error response to the connection if the parameter is missing or
416 * invalid.
417 *
418 * @param connection the MHD connection
419 * @param param_name the name of the parameter with the key
420 * @param[out] out_data pointer to store the result
421 * @param out_size expected size of data
422 * @return
423 * GNUNET_YES if the the argument is present
424 * GNUNET_NO if the argument is absent or malformed
425 * GNUNET_SYSERR on internal error (error response could not be sent)
426 */
427int
428TALER_MINT_mhd_request_arg_data (struct MHD_Connection *connection,
429 const char *param_name,
430 void *out_data,
431 size_t out_size)
432{
433 const char *str;
417 434
435 str = MHD_lookup_connection_value (connection,
436 MHD_GET_ARGUMENT_KIND,
437 param_name);
438 if (NULL == str)
439 {
440 return (MHD_NO ==
441 TALER_MINT_reply_arg_missing (connection, param_name))
442 ? GNUNET_SYSERR : GNUNET_NO;
443 }
444 if (GNUNET_OK !=
445 GNUNET_STRINGS_string_to_data (str,
446 strlen (str),
447 out_data,
448 out_size))
449 return (MHD_NO ==
450 TALER_MINT_reply_arg_invalid (connection, param_name))
451 ? GNUNET_SYSERR : GNUNET_NO;
452 return GNUNET_OK;
453}
diff --git a/src/mint/taler-mint-httpd_json.h b/src/mint/taler-mint-httpd_parsing.h
index da601401f..2c6bb073c 100644
--- a/src/mint/taler-mint-httpd_json.h
+++ b/src/mint/taler-mint-httpd_parsing.h
@@ -1,4 +1,26 @@
1/*
2 This file is part of TALER
3 (C) 2014 GNUnet e.V.
1 4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16
17/**
18 * @file taler-mint-httpd_parsing.h
19 * @brief functions to parse incoming requests
20 * @author Florian Dold
21 * @author Benedikt Mueller
22 * @author Christian Grothoff
23 */
2 24
3#ifndef TALER_MICROHTTPD_LIB_H_ 25#ifndef TALER_MICROHTTPD_LIB_H_
4#define TALER_MICROHTTPD_LIB_H_ 26#define TALER_MICROHTTPD_LIB_H_
@@ -45,38 +67,6 @@ enum
45}; 67};
46 68
47 69
48
49/**
50 * Send JSON object as response. Decreases
51 * the reference count of the JSON object.
52 *
53 * @param connection the MHD connection
54 * @param json the json object
55 * @param status_code the http status code
56 * @return MHD result code (MHD_YES on success)
57 */
58int
59send_response_json (struct MHD_Connection *connection,
60 json_t *json,
61 unsigned int status_code);
62
63
64/**
65 * Send a JSON object via an MHD connection,
66 * specified with the JANSSON pack syntax (see json_pack).
67 *
68 * @param connection connection to send the JSON over
69 * @param http_code HTTP status for the response
70 * @param fmt format string for pack
71 * @param ... varargs
72 * @return MHD_YES on success or MHD_NO on error
73 */
74int
75request_send_json_pack (struct MHD_Connection *connection,
76 unsigned int http_code,
77 const char *fmt, ...);
78
79
80/** 70/**
81 * Process a POST request containing a JSON object. 71 * Process a POST request containing a JSON object.
82 * 72 *
@@ -116,4 +106,31 @@ int
116request_json_require_nav (struct MHD_Connection *connection, 106request_json_require_nav (struct MHD_Connection *connection,
117 const json_t *root, ...); 107 const json_t *root, ...);
118 108
109
110
111
112/**
113 * Extraxt base32crockford encoded data from request.
114 *
115 * Queues an error response to the connection if the parameter is missing or
116 * invalid.
117 *
118 * @param connection the MHD connection
119 * @param param_name the name of the parameter with the key
120 * @param[out] out_data pointer to store the result
121 * @param out_size expected size of data
122 * @return
123 * GNUNET_YES if the the argument is present
124 * GNUNET_NO if the argument is absent or malformed
125 * GNUNET_SYSERR on internal error (error response could not be sent)
126 */
127int
128TALER_MINT_mhd_request_arg_data (struct MHD_Connection *connection,
129 const char *param_name,
130 void *out_data,
131 size_t out_size);
132
133
134
135
119#endif /* TALER_MICROHTTPD_LIB_H_ */ 136#endif /* TALER_MICROHTTPD_LIB_H_ */
diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c
index 888e7de3b..73b474194 100644
--- a/src/mint/taler-mint-httpd_refresh.c
+++ b/src/mint/taler-mint-httpd_refresh.c
@@ -31,10 +31,11 @@
31#include "taler_signatures.h" 31#include "taler_signatures.h"
32#include "taler_rsa.h" 32#include "taler_rsa.h"
33#include "taler_json_lib.h" 33#include "taler_json_lib.h"
34#include "taler-mint-httpd_json.h" 34#include "taler-mint-httpd_parsing.h"
35#include "taler-mint-httpd_keys.h" 35#include "taler-mint-httpd_keys.h"
36#include "taler-mint-httpd_mhd.h" 36#include "taler-mint-httpd_mhd.h"
37#include "taler-mint-httpd_refresh.h" 37#include "taler-mint-httpd_refresh.h"
38#include "taler-mint-httpd_responses.h"
38 39
39 40
40/** 41/**
@@ -228,10 +229,10 @@ check_confirm_signature (struct MHD_Connection *connection,
228 coin_pub)) 229 coin_pub))
229 { 230 {
230 if (MHD_YES != 231 if (MHD_YES !=
231 request_send_json_pack (connection, 232 TALER_MINT_reply_json_pack (connection,
232 MHD_HTTP_UNAUTHORIZED, 233 MHD_HTTP_UNAUTHORIZED,
233 "{s:s}", 234 "{s:s}",
234 "error", "signature invalid")) 235 "error", "signature invalid"))
235 return GNUNET_SYSERR; 236 return GNUNET_SYSERR;
236 return GNUNET_NO; 237 return GNUNET_NO;
237 } 238 }
@@ -356,15 +357,19 @@ refresh_accept_melts (struct MHD_Connection *connection,
356 dki = &(TALER_MINT_get_denom_key (key_state, &coin_public_info.denom_pub)->issue); 357 dki = &(TALER_MINT_get_denom_key (key_state, &coin_public_info.denom_pub)->issue);
357 358
358 if (NULL == dki) 359 if (NULL == dki)
359 return (MHD_YES == request_send_json_pack (connection, MHD_HTTP_NOT_FOUND, 360 return (MHD_YES ==
360 "{s:s}", 361 TALER_MINT_reply_json_pack (connection,
361 "error", "denom not found")) 362 MHD_HTTP_NOT_FOUND,
363 "{s:s}",
364 "error", "denom not found"))
362 ? GNUNET_NO : GNUNET_SYSERR; 365 ? GNUNET_NO : GNUNET_SYSERR;
363 366
364 if (GNUNET_OK != TALER_MINT_test_coin_valid (key_state, &coin_public_info)) 367 if (GNUNET_OK != TALER_MINT_test_coin_valid (key_state, &coin_public_info))
365 return (MHD_YES == request_send_json_pack (connection, MHD_HTTP_NOT_FOUND, 368 return (MHD_YES ==
366 "{s:s}", 369 TALER_MINT_reply_json_pack (connection,
367 "error", "coin invalid")) 370 MHD_HTTP_NOT_FOUND,
371 "{s:s}",
372 "error", "coin invalid"))
368 ? GNUNET_NO : GNUNET_SYSERR; 373 ? GNUNET_NO : GNUNET_SYSERR;
369 374
370 res = TALER_MINT_DB_get_known_coin (db_conn, &coin_public_info.coin_pub, 375 res = TALER_MINT_DB_get_known_coin (db_conn, &coin_public_info.coin_pub,
@@ -379,9 +384,13 @@ refresh_accept_melts (struct MHD_Connection *connection,
379 if (GNUNET_YES == res) 384 if (GNUNET_YES == res)
380 { 385 {
381 if (GNUNET_YES == known_coin.is_refreshed) 386 if (GNUNET_YES == known_coin.is_refreshed)
382 return (MHD_YES == request_send_json_pack (connection, MHD_HTTP_NOT_FOUND, 387 return (MHD_YES ==
383 "{s:s}", 388 TALER_MINT_reply_json_pack (connection,
384 "error", "coin already refreshed")) ? GNUNET_NO : GNUNET_SYSERR; 389 MHD_HTTP_NOT_FOUND,
390 "{s:s}",
391 "error",
392 "coin already refreshed"))
393 ? GNUNET_NO : GNUNET_SYSERR;
385 } 394 }
386 else 395 else
387 { 396 {
@@ -413,9 +422,11 @@ refresh_accept_melts (struct MHD_Connection *connection,
413 * pay the refreshing fees of the coin. */ 422 * pay the refreshing fees of the coin. */
414 423
415 if (TALER_amount_cmp (coin_gain, TALER_amount_ntoh (dki->fee_refresh)) < 0) 424 if (TALER_amount_cmp (coin_gain, TALER_amount_ntoh (dki->fee_refresh)) < 0)
416 return (MHD_YES == request_send_json_pack (connection, MHD_HTTP_NOT_FOUND, 425 return (MHD_YES ==
417 "{s:s}", 426 TALER_MINT_reply_json_pack (connection,
418 "error", "depleted")) ? GNUNET_NO : GNUNET_SYSERR; 427 MHD_HTTP_NOT_FOUND,
428 "{s:s}",
429 "error", "depleted")) ? GNUNET_NO : GNUNET_SYSERR;
419 430
420 coin_gain = TALER_amount_subtract (coin_gain, TALER_amount_ntoh (dki->fee_refresh)); 431 coin_gain = TALER_amount_subtract (coin_gain, TALER_amount_ntoh (dki->fee_refresh));
421 432
@@ -472,9 +483,9 @@ helper_refresh_send_melt_response (struct MHD_Connection *connection,
472 json_object_set (root, "signature", sig_json); 483 json_object_set (root, "signature", sig_json);
473 } 484 }
474 485
475 return send_response_json (connection, 486 return TALER_MINT_reply_json (connection,
476 root, 487 root,
477 MHD_HTTP_OK); 488 MHD_HTTP_OK);
478} 489}
479 490
480 491
@@ -524,9 +535,10 @@ request_json_check_signature (struct MHD_Connection *connection,
524 if (purpose_num != ntohl (purpose->purpose)) 535 if (purpose_num != ntohl (purpose->purpose))
525 { 536 {
526 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "signature invalid (purpose wrong)\n"); 537 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "signature invalid (purpose wrong)\n");
527 return request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST, 538 return TALER_MINT_reply_json_pack (connection,
528 "{s:s}", 539 MHD_HTTP_BAD_REQUEST,
529 "error", "signature invalid (purpose)"); 540 "{s:s}",
541 "error", "signature invalid (purpose)");
530 } 542 }
531 543
532 res = request_json_require_nav (connection, root, 544 res = request_json_require_nav (connection, root,
@@ -543,10 +555,11 @@ request_json_check_signature (struct MHD_Connection *connection,
543 if (size != ntohl (purpose->size)) 555 if (size != ntohl (purpose->size))
544 { 556 {
545 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "signature invalid (size wrong)\n"); 557 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "signature invalid (size wrong)\n");
546 return request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST, 558 return TALER_MINT_reply_json_pack (connection,
547 GNUNET_NO, GNUNET_SYSERR, 559 MHD_HTTP_BAD_REQUEST,
548 "{s:s}", 560 GNUNET_NO, GNUNET_SYSERR,
549 "error", "signature invalid (size)"); 561 "{s:s}",
562 "error", "signature invalid (size)");
550 } 563 }
551 564
552 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (purpose_num, 565 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (purpose_num,
@@ -555,9 +568,11 @@ request_json_check_signature (struct MHD_Connection *connection,
555 pub)) 568 pub))
556 { 569 {
557 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "signature invalid (did not verify)\n"); 570 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "signature invalid (did not verify)\n");
558 return request_send_json_pack (connection, MHD_HTTP_UNAUTHORIZED, 571 return TALER_MINT_reply_json_pack (connection,
559 "{s:s}", 572 MHD_HTTP_UNAUTHORIZED,
560 "error", "invalid signature (verification)"); 573 "{s:s}",
574 "error",
575 "invalid signature (verification)");
561 } 576 }
562 577
563 return GNUNET_OK; 578 return GNUNET_OK;
@@ -705,10 +720,11 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh,
705 if (NULL == melt_sig_json) 720 if (NULL == melt_sig_json)
706 { 721 {
707 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn)); 722 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn));
708 return request_send_json_pack (connection, 723 return TALER_MINT_reply_json_pack (connection,
709 MHD_HTTP_BAD_REQUEST, 724 MHD_HTTP_BAD_REQUEST,
710 "{s:s}", 725 "{s:s}",
711 "error", "melt_signature missing"); 726 "error",
727 "melt_signature missing");
712 } 728 }
713 729
714 body.melt_hash = melt_hash; 730 body.melt_hash = melt_hash;
@@ -734,9 +750,11 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh,
734 { 750 {
735 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn)); 751 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn));
736 752
737 return request_send_json_pack (connection, MHD_HTTP_FORBIDDEN, 753 return TALER_MINT_reply_json_pack (connection,
738 "{s:s}", 754 MHD_HTTP_FORBIDDEN,
739 "error", "not enough coins melted"); 755 "{s:s}",
756 "error",
757 "not enough coins melted");
740 } 758 }
741 759
742 if (GNUNET_OK != TALER_MINT_DB_commit (db_conn)) 760 if (GNUNET_OK != TALER_MINT_DB_commit (db_conn))
@@ -771,10 +789,11 @@ refresh_send_commit_response (struct MHD_Connection *connection,
771 body.noreveal_index = htons (refresh_session->noreveal_index); 789 body.noreveal_index = htons (refresh_session->noreveal_index);
772 sig_json = sign_as_json (&body.purpose); 790 sig_json = sign_as_json (&body.purpose);
773 GNUNET_assert (NULL != sig_json); 791 GNUNET_assert (NULL != sig_json);
774 return request_send_json_pack (connection, MHD_HTTP_OK, 792 return TALER_MINT_reply_json_pack (connection,
775 "{s:i, s:o}", 793 MHD_HTTP_OK,
776 "noreveal_index", (int) refresh_session->noreveal_index, 794 "{s:i, s:o}",
777 "signature", sig_json); 795 "noreveal_index", (int) refresh_session->noreveal_index,
796 "signature", sig_json);
778} 797}
779 798
780 799
@@ -1022,9 +1041,11 @@ TALER_MINT_handler_refresh_commit (struct RequestHandler *rh,
1022 if (NULL == commit_sig_json) 1041 if (NULL == commit_sig_json)
1023 { 1042 {
1024 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn)); 1043 GNUNET_break (GNUNET_OK == TALER_MINT_DB_rollback (db_conn));
1025 return request_send_json_pack (connection, MHD_HTTP_BAD_REQUEST, 1044 return TALER_MINT_reply_json_pack (connection,
1026 "{s:s}", 1045 MHD_HTTP_BAD_REQUEST,
1027 "error", "commit_signature missing"); 1046 "{s:s}",
1047 "error",
1048 "commit_signature missing");
1028 } 1049 }
1029 1050
1030 body.commit_hash = commit_hash; 1051 body.commit_hash = commit_hash;
@@ -1106,9 +1127,9 @@ helper_refresh_reveal_send_response (struct MHD_Connection *connection,
1106 TALER_JSON_from_data (&ev_sig, 1127 TALER_JSON_from_data (&ev_sig,
1107 sizeof (struct TALER_RSA_Signature))); 1128 sizeof (struct TALER_RSA_Signature)));
1108 } 1129 }
1109 return send_response_json (connection, 1130 return TALER_MINT_reply_json (connection,
1110 root, 1131 root,
1111 MHD_HTTP_OK); 1132 MHD_HTTP_OK);
1112} 1133}
1113 1134
1114 1135
@@ -1471,10 +1492,11 @@ TALER_MINT_handler_refresh_link (struct RequestHandler *rh,
1471 } 1492 }
1472 if (GNUNET_NO == res) 1493 if (GNUNET_NO == res)
1473 { 1494 {
1474 return request_send_json_pack (connection, 1495 return TALER_MINT_reply_json_pack (connection,
1475 MHD_HTTP_NOT_FOUND, 1496 MHD_HTTP_NOT_FOUND,
1476 "{s:s}", 1497 "{s:s}",
1477 "error", "link data not found (transfer)"); 1498 "error",
1499 "link data not found (transfer)");
1478 } 1500 }
1479 GNUNET_assert (GNUNET_OK == res); 1501 GNUNET_assert (GNUNET_OK == res);
1480 1502
@@ -1486,10 +1508,11 @@ TALER_MINT_handler_refresh_link (struct RequestHandler *rh,
1486 } 1508 }
1487 if (GNUNET_NO == res) 1509 if (GNUNET_NO == res)
1488 { 1510 {
1489 return request_send_json_pack (connection, 1511 return TALER_MINT_reply_json_pack (connection,
1490 MHD_HTTP_NOT_FOUND, 1512 MHD_HTTP_NOT_FOUND,
1491 "{s:s}", 1513 "{s:s}",
1492 "error", "link data not found (link)"); 1514 "error",
1515 "link data not found (link)");
1493 } 1516 }
1494 GNUNET_assert (GNUNET_OK == res); 1517 GNUNET_assert (GNUNET_OK == res);
1495 json_object_set_new (root, "transfer_pub", 1518 json_object_set_new (root, "transfer_pub",
@@ -1498,7 +1521,9 @@ TALER_MINT_handler_refresh_link (struct RequestHandler *rh,
1498 json_object_set_new (root, "secret_enc", 1521 json_object_set_new (root, "secret_enc",
1499 TALER_JSON_from_data (&shared_secret_enc, 1522 TALER_JSON_from_data (&shared_secret_enc,
1500 sizeof (struct SharedSecretEnc))); 1523 sizeof (struct SharedSecretEnc)));
1501 return send_response_json (connection, root, MHD_HTTP_OK); 1524 return TALER_MINT_reply_json (connection,
1525 root,
1526 MHD_HTTP_OK);
1502} 1527}
1503 1528
1504 1529
diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c
new file mode 100644
index 000000000..8f886c3d9
--- /dev/null
+++ b/src/mint/taler-mint-httpd_responses.c
@@ -0,0 +1,146 @@
1/*
2 This file is part of TALER
3 (C) 2014 GNUnet e.V.
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16
17/**
18 * @file taler-mint-httpd_responses.c
19 * @brief API for generating the various replies of the mint; these
20 * functions are called TALER_MINT_reply_ and they generate
21 * and queue MHD response objects for a given connection.
22 * @author Florian Dold
23 * @author Benedikt Mueller
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "taler-mint-httpd_responses.h"
28
29
30/**
31 * Send JSON object as response. Decreases the reference count of the
32 * JSON object.
33 *
34 * @param connection the MHD connection
35 * @param json the json object
36 * @param response_code the http response code
37 * @return MHD result code
38 */
39int
40TALER_MINT_reply_json (struct MHD_Connection *connection,
41 json_t *json,
42 unsigned int response_code)
43{
44 struct MHD_Response *resp;
45 char *json_str;
46 int ret;
47
48 json_str = json_dumps (json, JSON_INDENT(2));
49 json_decref (json);
50 resp = MHD_create_response_from_buffer (strlen (json_str), json_str,
51 MHD_RESPMEM_MUST_FREE);
52 if (NULL == resp)
53 return MHD_NO;
54 (void) MHD_add_response_header (resp,
55 MHD_HTTP_HEADER_CONTENT_TYPE,
56 "application/json");
57 ret = MHD_queue_response (connection, response_code, resp);
58 MHD_destroy_response (resp);
59 return ret;
60}
61
62
63/**
64 * Function to call to handle the request by building a JSON
65 * reply from a format string and varargs.
66 *
67 * @param connection the MHD connection to handle
68 * @param response_code HTTP response code to use
69 * @param fmt format string for pack
70 * @param ... varargs
71 * @return MHD result code
72 */
73int
74TALER_MINT_reply_json_pack (struct MHD_Connection *connection,
75 unsigned int response_code,
76 const char *fmt,
77 ...)
78{
79 json_t *json;
80 va_list argp;
81
82 va_start (argp, fmt);
83 json = json_vpack_ex (NULL, 0, fmt, argp);
84 va_end (argp);
85 if (NULL == json)
86 return MHD_NO;
87 return TALER_MINT_reply_json (connection,
88 json,
89 response_code);
90}
91
92
93/**
94 * Send a response indicating an invalid argument.
95 *
96 * @param connection the MHD connection to use
97 * @param param_name the parameter that is invalid
98 * @return a MHD result code
99 */
100int
101TALER_MINT_reply_arg_invalid (struct MHD_Connection *connection,
102 const char *param_name)
103{
104 json_t *json;
105
106 json = json_pack ("{ s:s, s:s }",
107 "error",
108 "invalid parameter",
109 "parameter",
110 param_name);
111 return TALER_MINT_reply_json (connection,
112 json,
113 MHD_HTTP_BAD_REQUEST);
114}
115
116
117/**
118 * Send a response indicating a missing argument.
119 *
120 * @param connection the MHD connection to use
121 * @param param_name the parameter that is missing
122 * @return a MHD result code
123 */
124int
125TALER_MINT_reply_arg_missing (struct MHD_Connection *connection,
126 const char *param_name)
127{
128 json_t *json;
129
130 json = json_pack ("{ s:s, s:s }",
131 "error",
132 "missing parameter",
133 "parameter",
134 param_name);
135 return TALER_MINT_reply_json (connection,
136 json,
137 MHD_HTTP_BAD_REQUEST);
138}
139
140
141
142
143
144
145
146/* end of taler-mint-httpd_responses.c */
diff --git a/src/mint/taler-mint-httpd_responses.h b/src/mint/taler-mint-httpd_responses.h
new file mode 100644
index 000000000..0e48341fd
--- /dev/null
+++ b/src/mint/taler-mint-httpd_responses.h
@@ -0,0 +1,93 @@
1/*
2 This file is part of TALER
3 (C) 2014 GNUnet e.V.
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16
17/**
18 * @file taler-mint-httpd_responses.h
19 * @brief API for generating the various replies of the mint; these
20 * functions are called TALER_MINT_reply_ and they generate
21 * and queue MHD response objects for a given connection.
22 * @author Florian Dold
23 * @author Benedikt Mueller
24 * @author Christian Grothoff
25 */
26#ifndef TALER_MINT_HTTPD_RESPONSES_H
27#define TALER_MINT_HTTPD_RESPONSES_H
28#include <gnunet/gnunet_util_lib.h>
29#include <jansson.h>
30#include <microhttpd.h>
31#include <libpq-fe.h>
32#include <pthread.h>
33#include "taler-mint-httpd.h"
34#include "taler-mint-httpd_mhd.h"
35
36
37/**
38 * Send JSON object as response. Decreases the reference count of the
39 * JSON object.
40 *
41 * @param connection the MHD connection
42 * @param json the json object
43 * @param response_code the http response code
44 * @return MHD result code
45 */
46int
47TALER_MINT_reply_json (struct MHD_Connection *connection,
48 json_t *json,
49 unsigned int response_code);
50
51
52/**
53 * Function to call to handle the request by building a JSON
54 * reply from a format string and varargs.
55 *
56 * @param connection the MHD connection to handle
57 * @param response_code HTTP response code to use
58 * @param fmt format string for pack
59 * @param ... varargs
60 * @return MHD result code
61 */
62int
63TALER_MINT_reply_json_pack (struct MHD_Connection *connection,
64 unsigned int response_code,
65 const char *fmt,
66 ...);
67
68
69/**
70 * Send a response indicating an invalid argument.
71 *
72 * @param connection the MHD connection to use
73 * @param param_name the parameter that is invalid
74 * @return MHD result code
75 */
76int
77TALER_MINT_reply_arg_invalid (struct MHD_Connection *connection,
78 const char *param_name);
79
80
81/**
82 * Send a response indicating a missing argument.
83 *
84 * @param connection the MHD connection to use
85 * @param param_name the parameter that is missing
86 * @return a MHD result code
87 */
88int
89TALER_MINT_reply_arg_missing (struct MHD_Connection *connection,
90 const char *param_name);
91
92
93#endif
diff --git a/src/mint/taler-mint-httpd_withdraw.c b/src/mint/taler-mint-httpd_withdraw.c
index 22024e80e..cc0de7f6f 100644
--- a/src/mint/taler-mint-httpd_withdraw.c
+++ b/src/mint/taler-mint-httpd_withdraw.c
@@ -31,10 +31,11 @@
31#include "taler_signatures.h" 31#include "taler_signatures.h"
32#include "taler_rsa.h" 32#include "taler_rsa.h"
33#include "taler_json_lib.h" 33#include "taler_json_lib.h"
34#include "taler-mint-httpd_json.h" 34#include "taler-mint-httpd_parsing.h"
35#include "taler-mint-httpd_keys.h" 35#include "taler-mint-httpd_keys.h"
36#include "taler-mint-httpd_mhd.h" 36#include "taler-mint-httpd_mhd.h"
37#include "taler-mint-httpd_withdraw.h" 37#include "taler-mint-httpd_withdraw.h"
38#include "taler-mint-httpd_responses.h"
38 39
39 40
40/** 41/**
@@ -135,14 +136,11 @@ TALER_MINT_handler_withdraw_status (struct RequestHandler *rh,
135 &reserve_pub, 136 &reserve_pub,
136 &reserve); 137 &reserve);
137 if (GNUNET_SYSERR == res) 138 if (GNUNET_SYSERR == res)
138 return TALER_MINT_helper_send_json_pack (rh, 139 return TALER_MINT_reply_json_pack (connection,
139 connection, 140 MHD_HTTP_NOT_FOUND,
140 connection_cls, 141 "{s:s}",
141 0 /* no caching */, 142 "error",
142 MHD_HTTP_NOT_FOUND, 143 "Reserve not found");
143 "{s:s}",
144 "error",
145 "Reserve not found");
146 if (GNUNET_OK != res) 144 if (GNUNET_OK != res)
147 { 145 {
148 // FIXME: return 'internal error'? 146 // FIXME: return 'internal error'?
@@ -178,9 +176,9 @@ TALER_MINT_handler_withdraw_status (struct RequestHandler *rh,
178 sig_to_json (&reserve.status_sig_purpose, 176 sig_to_json (&reserve.status_sig_purpose,
179 &reserve.status_sig)); 177 &reserve.status_sig));
180 178
181 return send_response_json (connection, 179 return TALER_MINT_reply_json (connection,
182 json, 180 json,
183 MHD_HTTP_OK); 181 MHD_HTTP_OK);
184} 182}
185 183
186 184
@@ -200,9 +198,9 @@ helper_withdraw_sign_send_reply (struct MHD_Connection *connection,
200 json_object_set_new (root, "ev_sig", 198 json_object_set_new (root, "ev_sig",
201 TALER_JSON_from_data (&collectable->ev_sig, 199 TALER_JSON_from_data (&collectable->ev_sig,
202 sizeof (struct TALER_RSA_Signature))); 200 sizeof (struct TALER_RSA_Signature)));
203 return send_response_json (connection, 201 return TALER_MINT_reply_json (connection,
204 root, 202 root,
205 MHD_HTTP_OK); 203 MHD_HTTP_OK);
206} 204}
207 205
208 206
@@ -317,10 +315,11 @@ TALER_MINT_handler_withdraw_sign (struct RequestHandler *rh,
317 return MHD_NO; 315 return MHD_NO;
318 } 316 }
319 if (GNUNET_NO == res) 317 if (GNUNET_NO == res)
320 return request_send_json_pack (connection, 318 return TALER_MINT_reply_json_pack (connection,
321 MHD_HTTP_NOT_FOUND, 319 MHD_HTTP_NOT_FOUND,
322 "{s:s}", 320 "{s:s}",
323 "error", "Reserve not found"); 321 "error",
322 "Reserve not found");
324 323
325 // fill out all the missing info in the request before 324 // fill out all the missing info in the request before
326 // we can check the signature on the request 325 // we can check the signature on the request
@@ -334,19 +333,21 @@ TALER_MINT_handler_withdraw_sign (struct RequestHandler *rh,
334 &wsrd.purpose, 333 &wsrd.purpose,
335 &wsrd.sig, 334 &wsrd.sig,
336 &wsrd.reserve_pub)) 335 &wsrd.reserve_pub))
337 return request_send_json_pack (connection, 336 return TALER_MINT_reply_json_pack (connection,
338 MHD_HTTP_UNAUTHORIZED, 337 MHD_HTTP_UNAUTHORIZED,
339 "{s:s}", 338 "{s:s}",
340 "error", "Invalid Signature"); 339 "error", "Invalid Signature");
341 340
342 key_state = TALER_MINT_key_state_acquire (); 341 key_state = TALER_MINT_key_state_acquire ();
343 dki = TALER_MINT_get_denom_key (key_state, 342 dki = TALER_MINT_get_denom_key (key_state,
344 &wsrd.denomination_pub); 343 &wsrd.denomination_pub);
345 TALER_MINT_key_state_release (key_state); 344 TALER_MINT_key_state_release (key_state);
346 if (NULL == dki) 345 if (NULL == dki)
347 return request_send_json_pack (connection, MHD_HTTP_NOT_FOUND, 346 return TALER_MINT_reply_json_pack (connection,
348 "{s:s}", 347 MHD_HTTP_NOT_FOUND,
349 "error", "Denomination not found"); 348 "{s:s}",
349 "error",
350 "Denomination not found");
350 351
351 amount_required = TALER_amount_ntoh (dki->issue.value); 352 amount_required = TALER_amount_ntoh (dki->issue.value);
352 amount_required = TALER_amount_add (amount_required, 353 amount_required = TALER_amount_add (amount_required,
@@ -354,14 +355,16 @@ TALER_MINT_handler_withdraw_sign (struct RequestHandler *rh,
354 355
355 if (0 < TALER_amount_cmp (amount_required, 356 if (0 < TALER_amount_cmp (amount_required,
356 TALER_amount_ntoh (reserve.balance))) 357 TALER_amount_ntoh (reserve.balance)))
357 return request_send_json_pack (connection, 358 return TALER_MINT_reply_json_pack (connection,
358 MHD_HTTP_PAYMENT_REQUIRED, 359 MHD_HTTP_PAYMENT_REQUIRED,
359 "{s:s}", 360 "{s:s}",
360 "error", "Insufficient funds"); 361 "error",
361 if (GNUNET_OK != TALER_RSA_sign (dki->denom_priv, 362 "Insufficient funds");
362 &wsrd.coin_envelope, 363 if (GNUNET_OK !=
363 sizeof (struct TALER_RSA_BlindedSignaturePurpose), 364 TALER_RSA_sign (dki->denom_priv,
364 &ev_sig)) 365 &wsrd.coin_envelope,
366 sizeof (struct TALER_RSA_BlindedSignaturePurpose),
367 &ev_sig))
365 { 368 {
366 // FIXME: return 'internal error' 369 // FIXME: return 'internal error'
367 GNUNET_break (0); 370 GNUNET_break (0);