Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2023, 2024 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 exchangedb_history.c
18 : * @brief helper function to build AML inputs from account histories
19 : * @author Christian Grothoff
20 : */
21 : #include "taler_exchangedb_plugin.h"
22 : #include "taler_exchangedb_lib.h"
23 : #include "taler_kyclogic_lib.h"
24 : #include "taler_json_lib.h"
25 : #include <gnunet/gnunet_common.h>
26 :
27 : /**
28 : * Function called to expand AML history for the account.
29 : *
30 : * @param cls a `json_t *` array to build
31 : * @param decision_time when was the decision taken
32 : * @param justification what was the given justification
33 : * @param decider_pub which key signed the decision
34 : * @param jproperties what are the new account properties
35 : * @param jnew_rules what are the new account rules
36 : * @param to_investigate should AML staff investigate
37 : * after the decision
38 : * @param is_active is this the active decision
39 : */
40 : static void
41 0 : add_aml_history_entry (
42 : void *cls,
43 : struct GNUNET_TIME_Timestamp decision_time,
44 : const char *justification,
45 : const struct TALER_AmlOfficerPublicKeyP *decider_pub,
46 : const json_t *jproperties,
47 : const json_t *jnew_rules,
48 : bool to_investigate,
49 : bool is_active)
50 : {
51 0 : json_t *aml_history = cls;
52 : json_t *e;
53 :
54 0 : e = GNUNET_JSON_PACK (
55 : GNUNET_JSON_pack_timestamp ("decision_time",
56 : decision_time),
57 : GNUNET_JSON_pack_string ("justification",
58 : justification),
59 : GNUNET_JSON_pack_data_auto ("decider_pub",
60 : decider_pub),
61 : GNUNET_JSON_pack_object_incref ("properties",
62 : (json_t *) jproperties),
63 : GNUNET_JSON_pack_object_incref ("new_rules",
64 : (json_t *) jnew_rules),
65 : GNUNET_JSON_pack_bool ("to_investigate",
66 : to_investigate),
67 : GNUNET_JSON_pack_bool ("is_active",
68 : is_active)
69 : );
70 0 : GNUNET_assert (0 ==
71 : json_array_append_new (aml_history,
72 : e));
73 0 : }
74 :
75 :
76 : json_t *
77 0 : TALER_EXCHANGEDB_aml_history_builder (void *cls)
78 : {
79 0 : struct TALER_EXCHANGEDB_HistoryBuilderContext *hbc = cls;
80 0 : const struct TALER_NormalizedPaytoHashP *acc = hbc->account;
81 : enum GNUNET_DB_QueryStatus qs;
82 : json_t *aml_history;
83 :
84 0 : aml_history = json_array ();
85 0 : GNUNET_assert (NULL != aml_history);
86 0 : qs = hbc->db_plugin->lookup_aml_history (
87 0 : hbc->db_plugin->cls,
88 : acc,
89 : &add_aml_history_entry,
90 : aml_history);
91 0 : switch (qs)
92 : {
93 0 : case GNUNET_DB_STATUS_HARD_ERROR:
94 : case GNUNET_DB_STATUS_SOFT_ERROR:
95 0 : GNUNET_break (0);
96 0 : json_decref (aml_history);
97 0 : return NULL;
98 0 : case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
99 : /* empty history is fine! */
100 0 : break;
101 0 : case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
102 0 : break;
103 : }
104 0 : return aml_history;
105 : }
106 :
107 :
108 : /**
109 : * Closure for #add_kyc_history_entry.
110 : */
111 : struct KycContext
112 : {
113 : /**
114 : * JSON array we are building.
115 : */
116 : json_t *kyc_history;
117 :
118 : /**
119 : * Key to use to decrypt KYC attributes.
120 : */
121 : const struct TALER_AttributeEncryptionKeyP *attribute_key;
122 : };
123 :
124 :
125 : /**
126 : * Function called to expand KYC history for the account.
127 : *
128 : * @param cls a `json_t *` array to build
129 : * @param provider_name name of the KYC provider
130 : * or NULL for none
131 : * @param finished did the KYC process finish
132 : * @param error_code error code from the KYC process
133 : * @param error_message error message from the KYC process,
134 : * or NULL for none
135 : * @param provider_user_id user ID at the provider
136 : * or NULL for none
137 : * @param provider_legitimization_id legitimization process ID at the provider
138 : * or NULL for none
139 : * @param collection_time when was the data collected
140 : * @param expiration_time when does the collected data expire
141 : * @param encrypted_attributes_len number of bytes in @a encrypted_attributes
142 : * @param encrypted_attributes encrypted KYC attributes
143 : */
144 : static void
145 0 : add_kyc_history_entry (
146 : void *cls,
147 : const char *provider_name,
148 : bool finished,
149 : enum TALER_ErrorCode error_code,
150 : const char *error_message,
151 : const char *provider_user_id,
152 : const char *provider_legitimization_id,
153 : struct GNUNET_TIME_Timestamp collection_time,
154 : struct GNUNET_TIME_Absolute expiration_time,
155 : size_t encrypted_attributes_len,
156 : const void *encrypted_attributes)
157 : {
158 0 : struct KycContext *kc = cls;
159 0 : json_t *kyc_history = kc->kyc_history;
160 : json_t *attributes;
161 : json_t *e;
162 :
163 0 : attributes = TALER_CRYPTO_kyc_attributes_decrypt (
164 : kc->attribute_key,
165 : encrypted_attributes,
166 : encrypted_attributes_len);
167 0 : e = GNUNET_JSON_PACK (
168 : GNUNET_JSON_pack_string (
169 : "provider_name",
170 : provider_name),
171 : GNUNET_JSON_pack_bool (
172 : "finished",
173 : finished),
174 : TALER_JSON_pack_ec (error_code),
175 : GNUNET_JSON_pack_allow_null (
176 : GNUNET_JSON_pack_string (
177 : "error_message",
178 : error_message)),
179 : GNUNET_JSON_pack_allow_null (
180 : GNUNET_JSON_pack_string (
181 : "provider_user_id",
182 : provider_user_id)),
183 : GNUNET_JSON_pack_allow_null (
184 : GNUNET_JSON_pack_string (
185 : "provider_legitimization_id",
186 : provider_legitimization_id)),
187 : GNUNET_JSON_pack_allow_null (
188 : GNUNET_JSON_pack_timestamp (
189 : "collection_time",
190 : collection_time)),
191 : GNUNET_JSON_pack_allow_null (
192 : GNUNET_JSON_pack_timestamp (
193 : "expiration_time",
194 : GNUNET_TIME_absolute_to_timestamp (
195 : expiration_time))),
196 : GNUNET_JSON_pack_allow_null (
197 : GNUNET_JSON_pack_object_steal (
198 : "attributes",
199 : attributes))
200 : );
201 :
202 0 : GNUNET_assert (0 ==
203 : json_array_append_new (kyc_history,
204 : e));
205 0 : }
206 :
207 :
208 : json_t *
209 0 : TALER_EXCHANGEDB_kyc_history_builder (void *cls)
210 : {
211 0 : struct TALER_EXCHANGEDB_HistoryBuilderContext *hbc = cls;
212 0 : const struct TALER_NormalizedPaytoHashP *acc = hbc->account;
213 : enum GNUNET_DB_QueryStatus qs;
214 0 : struct KycContext kc = {
215 0 : .kyc_history = json_array (),
216 0 : .attribute_key = hbc->attribute_key
217 : };
218 :
219 0 : GNUNET_assert (NULL != kc.kyc_history);
220 0 : qs = hbc->db_plugin->lookup_kyc_history (
221 0 : hbc->db_plugin->cls,
222 : acc,
223 : &add_kyc_history_entry,
224 : &kc);
225 0 : switch (qs)
226 : {
227 0 : case GNUNET_DB_STATUS_HARD_ERROR:
228 : case GNUNET_DB_STATUS_SOFT_ERROR:
229 0 : GNUNET_break (0);
230 0 : json_decref (kc.kyc_history);
231 0 : return NULL;
232 0 : case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
233 : /* empty history is fine! */
234 0 : break;
235 0 : case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
236 0 : break;
237 : }
238 0 : return kc.kyc_history;
239 : }
240 :
241 :
242 : json_t *
243 0 : TALER_EXCHANGEDB_current_rule_builder (void *cls)
244 : {
245 0 : struct TALER_EXCHANGEDB_HistoryBuilderContext *hbc = cls;
246 0 : const struct TALER_NormalizedPaytoHashP *acc = hbc->account;
247 : enum GNUNET_DB_QueryStatus qs;
248 : json_t *jlrs;
249 :
250 0 : qs = hbc->db_plugin->get_kyc_rules2 (
251 0 : hbc->db_plugin->cls,
252 : acc,
253 : &jlrs);
254 0 : switch (qs)
255 : {
256 0 : case GNUNET_DB_STATUS_HARD_ERROR:
257 : case GNUNET_DB_STATUS_SOFT_ERROR:
258 0 : GNUNET_break (0);
259 0 : return NULL;
260 0 : case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
261 0 : jlrs = TALER_KYCLOGIC_get_default_legi_rules (
262 0 : hbc->is_wallet);
263 0 : break;
264 0 : case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
265 0 : break;
266 : }
267 0 : return jlrs;
268 : }
269 :
270 :
271 : /**
272 : * Closure for decrypt_attributes().
273 : */
274 : struct DecryptContext
275 : {
276 : /**
277 : * Overall context.
278 : */
279 : const struct TALER_EXCHANGEDB_HistoryBuilderContext *hbc;
280 :
281 : /**
282 : * Where to return the attributes.
283 : */
284 : json_t *attr;
285 : };
286 :
287 :
288 : /**
289 : * Decrypt and return AML attribute information.
290 : *
291 : * @param cls a `struct DecryptContext *`
292 : * @param row_id current row in kyc_attributes table
293 : * @param collection_time when were the attributes collected
294 : * @param enc_attributes_size size of @a enc_attributes
295 : * @param enc_attributes the encrypted collected attributes
296 : */
297 : static void
298 10 : decrypt_attributes (
299 : void *cls,
300 : uint64_t row_id,
301 : struct GNUNET_TIME_Timestamp collection_time,
302 : size_t enc_attributes_size,
303 : const void *enc_attributes)
304 : {
305 10 : struct DecryptContext *decon = cls;
306 :
307 : (void) row_id;
308 : (void) collection_time;
309 : decon->attr
310 10 : = TALER_CRYPTO_kyc_attributes_decrypt (decon->hbc->attribute_key,
311 : enc_attributes,
312 : enc_attributes_size);
313 10 : GNUNET_break (NULL != decon->attr);
314 10 : }
315 :
316 :
317 : json_t *
318 10 : TALER_EXCHANGEDB_current_attributes_builder (void *cls)
319 : {
320 10 : struct TALER_EXCHANGEDB_HistoryBuilderContext *hbc = cls;
321 10 : const struct TALER_NormalizedPaytoHashP *acc = hbc->account;
322 : enum GNUNET_DB_QueryStatus qs;
323 10 : struct DecryptContext decon = {
324 : .hbc = hbc
325 : };
326 :
327 10 : qs = hbc->db_plugin->select_aml_attributes (
328 10 : hbc->db_plugin->cls,
329 : acc,
330 : INT64_MAX,
331 : -1, /* we only fetch the latest ones */
332 : &decrypt_attributes,
333 : &decon);
334 10 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
335 : "select_aml_attributes returned %d\n",
336 : (int) qs);
337 10 : switch (qs)
338 : {
339 0 : case GNUNET_DB_STATUS_HARD_ERROR:
340 : case GNUNET_DB_STATUS_SOFT_ERROR:
341 0 : GNUNET_break (0);
342 0 : return NULL;
343 0 : case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
344 0 : decon.attr = json_object ();
345 0 : GNUNET_break (NULL != decon.attr);
346 0 : break;
347 10 : case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
348 10 : GNUNET_break (NULL != decon.attr);
349 10 : break;
350 : }
351 10 : return decon.attr;
352 : }
|