merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

merchant_api_post-management-instances-INSTANCE-auth.c (7840B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2014-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 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-management-instances-INSTANCE-auth-new.c
     19  * @brief Implementation of the POST /management/instances/$INSTANCE/auth request
     20  * @author Christian Grothoff
     21  */
     22 #include "taler/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/taler-merchant/post-management-instances-INSTANCE-auth.h>
     29 #include "merchant_api_curl_defaults.h"
     30 #include "merchant_api_common.h"
     31 #include <taler/taler_json_lib.h>
     32 #include <taler/taler_curl_lib.h>
     33 
     34 
     35 /**
     36  * Handle for a POST /management/instances/$INSTANCE/auth operation.
     37  */
     38 struct TALER_MERCHANT_PostManagementInstancesAuthHandle
     39 {
     40   /**
     41    * Base URL of the merchant backend.
     42    */
     43   char *base_url;
     44 
     45   /**
     46    * The full URL for this request.
     47    */
     48   char *url;
     49 
     50   /**
     51    * Handle for the request.
     52    */
     53   struct GNUNET_CURL_Job *job;
     54 
     55   /**
     56    * Function to call with the result.
     57    */
     58   TALER_MERCHANT_PostManagementInstancesAuthCallback cb;
     59 
     60   /**
     61    * Closure for @a cb.
     62    */
     63   TALER_MERCHANT_POST_MANAGEMENT_INSTANCES_AUTH_RESULT_CLOSURE *cb_cls;
     64 
     65   /**
     66    * Reference to the execution context.
     67    */
     68   struct GNUNET_CURL_Context *ctx;
     69 
     70   /**
     71    * Minor context that holds body and headers.
     72    */
     73   struct TALER_CURL_PostContext post_ctx;
     74 
     75   /**
     76    * Instance identifier.
     77    */
     78   char *instance_id;
     79 
     80   /**
     81    * New authentication password.
     82    */
     83   char *auth_password;
     84 };
     85 
     86 
     87 /**
     88  * Function called when we're done processing the
     89  * HTTP POST /management/instances/$INSTANCE/auth request.
     90  *
     91  * @param cls the `struct TALER_MERCHANT_PostManagementInstancesAuthHandle`
     92  * @param response_code HTTP response code, 0 on error
     93  * @param response response body, NULL if not in JSON
     94  */
     95 static void
     96 handle_post_management_instances_auth_finished (void *cls,
     97                                                 long response_code,
     98                                                 const void *response)
     99 {
    100   struct TALER_MERCHANT_PostManagementInstancesAuthHandle *piah = cls;
    101   const json_t *json = response;
    102   struct TALER_MERCHANT_PostManagementInstancesAuthResponse iar = {
    103     .hr.http_status = (unsigned int) response_code,
    104     .hr.reply = json
    105   };
    106 
    107   piah->job = NULL;
    108   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    109               "POST /management/instances/$INSTANCE/auth completed with "
    110               "response code %u\n",
    111               (unsigned int) response_code);
    112   switch (response_code)
    113   {
    114   case MHD_HTTP_NO_CONTENT:
    115     break;
    116   case MHD_HTTP_ACCEPTED:
    117     if (GNUNET_OK !=
    118         TALER_MERCHANT_parse_mfa_challenge_response_ (
    119           json,
    120           &iar.details.accepted))
    121     {
    122       GNUNET_break_op (0);
    123       iar.hr.http_status = 0;
    124       iar.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
    125     }
    126     break;
    127   case MHD_HTTP_BAD_REQUEST:
    128     iar.hr.ec = TALER_JSON_get_error_code (json);
    129     iar.hr.hint = TALER_JSON_get_error_hint (json);
    130     break;
    131   case MHD_HTTP_UNAUTHORIZED:
    132     iar.hr.ec = TALER_JSON_get_error_code (json);
    133     iar.hr.hint = TALER_JSON_get_error_hint (json);
    134     break;
    135   default:
    136     iar.hr.ec = TALER_JSON_get_error_code (json);
    137     iar.hr.hint = TALER_JSON_get_error_hint (json);
    138     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    139                 "Unexpected response code %u/%d\n",
    140                 (unsigned int) response_code,
    141                 (int) iar.hr.ec);
    142     break;
    143   }
    144   piah->cb (piah->cb_cls,
    145             &iar);
    146   if (MHD_HTTP_ACCEPTED == response_code)
    147     TALER_MERCHANT_mfa_challenge_response_free (
    148       &iar.details.accepted);
    149   TALER_MERCHANT_post_management_instances_auth_cancel (piah);
    150 }
    151 
    152 
    153 struct TALER_MERCHANT_PostManagementInstancesAuthHandle *
    154 TALER_MERCHANT_post_management_instances_auth_create (
    155   struct GNUNET_CURL_Context *ctx,
    156   const char *url,
    157   const char *instance_id,
    158   const char *auth_password)
    159 {
    160   struct TALER_MERCHANT_PostManagementInstancesAuthHandle *piah;
    161 
    162   piah = GNUNET_new (struct TALER_MERCHANT_PostManagementInstancesAuthHandle);
    163   piah->ctx = ctx;
    164   piah->base_url = GNUNET_strdup (url);
    165   if (NULL != instance_id)
    166     piah->instance_id = GNUNET_strdup (instance_id);
    167   if (NULL != auth_password)
    168     piah->auth_password = GNUNET_strdup (auth_password);
    169   return piah;
    170 }
    171 
    172 
    173 enum TALER_ErrorCode
    174 TALER_MERCHANT_post_management_instances_auth_start (
    175   struct TALER_MERCHANT_PostManagementInstancesAuthHandle *piah,
    176   TALER_MERCHANT_PostManagementInstancesAuthCallback cb,
    177   TALER_MERCHANT_POST_MANAGEMENT_INSTANCES_AUTH_RESULT_CLOSURE *cb_cls)
    178 {
    179   json_t *req_obj;
    180   CURL *eh;
    181 
    182   piah->cb = cb;
    183   piah->cb_cls = cb_cls;
    184   if (NULL != piah->instance_id)
    185   {
    186     char *path;
    187 
    188     GNUNET_asprintf (&path,
    189                      "management/instances/%s/auth",
    190                      piah->instance_id);
    191     piah->url = TALER_url_join (piah->base_url,
    192                                 path,
    193                                 NULL);
    194     GNUNET_free (path);
    195   }
    196   else
    197   {
    198     /* backend_url is already identifying the instance */
    199     piah->url = TALER_url_join (piah->base_url,
    200                                 "private/auth",
    201                                 NULL);
    202   }
    203   if (NULL == piah->url)
    204     return TALER_EC_GENERIC_CONFIGURATION_INVALID;
    205 
    206   if (NULL == piah->auth_password)
    207   {
    208     req_obj = GNUNET_JSON_PACK (
    209       GNUNET_JSON_pack_string ("method",
    210                                "external"));
    211   }
    212   else
    213   {
    214     req_obj = GNUNET_JSON_PACK (
    215       GNUNET_JSON_pack_string ("method",
    216                                "token"),
    217       GNUNET_JSON_pack_string ("password",
    218                                piah->auth_password));
    219   }
    220   eh = TALER_MERCHANT_curl_easy_get_ (piah->url);
    221   if ( (NULL == eh) ||
    222        (GNUNET_OK !=
    223         TALER_curl_easy_post (&piah->post_ctx,
    224                               eh,
    225                               req_obj)) )
    226   {
    227     GNUNET_break (0);
    228     json_decref (req_obj);
    229     if (NULL != eh)
    230       curl_easy_cleanup (eh);
    231     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    232   }
    233   json_decref (req_obj);
    234   GNUNET_assert (CURLE_OK ==
    235                  curl_easy_setopt (eh,
    236                                    CURLOPT_CUSTOMREQUEST,
    237                                    MHD_HTTP_METHOD_POST));
    238   piah->job = GNUNET_CURL_job_add2 (piah->ctx,
    239                                     eh,
    240                                     piah->post_ctx.headers,
    241                                     &
    242                                     handle_post_management_instances_auth_finished,
    243                                     piah);
    244   if (NULL == piah->job)
    245     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    246   return TALER_EC_NONE;
    247 }
    248 
    249 
    250 void
    251 TALER_MERCHANT_post_management_instances_auth_cancel (
    252   struct TALER_MERCHANT_PostManagementInstancesAuthHandle *piah)
    253 {
    254   if (NULL != piah->job)
    255   {
    256     GNUNET_CURL_job_cancel (piah->job);
    257     piah->job = NULL;
    258   }
    259   TALER_curl_easy_post_finished (&piah->post_ctx);
    260   GNUNET_free (piah->instance_id);
    261   GNUNET_free (piah->auth_password);
    262   GNUNET_free (piah->url);
    263   GNUNET_free (piah->base_url);
    264   GNUNET_free (piah);
    265 }
    266 
    267 
    268 /* end of merchant_api_post-management-instances-INSTANCE-auth-new.c */