exchange_api_post-auditors-AUDITOR_PUB-H_DENOM_PUB.c (7686B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2015-2026 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU 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 General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 TALER; see the file COPYING. If not, see 15 <http://www.gnu.org/licenses/> 16 */ 17 /** 18 * @file lib/exchange_api_post-auditors-AUDITOR_PUB-H_DENOM_PUB.c 19 * @brief functions for the auditor to add its signature for denomination at the exchange 20 * @author Christian Grothoff 21 */ 22 #include "taler/taler_json_lib.h" 23 #include <gnunet/gnunet_curl_lib.h> 24 #include <microhttpd.h> 25 #include "taler/exchange/post-auditors-AUDITOR_PUB-H_DENOM_PUB.h" 26 #include "auditor_api_curl_defaults.h" 27 #include "taler/taler_curl_lib.h" 28 29 30 struct TALER_EXCHANGE_PostAuditorsHandle 31 { 32 33 /** 34 * The base URL for this request. 35 */ 36 char *base_url; 37 38 /** 39 * The full URL for this request, set during _start. 40 */ 41 char *url; 42 43 /** 44 * Minor context that holds body and headers. 45 */ 46 struct TALER_CURL_PostContext post_ctx; 47 48 /** 49 * Handle for the request. 50 */ 51 struct GNUNET_CURL_Job *job; 52 53 /** 54 * Function to call with the result. 55 */ 56 TALER_EXCHANGE_PostAuditorsCallback cb; 57 58 /** 59 * Closure for @a cb. 60 */ 61 TALER_EXCHANGE_POST_AUDITORS_RESULT_CLOSURE *cb_cls; 62 63 /** 64 * Reference to the execution context. 65 */ 66 struct GNUNET_CURL_Context *ctx; 67 68 /** 69 * Hash of the denomination public key. 70 */ 71 struct TALER_DenominationHashP h_denom_pub; 72 73 /** 74 * The auditor's public key. 75 */ 76 struct TALER_AuditorPublicKeyP auditor_pub; 77 78 /** 79 * The auditor's signature. 80 */ 81 struct TALER_AuditorSignatureP auditor_sig; 82 83 }; 84 85 86 /** 87 * Function called when we're done processing the 88 * HTTP POST /auditor/$AUDITOR_PUB/$H_DENOM_PUB request. 89 * 90 * @param cls the `struct TALER_EXCHANGE_PostAuditorsHandle *` 91 * @param response_code HTTP response code, 0 on error 92 * @param response response body, NULL if not in JSON 93 */ 94 static void 95 handle_auditor_add_denomination_finished (void *cls, 96 long response_code, 97 const void *response) 98 { 99 struct TALER_EXCHANGE_PostAuditorsHandle *ah = cls; 100 const json_t *json = response; 101 struct TALER_EXCHANGE_PostAuditorsResponse adr = { 102 .hr.http_status = (unsigned int) response_code, 103 .hr.reply = json 104 }; 105 106 ah->job = NULL; 107 switch (response_code) 108 { 109 case MHD_HTTP_NO_CONTENT: 110 break; 111 case MHD_HTTP_FORBIDDEN: 112 adr.hr.ec = TALER_JSON_get_error_code (json); 113 adr.hr.hint = TALER_JSON_get_error_hint (json); 114 break; 115 case MHD_HTTP_NOT_FOUND: 116 adr.hr.ec = TALER_JSON_get_error_code (json); 117 adr.hr.hint = TALER_JSON_get_error_hint (json); 118 break; 119 case MHD_HTTP_GONE: 120 adr.hr.ec = TALER_JSON_get_error_code (json); 121 adr.hr.hint = TALER_JSON_get_error_hint (json); 122 break; 123 case MHD_HTTP_PRECONDITION_FAILED: 124 adr.hr.ec = TALER_JSON_get_error_code (json); 125 adr.hr.hint = TALER_JSON_get_error_hint (json); 126 break; 127 default: 128 /* unexpected response code */ 129 if (NULL != json) 130 { 131 adr.hr.ec = TALER_JSON_get_error_code (json); 132 adr.hr.hint = TALER_JSON_get_error_hint (json); 133 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 134 "Unexpected response code %u/%d for exchange auditor-add-denomination at URL `%s'\n", 135 (unsigned int) response_code, 136 (int) adr.hr.ec, 137 ah->url); 138 } 139 else 140 { 141 adr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; 142 adr.hr.hint = NULL; 143 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 144 "Unexpected HTTP response code %u (no JSON returned) at URL `%s'\n", 145 (unsigned int) response_code, 146 ah->url); 147 } 148 break; 149 } 150 if (NULL != ah->cb) 151 { 152 ah->cb (ah->cb_cls, 153 &adr); 154 ah->cb = NULL; 155 } 156 TALER_EXCHANGE_post_auditors_cancel (ah); 157 } 158 159 160 struct TALER_EXCHANGE_PostAuditorsHandle * 161 TALER_EXCHANGE_post_auditors_create ( 162 struct GNUNET_CURL_Context *ctx, 163 const char *url, 164 const struct TALER_DenominationHashP *h_denom_pub, 165 const struct TALER_AuditorPublicKeyP *auditor_pub, 166 const struct TALER_AuditorSignatureP *auditor_sig) 167 { 168 struct TALER_EXCHANGE_PostAuditorsHandle *ah; 169 170 ah = GNUNET_new (struct TALER_EXCHANGE_PostAuditorsHandle); 171 ah->ctx = ctx; 172 ah->base_url = GNUNET_strdup (url); 173 ah->h_denom_pub = *h_denom_pub; 174 ah->auditor_pub = *auditor_pub; 175 ah->auditor_sig = *auditor_sig; 176 return ah; 177 } 178 179 180 enum TALER_ErrorCode 181 TALER_EXCHANGE_post_auditors_start ( 182 struct TALER_EXCHANGE_PostAuditorsHandle *ah, 183 TALER_EXCHANGE_PostAuditorsCallback cb, 184 TALER_EXCHANGE_POST_AUDITORS_RESULT_CLOSURE *cb_cls) 185 { 186 CURL *eh; 187 json_t *body; 188 189 ah->cb = cb; 190 ah->cb_cls = cb_cls; 191 { 192 char apub_str[sizeof (ah->auditor_pub) * 2]; 193 char denom_str[sizeof (ah->h_denom_pub) * 2]; 194 char arg_str[sizeof (apub_str) + sizeof (denom_str) + 32]; 195 char *end; 196 197 end = GNUNET_STRINGS_data_to_string (&ah->auditor_pub, 198 sizeof (ah->auditor_pub), 199 apub_str, 200 sizeof (apub_str)); 201 *end = '\0'; 202 end = GNUNET_STRINGS_data_to_string (&ah->h_denom_pub, 203 sizeof (ah->h_denom_pub), 204 denom_str, 205 sizeof (denom_str)); 206 *end = '\0'; 207 GNUNET_snprintf (arg_str, 208 sizeof (arg_str), 209 "auditors/%s/%s", 210 apub_str, 211 denom_str); 212 ah->url = TALER_url_join (ah->base_url, 213 arg_str, 214 NULL); 215 } 216 if (NULL == ah->url) 217 { 218 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 219 "Could not construct request URL.\n"); 220 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 221 } 222 body = GNUNET_JSON_PACK ( 223 GNUNET_JSON_pack_data_auto ("auditor_sig", 224 &ah->auditor_sig)); 225 eh = TALER_AUDITOR_curl_easy_get_ (ah->url); 226 if ( (NULL == eh) || 227 (GNUNET_OK != 228 TALER_curl_easy_post (&ah->post_ctx, 229 eh, 230 body)) ) 231 { 232 GNUNET_break (0); 233 if (NULL != eh) 234 curl_easy_cleanup (eh); 235 json_decref (body); 236 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 237 } 238 json_decref (body); 239 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 240 "Requesting URL '%s'\n", 241 ah->url); 242 ah->job = GNUNET_CURL_job_add2 (ah->ctx, 243 eh, 244 ah->post_ctx.headers, 245 &handle_auditor_add_denomination_finished, 246 ah); 247 if (NULL == ah->job) 248 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 249 return TALER_EC_NONE; 250 } 251 252 253 void 254 TALER_EXCHANGE_post_auditors_cancel ( 255 struct TALER_EXCHANGE_PostAuditorsHandle *ah) 256 { 257 if (NULL != ah->job) 258 { 259 GNUNET_CURL_job_cancel (ah->job); 260 ah->job = NULL; 261 } 262 TALER_curl_easy_post_finished (&ah->post_ctx); 263 GNUNET_free (ah->url); 264 GNUNET_free (ah->base_url); 265 GNUNET_free (ah); 266 } 267 268 269 /* end of exchange_api_post-auditors-AUDITOR_PUB-H_DENOM_PUB.c */