taler-exchange-httpd_post-auditors-AUDITOR_PUB-H_DENOM_PUB.c (7289B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2020 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_post-auditors-AUDITOR_PUB-H_DENOM_PUB.c 18 * @brief Handle request to add auditor signature on a denomination. 19 * @author Christian Grothoff 20 */ 21 #include <gnunet/gnunet_util_lib.h> 22 #include <gnunet/gnunet_json_lib.h> 23 #include <jansson.h> 24 #include <microhttpd.h> 25 #include <pthread.h> 26 #include "taler/taler_json_lib.h" 27 #include "taler/taler_mhd_lib.h" 28 #include "taler-exchange-httpd_post-auditors-AUDITOR_PUB-H_DENOM_PUB.h" 29 #include "taler-exchange-httpd_responses.h" 30 #include "exchange-database/get_denomination_meta.h" 31 #include "exchange-database/insert_auditor_denom_sig.h" 32 #include "exchange-database/get_auditor_status.h" 33 34 35 /** 36 * Closure for the #add_auditor_denom_sig transaction. 37 */ 38 struct AddAuditorDenomContext 39 { 40 /** 41 * Auditor's signature affirming the AUDITORS XXX operation 42 * (includes timestamp). 43 */ 44 struct TALER_AuditorSignatureP auditor_sig; 45 46 /** 47 * Denomination this is about. 48 */ 49 const struct TALER_DenominationHashP *h_denom_pub; 50 51 /** 52 * Auditor this is about. 53 */ 54 const struct TALER_AuditorPublicKeyP *auditor_pub; 55 56 }; 57 58 59 /** 60 * Function implementing database transaction to add an auditors. Runs the 61 * transaction logic; IF it returns a non-error code, the transaction logic 62 * MUST NOT queue a MHD response. IF it returns an hard error, the 63 * transaction logic MUST queue a MHD response and set @a mhd_ret. IF it 64 * returns the soft error code, the function MAY be called again to retry and 65 * MUST not queue a MHD response. 66 * 67 * @param cls closure with a `struct AddAuditorDenomContext` 68 * @param connection MHD request which triggered the transaction 69 * @param[out] mhd_ret set to MHD response status for @a connection, 70 * if transaction failed (!) 71 * @return transaction status 72 */ 73 static enum GNUNET_DB_QueryStatus 74 add_auditor_denom_sig (void *cls, 75 struct MHD_Connection *connection, 76 enum MHD_Result *mhd_ret) 77 { 78 struct AddAuditorDenomContext *awc = cls; 79 struct TALER_EXCHANGEDB_DenominationKeyMetaData meta; 80 enum GNUNET_DB_QueryStatus qs; 81 char *auditor_url; 82 bool enabled; 83 84 qs = TALER_EXCHANGEDB_get_denomination_meta ( 85 TEH_pg, 86 awc->h_denom_pub, 87 &meta); 88 if (qs < 0) 89 { 90 if (GNUNET_DB_STATUS_SOFT_ERROR == qs) 91 return qs; 92 GNUNET_break (0); 93 *mhd_ret = TALER_MHD_reply_with_error (connection, 94 MHD_HTTP_INTERNAL_SERVER_ERROR, 95 TALER_EC_GENERIC_DB_FETCH_FAILED, 96 "lookup denomination key"); 97 return qs; 98 } 99 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) 100 { 101 *mhd_ret = TEH_RESPONSE_reply_invalid_denom_cipher_for_operation ( 102 connection, 103 awc->h_denom_pub); 104 return GNUNET_DB_STATUS_HARD_ERROR; 105 } 106 107 qs = TALER_EXCHANGEDB_get_auditor_status ( 108 TEH_pg, 109 awc->auditor_pub, 110 &auditor_url, 111 &enabled); 112 if (qs < 0) 113 { 114 if (GNUNET_DB_STATUS_SOFT_ERROR == qs) 115 return qs; 116 GNUNET_break (0); 117 *mhd_ret = TALER_MHD_reply_with_error (connection, 118 MHD_HTTP_INTERNAL_SERVER_ERROR, 119 TALER_EC_GENERIC_DB_FETCH_FAILED, 120 "lookup auditor"); 121 return qs; 122 } 123 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) 124 { 125 *mhd_ret = TALER_MHD_reply_with_error ( 126 connection, 127 MHD_HTTP_PRECONDITION_FAILED, 128 TALER_EC_EXCHANGE_AUDITORS_AUDITOR_UNKNOWN, 129 TALER_B2S (awc->auditor_pub)); 130 return GNUNET_DB_STATUS_HARD_ERROR; 131 } 132 if (! enabled) 133 { 134 GNUNET_free (auditor_url); 135 *mhd_ret = TALER_MHD_reply_with_error ( 136 connection, 137 MHD_HTTP_GONE, 138 TALER_EC_EXCHANGE_AUDITORS_AUDITOR_INACTIVE, 139 TALER_B2S (awc->auditor_pub)); 140 return GNUNET_DB_STATUS_HARD_ERROR; 141 } 142 TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++; 143 if (GNUNET_OK != 144 TALER_auditor_denom_validity_verify ( 145 auditor_url, 146 awc->h_denom_pub, 147 &TEH_master_public_key, 148 meta.start, 149 meta.expire_withdraw, 150 meta.expire_deposit, 151 meta.expire_legal, 152 &meta.value, 153 &meta.fees, 154 awc->auditor_pub, 155 &awc->auditor_sig)) 156 { 157 GNUNET_free (auditor_url); 158 /* signature invalid */ 159 GNUNET_break_op (0); 160 *mhd_ret = TALER_MHD_reply_with_error ( 161 connection, 162 MHD_HTTP_FORBIDDEN, 163 TALER_EC_EXCHANGE_AUDITORS_AUDITOR_SIGNATURE_INVALID, 164 NULL); 165 return GNUNET_DB_STATUS_HARD_ERROR; 166 } 167 GNUNET_free (auditor_url); 168 169 qs = TALER_EXCHANGEDB_insert_auditor_denom_sig (TEH_pg, 170 awc->h_denom_pub, 171 awc->auditor_pub, 172 &awc->auditor_sig); 173 if (qs < 0) 174 { 175 GNUNET_break (0); 176 if (GNUNET_DB_STATUS_SOFT_ERROR == qs) 177 return qs; 178 *mhd_ret = TALER_MHD_reply_with_error (connection, 179 MHD_HTTP_INTERNAL_SERVER_ERROR, 180 TALER_EC_GENERIC_DB_STORE_FAILED, 181 "add auditor signature"); 182 return qs; 183 } 184 return qs; 185 } 186 187 188 enum MHD_Result 189 TEH_handler_auditors ( 190 struct MHD_Connection *connection, 191 const struct TALER_AuditorPublicKeyP *auditor_pub, 192 const struct TALER_DenominationHashP *h_denom_pub, 193 const json_t *root) 194 { 195 struct AddAuditorDenomContext awc = { 196 .auditor_pub = auditor_pub, 197 .h_denom_pub = h_denom_pub 198 }; 199 struct GNUNET_JSON_Specification spec[] = { 200 GNUNET_JSON_spec_fixed_auto ("auditor_sig", 201 &awc.auditor_sig), 202 GNUNET_JSON_spec_end () 203 }; 204 enum MHD_Result res; 205 enum GNUNET_GenericReturnValue ret; 206 207 ret = TALER_MHD_parse_json_data (connection, 208 root, 209 spec); 210 if (GNUNET_SYSERR == ret) 211 return MHD_NO; /* hard failure */ 212 if (GNUNET_NO == ret) 213 return MHD_YES; /* failure */ 214 ret = TEH_DB_run_transaction (connection, 215 "add auditor denom sig", 216 TEH_MT_REQUEST_OTHER, 217 &res, 218 &add_auditor_denom_sig, 219 &awc); 220 if (GNUNET_SYSERR == ret) 221 return res; 222 return TALER_MHD_reply_static ( 223 connection, 224 MHD_HTTP_NO_CONTENT, 225 NULL, 226 NULL, 227 0); 228 } 229 230 231 /* end of taler-exchange-httpd_auditors.c */