taler-exchange-httpd_management_auditors.c (6581B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2020, 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 Affero 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 Affero General Public License for more details. 12 13 You should have received a copy of the GNU Affero General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file taler-exchange-httpd_management_auditors.c 18 * @brief Handle request to add auditor. 19 * @author Christian Grothoff 20 */ 21 #include "taler/platform.h" 22 #include <gnunet/gnunet_util_lib.h> 23 #include <gnunet/gnunet_json_lib.h> 24 #include <jansson.h> 25 #include <microhttpd.h> 26 #include <pthread.h> 27 #include "taler/taler_json_lib.h" 28 #include "taler/taler_mhd_lib.h" 29 #include "taler-exchange-httpd_management.h" 30 #include "taler-exchange-httpd_responses.h" 31 #include "taler-exchange-httpd_keys.h" 32 33 34 /** 35 * Closure for the #add_auditor transaction. 36 */ 37 struct AddAuditorContext 38 { 39 /** 40 * Master signature to store. 41 */ 42 struct TALER_MasterSignatureP master_sig; 43 44 /** 45 * Auditor public key this is about. 46 */ 47 struct TALER_AuditorPublicKeyP auditor_pub; 48 49 /** 50 * Auditor URL this is about. 51 */ 52 const char *auditor_url; 53 54 /** 55 * Human readable name of the auditor. 56 */ 57 const char *auditor_name; 58 59 /** 60 * Timestamp for checking against replay attacks. 61 */ 62 struct GNUNET_TIME_Timestamp validity_start; 63 64 }; 65 66 67 /** 68 * Function implementing database transaction to add an auditor. Runs the 69 * transaction logic; IF it returns a non-error code, the transaction logic 70 * MUST NOT queue a MHD response. IF it returns an hard error, the 71 * transaction logic MUST queue a MHD response and set @a mhd_ret. IF it 72 * returns the soft error code, the function MAY be called again to retry and 73 * MUST not queue a MHD response. 74 * 75 * @param cls closure with a `struct AddAuditorContext` 76 * @param connection MHD request which triggered the transaction 77 * @param[out] mhd_ret set to MHD response status for @a connection, 78 * if transaction failed (!) 79 * @return transaction status 80 */ 81 static enum GNUNET_DB_QueryStatus 82 add_auditor (void *cls, 83 struct MHD_Connection *connection, 84 MHD_RESULT *mhd_ret) 85 { 86 struct AddAuditorContext *aac = cls; 87 struct GNUNET_TIME_Timestamp last_date; 88 enum GNUNET_DB_QueryStatus qs; 89 90 qs = TEH_plugin->lookup_auditor_timestamp (TEH_plugin->cls, 91 &aac->auditor_pub, 92 &last_date); 93 if (qs < 0) 94 { 95 if (GNUNET_DB_STATUS_SOFT_ERROR == qs) 96 return qs; 97 GNUNET_break (0); 98 *mhd_ret = TALER_MHD_reply_with_error (connection, 99 MHD_HTTP_INTERNAL_SERVER_ERROR, 100 TALER_EC_GENERIC_DB_FETCH_FAILED, 101 "lookup auditor"); 102 return qs; 103 } 104 if ( (0 < qs) && 105 (GNUNET_TIME_timestamp_cmp (last_date, 106 >, 107 aac->validity_start) ) ) 108 { 109 *mhd_ret = TALER_MHD_reply_with_error ( 110 connection, 111 MHD_HTTP_CONFLICT, 112 TALER_EC_EXCHANGE_MANAGEMENT_AUDITOR_MORE_RECENT_PRESENT, 113 NULL); 114 return GNUNET_DB_STATUS_HARD_ERROR; 115 } 116 if (0 == qs) 117 qs = TEH_plugin->insert_auditor (TEH_plugin->cls, 118 &aac->auditor_pub, 119 aac->auditor_url, 120 aac->auditor_name, 121 aac->validity_start); 122 else 123 qs = TEH_plugin->update_auditor (TEH_plugin->cls, 124 &aac->auditor_pub, 125 aac->auditor_url, 126 aac->auditor_name, 127 aac->validity_start, 128 true); 129 if (qs < 0) 130 { 131 GNUNET_break (0); 132 if (GNUNET_DB_STATUS_SOFT_ERROR == qs) 133 return qs; 134 *mhd_ret = TALER_MHD_reply_with_error (connection, 135 MHD_HTTP_INTERNAL_SERVER_ERROR, 136 TALER_EC_GENERIC_DB_STORE_FAILED, 137 "add auditor"); 138 return qs; 139 } 140 TEH_keys_update_states (); 141 return qs; 142 } 143 144 145 MHD_RESULT 146 TEH_handler_management_auditors ( 147 struct MHD_Connection *connection, 148 const json_t *root) 149 { 150 struct AddAuditorContext aac; 151 struct GNUNET_JSON_Specification spec[] = { 152 GNUNET_JSON_spec_fixed_auto ("master_sig", 153 &aac.master_sig), 154 GNUNET_JSON_spec_fixed_auto ("auditor_pub", 155 &aac.auditor_pub), 156 TALER_JSON_spec_web_url ("auditor_url", 157 &aac.auditor_url), 158 GNUNET_JSON_spec_string ("auditor_name", 159 &aac.auditor_name), 160 GNUNET_JSON_spec_timestamp ("validity_start", 161 &aac.validity_start), 162 GNUNET_JSON_spec_end () 163 }; 164 MHD_RESULT res; 165 enum GNUNET_GenericReturnValue ret; 166 167 ret = TALER_MHD_parse_json_data (connection, 168 root, 169 spec); 170 if (GNUNET_SYSERR == ret) 171 return MHD_NO; /* hard failure */ 172 if (GNUNET_NO == ret) 173 return MHD_YES; /* failure */ 174 if (GNUNET_OK != 175 TALER_exchange_offline_auditor_add_verify ( 176 &aac.auditor_pub, 177 aac.auditor_url, 178 aac.validity_start, 179 &TEH_master_public_key, 180 &aac.master_sig)) 181 { 182 GNUNET_break_op (0); 183 return TALER_MHD_reply_with_error ( 184 connection, 185 MHD_HTTP_FORBIDDEN, 186 TALER_EC_EXCHANGE_MANAGEMENT_AUDITOR_ADD_SIGNATURE_INVALID, 187 NULL); 188 } 189 190 ret = TEH_DB_run_transaction (connection, 191 "add auditor", 192 TEH_MT_REQUEST_OTHER, 193 &res, 194 &add_auditor, 195 &aac); 196 if (GNUNET_SYSERR == ret) 197 return res; 198 return TALER_MHD_reply_static ( 199 connection, 200 MHD_HTTP_NO_CONTENT, 201 NULL, 202 NULL, 203 0); 204 } 205 206 207 /* end of taler-exchange-httpd_management_auditors.c */