Line data Source code
1 : /*
2 : This file is part of TALER
3 : (C) 2014-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 General Public License for more details.
12 :
13 : You should have received a copy of the GNU General Public License along with
14 : TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15 : */
16 : /**
17 : * @file taler-merchant-httpd_auditors.c
18 : * @brief logic this HTTPD keeps for each exchange we interact with
19 : * @author Marcello Stanisci
20 : * @author Christian Grothoff
21 : */
22 : #include "platform.h"
23 : #include <taler/taler_json_lib.h>
24 : #include "taler-merchant-httpd_auditors.h"
25 :
26 : /**
27 : * Our representation of an auditor.
28 : */
29 : struct Auditor
30 : {
31 : /**
32 : * Auditor's legal name.
33 : */
34 : char *name;
35 :
36 : /**
37 : * Auditor's URL.
38 : */
39 : char *url;
40 :
41 : /**
42 : * Public key of the auditor.
43 : */
44 : struct TALER_AuditorPublicKeyP public_key;
45 :
46 : };
47 :
48 :
49 : /**
50 : * Array of the auditors this merchant is willing to accept.
51 : */
52 : static struct Auditor *auditors;
53 :
54 : /**
55 : * The length of the #auditors array.
56 : */
57 : static unsigned int nauditors;
58 :
59 : /**
60 : * JSON representation of the auditors accepted by this exchange.
61 : */
62 : json_t *j_auditors;
63 :
64 :
65 : enum GNUNET_GenericReturnValue
66 0 : TMH_AUDITORS_check_dk (struct TALER_EXCHANGE_Handle *mh,
67 : const struct TALER_EXCHANGE_DenomPublicKey *dk,
68 : bool exchange_trusted,
69 : unsigned int *hc,
70 : enum TALER_ErrorCode *ec)
71 : {
72 : const struct TALER_EXCHANGE_Keys *keys;
73 : const struct TALER_EXCHANGE_AuditorInformation *ai;
74 :
75 0 : if (GNUNET_TIME_absolute_is_past (dk->expire_deposit.abs_time))
76 : {
77 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
78 : "Denomination key offered by client has expired for deposits\n");
79 0 : *hc = MHD_HTTP_GONE;
80 0 : *ec = TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_DEPOSIT_EXPIRED;
81 0 : return GNUNET_SYSERR; /* expired */
82 : }
83 0 : if (exchange_trusted)
84 : {
85 0 : *ec = TALER_EC_NONE;
86 0 : *hc = MHD_HTTP_OK;
87 0 : return GNUNET_OK;
88 : }
89 0 : keys = TALER_EXCHANGE_get_keys (mh);
90 0 : if (NULL == keys)
91 : {
92 : /* this should never happen, keys should have been successfully
93 : obtained before we even got into this function */
94 0 : GNUNET_break (0);
95 0 : *ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
96 0 : *hc = MHD_HTTP_INTERNAL_SERVER_ERROR;
97 0 : return GNUNET_SYSERR;
98 : }
99 0 : for (unsigned int i = 0; i<keys->num_auditors; i++)
100 : {
101 0 : ai = &keys->auditors[i];
102 0 : for (unsigned int j = 0; j<nauditors; j++)
103 : {
104 0 : if (0 == GNUNET_memcmp (&ai->auditor_pub,
105 : &auditors[j].public_key))
106 : {
107 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
108 : "Found supported auditor `%s' (%s)\n",
109 : auditors[j].name,
110 : TALER_B2S (&auditors[j].public_key));
111 : }
112 0 : for (unsigned int k = 0; k<ai->num_denom_keys; k++)
113 0 : if (&keys->denom_keys[k] == dk)
114 : {
115 0 : *ec = TALER_EC_NONE;
116 0 : *hc = MHD_HTTP_OK;
117 0 : return GNUNET_OK;
118 : }
119 : }
120 : }
121 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
122 : "Denomination key %s offered by client not audited by any accepted auditor\n",
123 : GNUNET_h2s (&dk->h_key.hash));
124 0 : *hc = MHD_HTTP_BAD_REQUEST;
125 0 : *ec = TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_KEY_AUDITOR_FAILURE;
126 0 : return GNUNET_NO;
127 : }
128 :
129 :
130 : /**
131 : * Function called on each configuration section. Finds sections
132 : * about auditors and parses the entries.
133 : *
134 : * @param cls closure, with a `const struct GNUNET_CONFIGURATION_Handle *`
135 : * @param section name of the section
136 : */
137 : static void
138 0 : parse_auditors (void *cls,
139 : const char *section)
140 : {
141 0 : const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
142 : char *pks;
143 : struct Auditor auditor;
144 : char *currency;
145 :
146 0 : if (0 != strncasecmp (section,
147 : "merchant-auditor-",
148 : strlen ("merchant-auditor-")))
149 0 : return;
150 0 : if (GNUNET_OK !=
151 0 : GNUNET_CONFIGURATION_get_value_string (cfg,
152 : section,
153 : "CURRENCY",
154 : ¤cy))
155 : {
156 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
157 : section,
158 : "CURRENCY");
159 0 : return;
160 : }
161 0 : if (0 != strcasecmp (currency,
162 : TMH_currency))
163 : {
164 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
165 : "Auditor given in section `%s' is for another currency. Skipping.\n",
166 : section);
167 0 : GNUNET_free (currency);
168 0 : return;
169 : }
170 0 : GNUNET_free (currency);
171 0 : auditor.name = GNUNET_strdup (§ion[strlen ("merchant-auditor-")]);
172 0 : if (GNUNET_OK !=
173 0 : GNUNET_CONFIGURATION_get_value_string (cfg,
174 : section,
175 : "AUDITOR_BASE_URL",
176 : &auditor.url))
177 : {
178 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
179 : section,
180 : "URL");
181 0 : GNUNET_free (auditor.name);
182 0 : return;
183 : }
184 0 : if (GNUNET_OK !=
185 0 : GNUNET_CONFIGURATION_get_value_string (cfg,
186 : section,
187 : "AUDITOR_KEY",
188 : &pks))
189 : {
190 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
191 : section,
192 : "AUDITOR_KEY");
193 0 : GNUNET_free (auditor.name);
194 0 : GNUNET_free (auditor.url);
195 0 : return;
196 : }
197 0 : if (GNUNET_OK !=
198 0 : GNUNET_CRYPTO_eddsa_public_key_from_string (pks,
199 : strlen (pks),
200 : &auditor.public_key.eddsa_pub))
201 : {
202 0 : GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
203 : section,
204 : "AUDITOR_KEY",
205 : "need a valid EdDSA public key");
206 0 : GNUNET_free (auditor.name);
207 0 : GNUNET_free (auditor.url);
208 0 : GNUNET_free (pks);
209 0 : return;
210 : }
211 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
212 : "Loaded key data of auditor `%s' (%s)\n",
213 : auditor.name,
214 : TALER_B2S (&auditor.public_key));
215 0 : GNUNET_free (pks);
216 0 : GNUNET_array_append (auditors,
217 : nauditors,
218 : auditor);
219 : }
220 :
221 :
222 : int
223 0 : TMH_AUDITORS_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
224 : {
225 0 : GNUNET_CONFIGURATION_iterate_sections (cfg,
226 : &parse_auditors,
227 : (void *) cfg);
228 :
229 : /* Generate preferred exchange(s) array. */
230 0 : j_auditors = json_array ();
231 0 : for (unsigned int cnt = 0; cnt < nauditors; cnt++)
232 0 : GNUNET_assert (0 ==
233 : json_array_append_new (
234 : j_auditors,
235 : GNUNET_JSON_PACK (
236 : GNUNET_JSON_pack_string ("name",
237 : auditors[cnt].name),
238 : GNUNET_JSON_pack_data_auto ("auditor_pub",
239 : &auditors[cnt].public_key),
240 : GNUNET_JSON_pack_string ("url",
241 : auditors[cnt].url))));
242 0 : return nauditors;
243 : }
244 :
245 :
246 : /**
247 : * Release auditor information state.
248 : */
249 : void
250 0 : TMH_AUDITORS_done ()
251 : {
252 0 : json_decref (j_auditors);
253 0 : j_auditors = NULL;
254 0 : for (unsigned int i = 0; i<nauditors; i++)
255 : {
256 0 : GNUNET_free (auditors[i].name);
257 0 : GNUNET_free (auditors[i].url);
258 : }
259 0 : GNUNET_free (auditors);
260 0 : auditors = NULL;
261 0 : nauditors = 0;
262 0 : }
263 :
264 :
265 : /* end of taler-merchant-httpd_auditors.c */
|