exchange_api_get-aml-OFFICER_PUB.c (6294B)
1 /* 2 This file is part of TALER 3 Copyright (C) 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 /** 10 * @file lib/exchange_api_get-aml-OFFICER_PUB.c 11 * @brief Implementation of GET /aml/$OFFICER_PUB 12 */ 13 #include <microhttpd.h> 14 #include <gnunet/gnunet_util_lib.h> 15 #include <gnunet/gnunet_curl_lib.h> 16 #include "taler/taler_json_lib.h" 17 #include "taler/exchange/get-aml-OFFICER_PUB.h" 18 #include "exchange_api_handle.h" 19 #include "taler/taler_signatures.h" 20 #include "exchange_api_curl_defaults.h" 21 22 23 /** 24 * Handle for GET /aml/$OFFICER_PUB. 25 */ 26 struct TALER_EXCHANGE_GetAmlOfficerHandle 27 { 28 char *base_url; 29 char *url; 30 struct GNUNET_CURL_Job *job; 31 TALER_EXCHANGE_GetAmlOfficerCallback cb; 32 TALER_EXCHANGE_GET_AML_OFFICER_RESULT_CLOSURE *cb_cls; 33 struct GNUNET_CURL_Context *ctx; 34 struct TALER_AmlOfficerPublicKeyP officer_pub; 35 struct TALER_AmlOfficerPrivateKeyP officer_priv; 36 }; 37 38 39 /** 40 * Process a completed request. 41 * 42 * @param cls operation handle 43 * @param response_code HTTP status, 0 on transport failure 44 * @param response parsed JSON response 45 */ 46 static void 47 handle_get_aml_officer_finished (void *cls, 48 long response_code, 49 const void *response) 50 { 51 struct TALER_EXCHANGE_GetAmlOfficerHandle *gaoh = cls; 52 const json_t *j = response; 53 struct TALER_EXCHANGE_GetAmlOfficerResponse result = { 54 .hr.reply = j, 55 .hr.http_status = (unsigned int) response_code 56 }; 57 58 gaoh->job = NULL; 59 switch (response_code) 60 { 61 case 0: 62 result.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; 63 break; 64 case MHD_HTTP_OK: 65 { 66 struct GNUNET_JSON_Specification spec[] = { 67 GNUNET_JSON_spec_string ( 68 "officer_name", 69 &result.details.ok.officer_name), 70 GNUNET_JSON_spec_bool ( 71 "read_only", 72 &result.details.ok.read_only), 73 GNUNET_JSON_spec_end () 74 }; 75 76 if (GNUNET_OK != 77 GNUNET_JSON_parse (j, 78 spec, 79 NULL, 80 NULL)) 81 { 82 GNUNET_break_op (0); 83 result.hr.http_status = 0; 84 result.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; 85 } 86 break; 87 } 88 case MHD_HTTP_BAD_REQUEST: 89 case MHD_HTTP_FORBIDDEN: 90 case MHD_HTTP_INTERNAL_SERVER_ERROR: 91 result.hr.ec = TALER_JSON_get_error_code (j); 92 result.hr.hint = TALER_JSON_get_error_hint (j); 93 break; 94 default: 95 GNUNET_break_op (0); 96 result.hr.ec = TALER_JSON_get_error_code (j); 97 result.hr.hint = TALER_JSON_get_error_hint (j); 98 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 99 "Unexpected response code %u/%d for GET AML officer\n", 100 (unsigned int) response_code, 101 (int) result.hr.ec); 102 break; 103 } 104 gaoh->cb (gaoh->cb_cls, 105 &result); 106 gaoh->cb = NULL; 107 TALER_EXCHANGE_get_aml_officer_cancel (gaoh); 108 } 109 110 111 struct TALER_EXCHANGE_GetAmlOfficerHandle * 112 TALER_EXCHANGE_get_aml_officer_create ( 113 struct GNUNET_CURL_Context *ctx, 114 const char *url, 115 const struct TALER_AmlOfficerPrivateKeyP *officer_priv) 116 { 117 struct TALER_EXCHANGE_GetAmlOfficerHandle *gaoh; 118 119 gaoh = GNUNET_new (struct TALER_EXCHANGE_GetAmlOfficerHandle); 120 gaoh->ctx = ctx; 121 gaoh->base_url = GNUNET_strdup (url); 122 gaoh->officer_priv = *officer_priv; 123 GNUNET_CRYPTO_eddsa_key_get_public (&officer_priv->eddsa_priv, 124 &gaoh->officer_pub.eddsa_pub); 125 return gaoh; 126 } 127 128 129 enum TALER_ErrorCode 130 TALER_EXCHANGE_get_aml_officer_start ( 131 struct TALER_EXCHANGE_GetAmlOfficerHandle *gaoh, 132 TALER_EXCHANGE_GetAmlOfficerCallback cb, 133 TALER_EXCHANGE_GET_AML_OFFICER_RESULT_CLOSURE *cb_cls) 134 { 135 CURL *eh; 136 struct TALER_AmlOfficerSignatureP officer_sig; 137 char arg_str[sizeof (struct TALER_AmlOfficerPublicKeyP) * 2 + 16]; 138 struct curl_slist *job_headers = NULL; 139 char pub_str[sizeof (gaoh->officer_pub) * 2]; 140 char sig_str[sizeof (officer_sig) * 2]; 141 char *end; 142 char *hdr; 143 144 gaoh->cb = cb; 145 gaoh->cb_cls = cb_cls; 146 TALER_officer_aml_query_sign (&gaoh->officer_priv, 147 &officer_sig); 148 end = GNUNET_STRINGS_data_to_string (&gaoh->officer_pub, 149 sizeof (gaoh->officer_pub), 150 pub_str, 151 sizeof (pub_str)); 152 *end = '\0'; 153 GNUNET_snprintf (arg_str, 154 sizeof (arg_str), 155 "aml/%s", 156 pub_str); 157 gaoh->url = TALER_url_join (gaoh->base_url, 158 arg_str, 159 NULL); 160 if (NULL == gaoh->url) 161 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 162 eh = TALER_EXCHANGE_curl_easy_get_ (gaoh->url); 163 if (NULL == eh) 164 { 165 GNUNET_free (gaoh->url); 166 gaoh->url = NULL; 167 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 168 } 169 end = GNUNET_STRINGS_data_to_string (&officer_sig, 170 sizeof (officer_sig), 171 sig_str, 172 sizeof (sig_str)); 173 *end = '\0'; 174 GNUNET_asprintf (&hdr, 175 "%s: %s", 176 TALER_AML_OFFICER_SIGNATURE_HEADER, 177 sig_str); 178 job_headers = curl_slist_append (NULL, 179 hdr); 180 GNUNET_free (hdr); 181 gaoh->job = GNUNET_CURL_job_add2 (gaoh->ctx, 182 eh, 183 job_headers, 184 &handle_get_aml_officer_finished, 185 gaoh); 186 curl_slist_free_all (job_headers); 187 if (NULL == gaoh->job) 188 { 189 GNUNET_free (gaoh->url); 190 gaoh->url = NULL; 191 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 192 } 193 return TALER_EC_NONE; 194 } 195 196 197 void 198 TALER_EXCHANGE_get_aml_officer_cancel ( 199 struct TALER_EXCHANGE_GetAmlOfficerHandle *gaoh) 200 { 201 if (NULL != gaoh->job) 202 { 203 GNUNET_CURL_job_cancel (gaoh->job); 204 gaoh->job = NULL; 205 } 206 GNUNET_free (gaoh->url); 207 GNUNET_free (gaoh->base_url); 208 GNUNET_free (gaoh); 209 } 210 211 212 /* end of exchange_api_get-aml-OFFICER_PUB.c */