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