exchange_api_get-kyc-proof-PROVIDER_NAME.c (7756B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2021, 2022, 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_get-kyc-proof-PROVIDER_NAME.c 19 * @brief Implementation of the /kyc-proof request 20 * @author Christian Grothoff 21 */ 22 #include "taler/platform.h" 23 #include <microhttpd.h> /* just for HTTP proof codes */ 24 #include <gnunet/gnunet_util_lib.h> 25 #include <gnunet/gnunet_curl_lib.h> 26 #include "taler/taler_exchange_service.h" 27 #include "taler/taler_json_lib.h" 28 #include "exchange_api_handle.h" 29 #include "taler/taler_signatures.h" 30 #include "exchange_api_curl_defaults.h" 31 #include "taler/taler-exchange/get-kyc-proof-PROVIDER_NAME.h" 32 33 34 /** 35 * @brief A handle for GET /kyc-proof/$PROVIDER_NAME 36 */ 37 struct TALER_EXCHANGE_GetKycProofHandle 38 { 39 40 /** 41 * The base URL of the exchange. 42 */ 43 char *base_url; 44 45 /** 46 * The full URL for this request. 47 */ 48 char *url; 49 50 /** 51 * Handle to our CURL request. 52 */ 53 CURL *eh; 54 55 /** 56 * Handle for the request. 57 */ 58 struct GNUNET_CURL_Job *job; 59 60 /** 61 * Function to call with the result. 62 */ 63 TALER_EXCHANGE_GetKycProofCallback cb; 64 65 /** 66 * Closure for @e cb. 67 */ 68 TALER_EXCHANGE_GET_KYC_PROOF_RESULT_CLOSURE *cb_cls; 69 70 /** 71 * CURL context to use. 72 */ 73 struct GNUNET_CURL_Context *ctx; 74 75 /** 76 * Hash of the payto URI identifying the target account. 77 */ 78 struct TALER_NormalizedPaytoHashP h_payto; 79 80 /** 81 * Name of the KYC logic / provider. Heap-allocated copy. 82 */ 83 char *logic; 84 85 /** 86 * Additional query string arguments to append to the URL. 87 * Borrowed pointer (not owned), must start with '&'. 88 * NULL if not set. 89 */ 90 const char *args; 91 92 }; 93 94 95 /** 96 * Function called when we're done processing the 97 * HTTP GET /kyc-proof request. 98 * 99 * @param cls the `struct TALER_EXCHANGE_GetKycProofHandle` 100 * @param response_code HTTP response code, 0 on error 101 * @param body response body 102 * @param body_size number of bytes in @a body 103 */ 104 static void 105 handle_get_kyc_proof_finished (void *cls, 106 long response_code, 107 const void *body, 108 size_t body_size) 109 { 110 struct TALER_EXCHANGE_GetKycProofHandle *gkph = cls; 111 struct TALER_EXCHANGE_GetKycProofResponse gkpr = { 112 .hr.http_status = (unsigned int) response_code 113 }; 114 115 (void) body; 116 (void) body_size; 117 gkph->job = NULL; 118 switch (response_code) 119 { 120 case 0: 121 break; 122 case MHD_HTTP_SEE_OTHER: 123 { 124 char *redirect_url; 125 126 GNUNET_assert (CURLE_OK == 127 curl_easy_getinfo (gkph->eh, 128 CURLINFO_REDIRECT_URL, 129 &redirect_url)); 130 gkpr.details.found.redirect_url = redirect_url; 131 break; 132 } 133 case MHD_HTTP_BAD_REQUEST: 134 /* This should never happen, either us or the exchange is buggy 135 (or API version conflict); just pass JSON reply to the application */ 136 break; 137 case MHD_HTTP_UNAUTHORIZED: 138 break; 139 case MHD_HTTP_FORBIDDEN: 140 break; 141 case MHD_HTTP_NOT_FOUND: 142 break; 143 case MHD_HTTP_BAD_GATEWAY: 144 /* Server had an internal issue; we should retry, but this API 145 leaves this to the application */ 146 break; 147 case MHD_HTTP_GATEWAY_TIMEOUT: 148 /* Server had an internal issue; we should retry, but this API 149 leaves this to the application */ 150 break; 151 default: 152 /* unexpected response code */ 153 GNUNET_break_op (0); 154 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 155 "Unexpected response code %u for exchange get_kyc_proof\n", 156 (unsigned int) response_code); 157 break; 158 } 159 gkph->cb (gkph->cb_cls, 160 &gkpr); 161 TALER_EXCHANGE_get_kyc_proof_cancel (gkph); 162 } 163 164 165 struct TALER_EXCHANGE_GetKycProofHandle * 166 TALER_EXCHANGE_get_kyc_proof_create ( 167 struct GNUNET_CURL_Context *ctx, 168 const char *url, 169 const struct TALER_NormalizedPaytoHashP *h_payto, 170 const char *logic) 171 { 172 struct TALER_EXCHANGE_GetKycProofHandle *gkph; 173 174 gkph = GNUNET_new (struct TALER_EXCHANGE_GetKycProofHandle); 175 gkph->ctx = ctx; 176 gkph->base_url = GNUNET_strdup (url); 177 gkph->h_payto = *h_payto; 178 gkph->logic = GNUNET_strdup (logic); 179 return gkph; 180 } 181 182 183 enum GNUNET_GenericReturnValue 184 TALER_EXCHANGE_get_kyc_proof_set_options_ ( 185 struct TALER_EXCHANGE_GetKycProofHandle *gkph, 186 unsigned int num_options, 187 const struct TALER_EXCHANGE_GetKycProofOptionValue *options) 188 { 189 for (unsigned int i = 0; i < num_options; i++) 190 { 191 const struct TALER_EXCHANGE_GetKycProofOptionValue *opt = &options[i]; 192 193 switch (opt->option) 194 { 195 case TALER_EXCHANGE_GET_KYC_PROOF_OPTION_END: 196 return GNUNET_OK; 197 case TALER_EXCHANGE_GET_KYC_PROOF_OPTION_ARGS: 198 GNUNET_assert (opt->details.args[0] == '&'); 199 gkph->args = opt->details.args; 200 break; 201 } 202 } 203 return GNUNET_OK; 204 } 205 206 207 enum TALER_ErrorCode 208 TALER_EXCHANGE_get_kyc_proof_start ( 209 struct TALER_EXCHANGE_GetKycProofHandle *gkph, 210 TALER_EXCHANGE_GetKycProofCallback cb, 211 TALER_EXCHANGE_GET_KYC_PROOF_RESULT_CLOSURE *cb_cls) 212 { 213 char *arg_str; 214 215 if (NULL != gkph->job) 216 { 217 GNUNET_break (0); 218 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 219 } 220 gkph->cb = cb; 221 gkph->cb_cls = cb_cls; 222 { 223 char hstr[sizeof (gkph->h_payto) * 2]; 224 char *end; 225 226 end = GNUNET_STRINGS_data_to_string (&gkph->h_payto, 227 sizeof (gkph->h_payto), 228 hstr, 229 sizeof (hstr)); 230 *end = '\0'; 231 GNUNET_asprintf (&arg_str, 232 "kyc-proof/%s?state=%s%s", 233 gkph->logic, 234 hstr, 235 (NULL != gkph->args) ? gkph->args : ""); 236 } 237 gkph->url = TALER_url_join (gkph->base_url, 238 arg_str, 239 NULL); 240 GNUNET_free (arg_str); 241 if (NULL == gkph->url) 242 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 243 gkph->eh = TALER_EXCHANGE_curl_easy_get_ (gkph->url); 244 if (NULL == gkph->eh) 245 { 246 GNUNET_break (0); 247 GNUNET_free (gkph->url); 248 gkph->url = NULL; 249 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 250 } 251 /* disable location following, we want to learn the 252 result of a 303 redirect! */ 253 curl_easy_setopt (gkph->eh, 254 CURLOPT_FOLLOWLOCATION, 255 0L); 256 gkph->job = GNUNET_CURL_job_add_raw (gkph->ctx, 257 gkph->eh, 258 NULL, 259 &handle_get_kyc_proof_finished, 260 gkph); 261 if (NULL == gkph->job) 262 { 263 curl_easy_cleanup (gkph->eh); 264 gkph->eh = NULL; 265 GNUNET_free (gkph->url); 266 gkph->url = NULL; 267 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 268 } 269 return TALER_EC_NONE; 270 } 271 272 273 void 274 TALER_EXCHANGE_get_kyc_proof_cancel ( 275 struct TALER_EXCHANGE_GetKycProofHandle *gkph) 276 { 277 if (NULL != gkph->job) 278 { 279 GNUNET_CURL_job_cancel (gkph->job); 280 gkph->job = NULL; 281 } 282 GNUNET_free (gkph->url); 283 GNUNET_free (gkph->logic); 284 GNUNET_free (gkph->base_url); 285 GNUNET_free (gkph); 286 } 287 288 289 /* end of exchange_api_get-kyc-proof-PROVIDER_NAME.c */