Line data Source code
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 src/backend/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 : #include "merchant-database/do_solve_mfa_challenge.h"
30 :
31 :
32 : enum MHD_Result
33 11 : TMH_post_challenge_ID_confirm (const struct TMH_RequestHandler *rh,
34 : struct MHD_Connection *connection,
35 : struct TMH_HandlerContext *hc)
36 : {
37 : uint64_t challenge_serial;
38 : struct TALER_MERCHANT_MFA_BodyHash h_body;
39 : const char *tan;
40 : struct GNUNET_JSON_Specification spec[] = {
41 11 : GNUNET_JSON_spec_string ("tan",
42 : &tan),
43 11 : GNUNET_JSON_spec_end ()
44 : };
45 : enum GNUNET_DB_QueryStatus qs;
46 : bool solved;
47 : uint32_t retry_counter;
48 : enum GNUNET_GenericReturnValue ret;
49 11 : char *xtan = NULL;
50 :
51 11 : ret = TMH_mfa_parse_challenge_id (hc,
52 11 : hc->infix,
53 : &challenge_serial,
54 : &h_body);
55 11 : if (GNUNET_OK != ret)
56 0 : return (GNUNET_SYSERR == ret) ? MHD_NO : MHD_YES;
57 : {
58 : enum GNUNET_GenericReturnValue res;
59 :
60 11 : res = TALER_MHD_parse_json_data (hc->connection,
61 11 : hc->request_body,
62 : spec);
63 11 : if (GNUNET_OK != res)
64 : {
65 0 : GNUNET_break_op (0);
66 : return (GNUNET_NO == res)
67 : ? MHD_YES
68 0 : : MHD_NO;
69 : }
70 : }
71 : {
72 : /* User may have submitted the entire challenge as a single
73 : 8-digit number instead of (4-digits)-"-"-(4-digits) which
74 : is the new format generated by taler-merchant-httpd_mfa.c.
75 : Thus, in this case, we convert the format to the string
76 : with the dash and use that. */
77 : unsigned long long challenge_num;
78 : char dummy;
79 :
80 11 : if (1 ==
81 11 : sscanf (tan,
82 : "%llu%c",
83 : &challenge_num,
84 : &dummy))
85 : {
86 : /* inject hyphen */
87 0 : GNUNET_asprintf (&xtan,
88 : "%04llu-%04llu",
89 : challenge_num / 10000,
90 : challenge_num % 10000);
91 :
92 : }
93 : }
94 11 : qs = TALER_MERCHANTDB_do_solve_mfa_challenge (TMH_db,
95 : challenge_serial,
96 : &h_body,
97 11 : (NULL == xtan)
98 : ? tan
99 : : xtan,
100 : &solved,
101 : &retry_counter);
102 11 : GNUNET_free (xtan);
103 11 : switch (qs)
104 : {
105 0 : case GNUNET_DB_STATUS_HARD_ERROR:
106 0 : GNUNET_break (0);
107 0 : return TALER_MHD_reply_with_error (
108 : hc->connection,
109 :
110 : MHD_HTTP_INTERNAL_SERVER_ERROR,
111 : TALER_EC_GENERIC_DB_COMMIT_FAILED,
112 : "do_solve_mfa_challenge");
113 0 : case GNUNET_DB_STATUS_SOFT_ERROR:
114 0 : GNUNET_break (0);
115 0 : return TALER_MHD_reply_with_error (
116 : hc->connection,
117 : MHD_HTTP_INTERNAL_SERVER_ERROR,
118 : TALER_EC_GENERIC_DB_SOFT_FAILURE,
119 : "do_solve_mfa_challenge");
120 0 : case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
121 0 : GNUNET_break_op (0);
122 0 : return TALER_MHD_reply_with_error (
123 : hc->connection,
124 : MHD_HTTP_NOT_FOUND,
125 : TALER_EC_MERCHANT_TAN_CHALLENGE_UNKNOWN,
126 0 : hc->infix);
127 11 : case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
128 11 : break;
129 : }
130 11 : if (0 == retry_counter)
131 : {
132 0 : return TALER_MHD_reply_with_error (
133 : hc->connection,
134 : MHD_HTTP_TOO_MANY_REQUESTS,
135 : TALER_EC_MERCHANT_TAN_TOO_MANY_ATTEMPTS,
136 : NULL);
137 : }
138 11 : if (! solved)
139 : {
140 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
141 : "Generating JSON response with code %d\n",
142 : (int) TALER_EC_MERCHANT_TAN_CHALLENGE_FAILED);
143 0 : return TALER_MHD_REPLY_JSON_PACK (
144 : hc->connection,
145 : MHD_HTTP_CONFLICT,
146 : TALER_MHD_PACK_EC (TALER_EC_MERCHANT_TAN_CHALLENGE_FAILED),
147 : GNUNET_JSON_pack_uint64 ("retry_counter",
148 : retry_counter));
149 : }
150 11 : return TALER_MHD_reply_static (
151 : hc->connection,
152 : MHD_HTTP_NO_CONTENT,
153 : NULL,
154 : NULL,
155 : 0);
156 : }
|