merchant_api_post_instance_auth.c (6447B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2014-2021 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Lesser General Public License as published by the Free Software 7 Foundation; either version 2.1, 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 Lesser General Public License for more details. 12 13 You should have received a copy of the GNU Lesser General Public License along with 14 TALER; see the file COPYING.LGPL. If not, see 15 <http://www.gnu.org/licenses/> 16 */ 17 /** 18 * @file merchant_api_post_instance_auth.c 19 * @brief Implementation of the POST /instance/$ID/private/auth request 20 * @author Christian Grothoff 21 */ 22 #include "platform.h" 23 #include <curl/curl.h> 24 #include <jansson.h> 25 #include <microhttpd.h> /* just for HTTP status codes */ 26 #include <gnunet/gnunet_util_lib.h> 27 #include <gnunet/gnunet_curl_lib.h> 28 #include "taler_merchant_service.h" 29 #include "merchant_api_curl_defaults.h" 30 #include <taler/taler_json_lib.h> 31 #include <taler/taler_signatures.h> 32 #include <taler/taler_curl_lib.h> 33 34 35 /** 36 * Handle for a POST /instances/$ID/private/auth operation. 37 */ 38 struct TALER_MERCHANT_InstanceAuthPostHandle 39 { 40 /** 41 * The url for this request. 42 */ 43 char *url; 44 45 /** 46 * Handle for the request. 47 */ 48 struct GNUNET_CURL_Job *job; 49 50 /** 51 * Function to call with the result. 52 */ 53 TALER_MERCHANT_InstanceAuthPostCallback cb; 54 55 /** 56 * Closure for @a cb. 57 */ 58 void *cb_cls; 59 60 /** 61 * Reference to the execution context. 62 */ 63 struct GNUNET_CURL_Context *ctx; 64 65 /** 66 * Minor context that holds body and headers. 67 */ 68 struct TALER_CURL_PostContext post_ctx; 69 70 }; 71 72 73 /** 74 * Function called when we're done processing the 75 * HTTP GET /instances/$ID/private/auth request. 76 * 77 * @param cls the `struct TALER_MERCHANT_InstanceAuthPostHandle` 78 * @param response_code HTTP response code, 0 on error 79 * @param response response body, NULL if not in JSON 80 */ 81 static void 82 handle_post_instance_auth_finished (void *cls, 83 long response_code, 84 const void *response) 85 { 86 struct TALER_MERCHANT_InstanceAuthPostHandle *iaph = cls; 87 const json_t *json = response; 88 struct TALER_MERCHANT_HttpResponse hr = { 89 .http_status = (unsigned int) response_code, 90 .reply = json 91 }; 92 93 iaph->job = NULL; 94 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 95 "Got /instances/$ID response with status code %u\n", 96 (unsigned int) response_code); 97 switch (response_code) 98 { 99 case MHD_HTTP_NO_CONTENT: 100 break; 101 case MHD_HTTP_BAD_REQUEST: 102 /* happens if the auth token is malformed */ 103 hr.ec = TALER_JSON_get_error_code (json); 104 hr.hint = TALER_JSON_get_error_hint (json); 105 /* Nothing really to verify, merchant says we need to authenticate. */ 106 break; 107 case MHD_HTTP_UNAUTHORIZED: 108 hr.ec = TALER_JSON_get_error_code (json); 109 hr.hint = TALER_JSON_get_error_hint (json); 110 /* Nothing really to verify, merchant says we need to authenticate. */ 111 break; 112 default: 113 /* unexpected response code */ 114 hr.ec = TALER_JSON_get_error_code (json); 115 hr.hint = TALER_JSON_get_error_hint (json); 116 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 117 "Unexpected response code %u/%d\n", 118 (unsigned int) response_code, 119 (int) hr.ec); 120 break; 121 } 122 iaph->cb (iaph->cb_cls, 123 &hr); 124 TALER_MERCHANT_instance_auth_post_cancel (iaph); 125 } 126 127 128 struct TALER_MERCHANT_InstanceAuthPostHandle * 129 TALER_MERCHANT_instance_auth_post ( 130 struct GNUNET_CURL_Context *ctx, 131 const char *backend_url, 132 const char *instance_id, 133 const char *auth_password, 134 TALER_MERCHANT_InstanceAuthPostCallback cb, 135 void *cb_cls) 136 { 137 struct TALER_MERCHANT_InstanceAuthPostHandle *iaph; 138 json_t *req_obj; 139 140 iaph = GNUNET_new (struct TALER_MERCHANT_InstanceAuthPostHandle); 141 iaph->ctx = ctx; 142 iaph->cb = cb; 143 iaph->cb_cls = cb_cls; 144 if (NULL != instance_id) 145 { 146 char *path; 147 148 GNUNET_asprintf (&path, 149 "management/instances/%s/auth", 150 instance_id); 151 iaph->url = TALER_url_join (backend_url, 152 path, 153 NULL); 154 GNUNET_free (path); 155 } 156 else 157 { 158 /* backend_url is already identifying the instance */ 159 iaph->url = TALER_url_join (backend_url, 160 "private/auth", 161 NULL); 162 } 163 if (NULL == iaph->url) 164 { 165 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 166 "Could not construct request URL.\n"); 167 GNUNET_free (iaph); 168 return NULL; 169 } 170 if (NULL == auth_password) 171 { 172 req_obj = GNUNET_JSON_PACK ( 173 GNUNET_JSON_pack_string ("method", 174 "external")); 175 } 176 else 177 { 178 req_obj = GNUNET_JSON_PACK ( 179 GNUNET_JSON_pack_string ("method", 180 "token"), 181 GNUNET_JSON_pack_string ("password", 182 auth_password)); 183 } 184 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 185 "Requesting URL '%s'\n", 186 iaph->url); 187 { 188 CURL *eh; 189 190 eh = TALER_MERCHANT_curl_easy_get_ (iaph->url); 191 if (GNUNET_OK != 192 TALER_curl_easy_post (&iaph->post_ctx, 193 eh, 194 req_obj)) 195 { 196 GNUNET_break (0); 197 curl_easy_cleanup (eh); 198 json_decref (req_obj); 199 GNUNET_free (iaph->url); 200 GNUNET_free (iaph); 201 return NULL; 202 } 203 json_decref (req_obj); 204 GNUNET_assert (CURLE_OK == 205 curl_easy_setopt (eh, 206 CURLOPT_CUSTOMREQUEST, 207 MHD_HTTP_METHOD_POST)); 208 iaph->job = GNUNET_CURL_job_add2 (ctx, 209 eh, 210 iaph->post_ctx.headers, 211 &handle_post_instance_auth_finished, 212 iaph); 213 } 214 return iaph; 215 } 216 217 218 void 219 TALER_MERCHANT_instance_auth_post_cancel ( 220 struct TALER_MERCHANT_InstanceAuthPostHandle *iaph) 221 { 222 if (NULL != iaph->job) 223 GNUNET_CURL_job_cancel (iaph->job); 224 TALER_curl_easy_post_finished (&iaph->post_ctx); 225 GNUNET_free (iaph->url); 226 GNUNET_free (iaph); 227 }