taler-merchant-httpd_post-challenge-ID-confirm.c (3776B)
1 /* 2 This file is part of TALER 3 (C) 2025 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify 6 it under the terms of the GNU Affero General Public License as 7 published by the Free Software Foundation; either version 3, 8 or (at your option) any later version. 9 10 TALER is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public 16 License along with TALER; see the file COPYING. If not, 17 see <http://www.gnu.org/licenses/> 18 */ 19 20 /** 21 * @file taler-merchant-httpd_post-challenge-ID-confirm.c 22 * @brief endpoint to solve MFA challenge 23 * @author Christian Grothoff 24 */ 25 #include "platform.h" 26 #include "taler-merchant-httpd.h" 27 #include "taler-merchant-httpd_mfa.h" 28 #include "taler-merchant-httpd_post-challenge-ID-confirm.h" 29 30 31 MHD_RESULT 32 TMH_post_challenge_ID_confirm (const struct TMH_RequestHandler *rh, 33 struct MHD_Connection *connection, 34 struct TMH_HandlerContext *hc) 35 { 36 uint64_t challenge_serial; 37 struct TALER_MERCHANT_MFA_BodyHash h_body; 38 const char *tan; 39 struct GNUNET_JSON_Specification spec[] = { 40 GNUNET_JSON_spec_string ("tan", 41 &tan), 42 GNUNET_JSON_spec_end () 43 }; 44 enum GNUNET_DB_QueryStatus qs; 45 bool solved; 46 uint32_t retry_counter; 47 enum GNUNET_GenericReturnValue ret; 48 49 ret = TMH_mfa_parse_challenge_id (hc, 50 hc->infix, 51 &challenge_serial, 52 &h_body); 53 if (GNUNET_OK != ret) 54 return (GNUNET_SYSERR == ret) ? MHD_NO : MHD_YES; 55 { 56 enum GNUNET_GenericReturnValue res; 57 58 res = TALER_MHD_parse_json_data (hc->connection, 59 hc->request_body, 60 spec); 61 if (GNUNET_OK != res) 62 { 63 GNUNET_break_op (0); 64 return (GNUNET_NO == res) 65 ? MHD_YES 66 : MHD_NO; 67 } 68 } 69 qs = TMH_db->solve_mfa_challenge (TMH_db->cls, 70 challenge_serial, 71 &h_body, 72 tan, 73 &solved, 74 &retry_counter); 75 switch (qs) 76 { 77 case GNUNET_DB_STATUS_HARD_ERROR: 78 GNUNET_break (0); 79 return TALER_MHD_reply_with_error ( 80 hc->connection, 81 82 MHD_HTTP_INTERNAL_SERVER_ERROR, 83 TALER_EC_GENERIC_DB_COMMIT_FAILED, 84 "solve_mfa_challenge"); 85 case GNUNET_DB_STATUS_SOFT_ERROR: 86 GNUNET_break (0); 87 return TALER_MHD_reply_with_error ( 88 hc->connection, 89 MHD_HTTP_INTERNAL_SERVER_ERROR, 90 TALER_EC_GENERIC_DB_SOFT_FAILURE, 91 "solve_mfa_challenge"); 92 case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: 93 GNUNET_break_op (0); 94 return TALER_MHD_reply_with_error ( 95 hc->connection, 96 MHD_HTTP_NOT_FOUND, 97 TALER_EC_MERCHANT_TAN_CHALLENGE_UNKNOWN, 98 hc->infix); 99 case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: 100 break; 101 } 102 if (0 == retry_counter) 103 { 104 return TALER_MHD_reply_with_error ( 105 hc->connection, 106 MHD_HTTP_TOO_MANY_REQUESTS, 107 TALER_EC_MERCHANT_TAN_TOO_MANY_ATTEMPTS, 108 NULL); 109 } 110 if (! solved) 111 { 112 return TALER_MHD_REPLY_JSON_PACK ( 113 hc->connection, 114 MHD_HTTP_CONFLICT, 115 TALER_MHD_PACK_EC (TALER_EC_MERCHANT_TAN_CHALLENGE_FAILED), 116 GNUNET_JSON_pack_uint64 ("retry_counter", 117 retry_counter)); 118 } 119 return TALER_MHD_reply_static ( 120 hc->connection, 121 MHD_HTTP_NO_CONTENT, 122 NULL, 123 NULL, 124 0); 125 }