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