Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2016-2020 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 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 Public License for more details.
12 :
13 : You should have received a copy of the GNU Affero Public License along with
14 : TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15 : */
16 : /**
17 : * @file auditor/report-lib.c
18 : * @brief helper library to facilitate generation of audit reports
19 : * @author Christian Grothoff
20 : */
21 : #include "platform.h"
22 : #include "report-lib.h"
23 :
24 : /**
25 : * Handle to access the exchange's database.
26 : */
27 : struct TALER_EXCHANGEDB_Plugin *TALER_ARL_edb;
28 :
29 : /**
30 : * Which currency are we doing the audit for?
31 : */
32 : char *TALER_ARL_currency;
33 :
34 : /**
35 : * How many fractional digits does the currency use?
36 : */
37 : struct TALER_Amount TALER_ARL_currency_round_unit;
38 :
39 : /**
40 : * Our configuration.
41 : */
42 : const struct GNUNET_CONFIGURATION_Handle *TALER_ARL_cfg;
43 :
44 : /**
45 : * Handle to access the auditor's database.
46 : */
47 : struct TALER_AUDITORDB_Plugin *TALER_ARL_adb;
48 :
49 : /**
50 : * Master public key of the exchange to audit.
51 : */
52 : struct TALER_MasterPublicKeyP TALER_ARL_master_pub;
53 :
54 : /**
55 : * Public key of the auditor.
56 : */
57 : struct TALER_AuditorPublicKeyP TALER_ARL_auditor_pub;
58 :
59 : /**
60 : * REST API endpoint of the auditor.
61 : */
62 : char *TALER_ARL_auditor_url;
63 :
64 : /**
65 : * REST API endpoint of the exchange.
66 : */
67 : char *TALER_ARL_exchange_url;
68 :
69 : /**
70 : * At what time did the auditor process start?
71 : */
72 : struct GNUNET_TIME_Absolute start_time;
73 :
74 : /**
75 : * Results about denominations, cached per-transaction, maps denomination pub hashes
76 : * to `const struct TALER_EXCHANGEDB_DenominationKeyInformation`.
77 : */
78 : static struct GNUNET_CONTAINER_MultiHashMap *denominations;
79 :
80 : /**
81 : * Results about denominations, cached per-transaction, maps row/serial ID's
82 : * to `const struct TALER_EXCHANGEDB_DenominationKeyInformation`.
83 : */
84 : static struct GNUNET_CONTAINER_MultiUuidmap *denominations_by_serial;
85 :
86 : /**
87 : * Helper to convert a serial/row id to a uuid for the lookup
88 : * in a uuid hash table.
89 : *
90 : * @param serial serial id of entry
91 : * @param[out] uuid uuid to write
92 : */
93 : static void
94 37556 : serial_to_uuid (
95 : uint64_t serial,
96 : struct GNUNET_Uuid *uuid)
97 : {
98 37556 : uuid->value[0] = serial;
99 37556 : uuid->value[1] = serial >> 32;
100 37556 : uuid->value[2] = 0;
101 37556 : uuid->value[3] = 0;
102 37556 : }
103 :
104 :
105 : /**
106 : * Function called with the results of iterate_denomination_info(),
107 : * or directly (!). Used to check and add the respective denomination
108 : * to our hash table.
109 : *
110 : * @param cls closure, NULL
111 : * @param denom_serial table row of the denomaination
112 : * @param denom_pub public key, sometimes NULL (!)
113 : * @param issue issuing information with value, fees and other info about the denomination.
114 : */
115 : static void
116 34344 : add_denomination (
117 : void *cls,
118 : uint64_t denom_serial,
119 : const struct TALER_DenominationPublicKey *denom_pub,
120 : const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue)
121 : {
122 : (void) cls;
123 : (void) denom_pub;
124 34344 : if (NULL !=
125 34344 : GNUNET_CONTAINER_multihashmap_get (denominations,
126 : &issue->denom_hash.hash))
127 0 : return; /* value already known */
128 : #if GNUNET_EXTRA_LOGGING >= 1
129 : {
130 34344 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
131 : "Tracking denomination `%s' (%s)\n",
132 : GNUNET_h2s (&issue->denom_hash.hash),
133 : TALER_amount2s (&issue->value));
134 34344 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
135 : "Withdraw fee is %s\n",
136 : TALER_amount2s (&issue->fees.withdraw));
137 34344 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
138 : "Start time is %s\n",
139 : GNUNET_TIME_timestamp2s (issue->start));
140 34344 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
141 : "Expire deposit time is %s\n",
142 : GNUNET_TIME_timestamp2s (issue->expire_deposit));
143 : }
144 : #endif
145 : {
146 : struct TALER_EXCHANGEDB_DenominationKeyInformation *i;
147 : struct GNUNET_Uuid uuid;
148 :
149 34344 : i = GNUNET_new (struct TALER_EXCHANGEDB_DenominationKeyInformation);
150 34344 : *i = *issue;
151 34344 : GNUNET_assert (GNUNET_OK ==
152 : GNUNET_CONTAINER_multihashmap_put (denominations,
153 : &issue->denom_hash.hash,
154 : i,
155 : GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
156 34344 : serial_to_uuid (denom_serial, &uuid);
157 34344 : GNUNET_assert (GNUNET_OK ==
158 : GNUNET_CONTAINER_multiuuidmap_put (denominations_by_serial,
159 : &uuid,
160 : i,
161 : GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
162 : }
163 : }
164 :
165 :
166 : enum GNUNET_DB_QueryStatus
167 309 : TALER_ARL_get_denomination_info_by_hash (
168 : const struct TALER_DenominationHashP *dh,
169 : const struct TALER_EXCHANGEDB_DenominationKeyInformation **issuep)
170 : {
171 : enum GNUNET_DB_QueryStatus qs;
172 :
173 309 : if (NULL == denominations)
174 : {
175 15 : denominations = GNUNET_CONTAINER_multihashmap_create (256,
176 : GNUNET_NO);
177 15 : if (NULL == denominations_by_serial)
178 15 : denominations_by_serial = GNUNET_CONTAINER_multiuuidmap_create (256,
179 : GNUNET_NO)
180 : ;
181 :
182 15 : qs = TALER_ARL_edb->iterate_denomination_info (TALER_ARL_edb->cls,
183 : &add_denomination,
184 : NULL);
185 15 : if (0 > qs)
186 : {
187 0 : GNUNET_break (0);
188 0 : *issuep = NULL;
189 0 : return qs;
190 : }
191 : }
192 : {
193 : const struct TALER_EXCHANGEDB_DenominationKeyInformation *i;
194 :
195 309 : i = GNUNET_CONTAINER_multihashmap_get (denominations,
196 : &dh->hash);
197 309 : if (NULL != i)
198 : {
199 : /* cache hit */
200 309 : *issuep = i;
201 309 : return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
202 : }
203 : }
204 : /* maybe database changed since we last iterated, give it one more shot */
205 : {
206 : struct TALER_EXCHANGEDB_DenominationKeyInformation issue;
207 : uint64_t denom_serial;
208 :
209 0 : qs = TALER_ARL_edb->get_denomination_info (TALER_ARL_edb->cls,
210 : dh,
211 : &denom_serial,
212 : &issue);
213 0 : if (qs <= 0)
214 : {
215 0 : GNUNET_break (qs >= 0);
216 0 : if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
217 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
218 : "Denomination %s not found\n",
219 : TALER_B2S (dh));
220 0 : return qs;
221 : }
222 :
223 0 : add_denomination (NULL,
224 : denom_serial,
225 : NULL,
226 : &issue);
227 : }
228 : {
229 : const struct TALER_EXCHANGEDB_DenominationKeyInformation *i;
230 :
231 0 : i = GNUNET_CONTAINER_multihashmap_get (denominations,
232 : &dh->hash);
233 0 : if (NULL != i)
234 : {
235 : /* cache hit */
236 0 : *issuep = i;
237 0 : return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
238 : }
239 : }
240 : /* We found more keys, but not the denomination we are looking for :-( */
241 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
242 : "Denomination %s not found\n",
243 : TALER_B2S (dh));
244 0 : return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
245 : }
246 :
247 :
248 : enum GNUNET_DB_QueryStatus
249 3212 : TALER_ARL_get_denomination_info_by_serial (
250 : uint64_t denom_serial,
251 : const struct TALER_EXCHANGEDB_DenominationKeyInformation **issuep)
252 : {
253 : enum GNUNET_DB_QueryStatus qs;
254 : struct GNUNET_Uuid uuid;
255 :
256 3212 : serial_to_uuid (denom_serial,
257 : &uuid);
258 3212 : if (NULL == denominations_by_serial)
259 : {
260 66 : denominations_by_serial = GNUNET_CONTAINER_multiuuidmap_create (256,
261 : GNUNET_NO);
262 66 : if (NULL == denominations)
263 66 : denominations = GNUNET_CONTAINER_multihashmap_create (256,
264 : GNUNET_NO);
265 :
266 66 : qs = TALER_ARL_edb->iterate_denomination_info (TALER_ARL_edb->cls,
267 : &add_denomination,
268 : NULL);
269 66 : if (0 > qs)
270 : {
271 0 : GNUNET_break (0);
272 0 : *issuep = NULL;
273 0 : return qs;
274 : }
275 : }
276 : {
277 : const struct TALER_EXCHANGEDB_DenominationKeyInformation *i;
278 :
279 3212 : i = GNUNET_CONTAINER_multiuuidmap_get (denominations_by_serial,
280 : &uuid);
281 3212 : if (NULL != i)
282 : {
283 : /* cache hit */
284 3212 : *issuep = i;
285 3212 : return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
286 : }
287 : }
288 : /* maybe database changed since we last iterated, give it one more shot */
289 : {
290 : struct TALER_EXCHANGEDB_DenominationKeyInformation issue;
291 :
292 0 : qs = TALER_ARL_edb->get_denomination_by_serial (TALER_ARL_edb->cls,
293 : denom_serial,
294 : &issue);
295 0 : if (qs <= 0)
296 : {
297 0 : GNUNET_break (qs >= 0);
298 0 : if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
299 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
300 : "Denomination with serial %lu not found\n",
301 : denom_serial);
302 0 : return qs;
303 : }
304 :
305 0 : add_denomination (NULL,
306 : denom_serial,
307 : NULL,
308 : &issue);
309 : }
310 :
311 : {
312 : const struct TALER_EXCHANGEDB_DenominationKeyInformation *i;
313 :
314 0 : i = GNUNET_CONTAINER_multiuuidmap_get (denominations_by_serial,
315 : &uuid);
316 0 : if (NULL != i)
317 : {
318 : /* cache hit */
319 0 : *issuep = i;
320 0 : return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
321 : }
322 : }
323 : /* We found more keys, but not the denomination we are looking for :-( */
324 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
325 : "Denomination with serial %lu not found\n",
326 : denom_serial);
327 0 : return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
328 : }
329 :
330 :
331 : enum GNUNET_DB_QueryStatus
332 267 : TALER_ARL_get_denomination_info (
333 : const struct TALER_DenominationPublicKey *denom_pub,
334 : const struct TALER_EXCHANGEDB_DenominationKeyInformation **issue,
335 : struct TALER_DenominationHashP *dh)
336 : {
337 : struct TALER_DenominationHashP hc;
338 :
339 267 : if (NULL == dh)
340 131 : dh = &hc;
341 267 : TALER_denom_pub_hash (denom_pub,
342 : dh);
343 267 : return TALER_ARL_get_denomination_info_by_hash (dh,
344 : issue);
345 : }
346 :
347 :
348 : /**
349 : * Perform the given @a analysis within a transaction scope.
350 : * Commit on success.
351 : *
352 : * @param analysis analysis to run
353 : * @param analysis_cls closure for @a analysis
354 : * @return #GNUNET_OK if @a analysis successfully committed,
355 : * #GNUNET_NO if we had an error on commit (retry may help)
356 : * #GNUNET_SYSERR on hard errors
357 : */
358 : static enum GNUNET_GenericReturnValue
359 370 : transact (TALER_ARL_Analysis analysis,
360 : void *analysis_cls)
361 : {
362 : int ret;
363 : enum GNUNET_DB_QueryStatus qs;
364 :
365 370 : ret = TALER_ARL_adb->start (TALER_ARL_adb->cls);
366 370 : if (GNUNET_OK != ret)
367 : {
368 0 : GNUNET_break (0);
369 0 : return GNUNET_SYSERR;
370 : }
371 370 : if (GNUNET_OK !=
372 370 : TALER_ARL_edb->preflight (TALER_ARL_edb->cls))
373 : {
374 0 : GNUNET_break (0);
375 0 : return GNUNET_SYSERR;
376 : }
377 370 : ret = TALER_ARL_edb->start (TALER_ARL_edb->cls,
378 : "auditor");
379 370 : if (GNUNET_OK != ret)
380 : {
381 0 : GNUNET_break (0);
382 0 : TALER_ARL_edb->rollback (TALER_ARL_edb->cls);
383 0 : return GNUNET_SYSERR;
384 : }
385 370 : qs = analysis (analysis_cls);
386 370 : if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
387 : {
388 304 : qs = TALER_ARL_edb->commit (TALER_ARL_edb->cls);
389 304 : if (0 > qs)
390 : {
391 0 : GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
392 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
393 : "Exchange DB commit failed, rolling back transaction\n");
394 0 : TALER_ARL_adb->rollback (TALER_ARL_adb->cls);
395 : }
396 : else
397 : {
398 304 : qs = TALER_ARL_adb->commit (TALER_ARL_adb->cls);
399 304 : if (0 > qs)
400 : {
401 0 : GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
402 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
403 : "Auditor DB commit failed!\n");
404 : }
405 : }
406 : }
407 : else
408 : {
409 66 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
410 : "Processing failed; rolling back transaction\n");
411 66 : TALER_ARL_adb->rollback (TALER_ARL_adb->cls);
412 66 : TALER_ARL_edb->rollback (TALER_ARL_edb->cls);
413 : }
414 370 : switch (qs)
415 : {
416 0 : case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
417 0 : return GNUNET_OK;
418 364 : case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
419 364 : return GNUNET_OK;
420 6 : case GNUNET_DB_STATUS_SOFT_ERROR:
421 6 : return GNUNET_NO;
422 0 : case GNUNET_DB_STATUS_HARD_ERROR:
423 0 : return GNUNET_SYSERR;
424 : }
425 0 : return GNUNET_OK;
426 : }
427 :
428 :
429 : enum GNUNET_GenericReturnValue
430 370 : TALER_ARL_setup_sessions_and_run (TALER_ARL_Analysis ana,
431 : void *ana_cls)
432 : {
433 : enum GNUNET_DB_QueryStatus qs;
434 :
435 370 : if (GNUNET_SYSERR ==
436 370 : TALER_ARL_edb->preflight (TALER_ARL_edb->cls))
437 : {
438 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
439 : "Failed to initialize exchange connection.\n");
440 0 : return GNUNET_SYSERR;
441 : }
442 370 : if (GNUNET_SYSERR ==
443 370 : TALER_ARL_adb->preflight (TALER_ARL_adb->cls))
444 : {
445 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
446 : "Failed to initialize auditor session.\n");
447 0 : return GNUNET_SYSERR;
448 : }
449 :
450 370 : for (unsigned int retries=0; retries<3; retries++)
451 : {
452 370 : qs = transact (ana,
453 : ana_cls);
454 370 : if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
455 370 : break;
456 : }
457 370 : if (qs < 0)
458 0 : return GNUNET_SYSERR;
459 370 : return GNUNET_OK;
460 : }
461 :
462 :
463 : void
464 18037 : TALER_ARL_amount_add_ (struct TALER_Amount *sum,
465 : const struct TALER_Amount *a1,
466 : const struct TALER_Amount *a2,
467 : const char *filename,
468 : const char *functionname,
469 : unsigned int line)
470 : {
471 : enum TALER_AmountArithmeticResult aar;
472 : const char *msg;
473 : char *a2s;
474 :
475 18037 : aar = TALER_amount_add (sum,
476 : a1,
477 : a2);
478 18037 : if (aar >= 0)
479 18037 : return;
480 0 : switch (aar)
481 : {
482 0 : case TALER_AAR_INVALID_RESULT_OVERFLOW:
483 0 : msg =
484 : "arithmetic overflow in amount addition (likely the database is corrupt, see manual)";
485 0 : break;
486 0 : case TALER_AAR_INVALID_NORMALIZATION_FAILED:
487 0 : msg =
488 : "normalization failed in amount addition (likely the database is corrupt, see manual)";
489 0 : break;
490 0 : case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE:
491 0 : msg =
492 : "incompatible currencies in amount addition (likely bad configuration and auditor code missing a sanity check, see manual)";
493 0 : break;
494 0 : default:
495 0 : GNUNET_assert (0); /* should be impossible */
496 : }
497 0 : a2s = TALER_amount_to_string (a2);
498 0 : fprintf (stderr,
499 : "Aborting audit due to fatal error in function %s at %s:%d trying to add %s to %s: %s\n",
500 : functionname,
501 : filename,
502 : line,
503 : TALER_amount2s (a1),
504 : a2s,
505 : msg);
506 0 : GNUNET_free (a2s);
507 0 : exit (42);
508 : }
509 :
510 :
511 : void
512 351 : TALER_ARL_amount_subtract_ (struct TALER_Amount *diff,
513 : const struct TALER_Amount *a1,
514 : const struct TALER_Amount *a2,
515 : const char *filename,
516 : const char *functionname,
517 : unsigned int line)
518 : {
519 : enum TALER_AmountArithmeticResult aar;
520 : const char *msg;
521 : char *a2s;
522 :
523 351 : aar = TALER_amount_subtract (diff,
524 : a1,
525 : a2);
526 351 : if (aar >= 0)
527 351 : return;
528 0 : switch (aar)
529 : {
530 0 : case TALER_AAR_INVALID_NEGATIVE_RESULT:
531 0 : msg =
532 : "negative result in amount subtraction (likely the database is corrupt, see manual)";
533 0 : break;
534 0 : case TALER_AAR_INVALID_NORMALIZATION_FAILED:
535 0 : msg =
536 : "normalization failed in amount subtraction (likely the database is corrupt, see manual)";
537 0 : break;
538 0 : case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE:
539 0 : msg =
540 : "currencies incompatible in amount subtraction (likely bad configuration and auditor code missing a sanity check, see manual)";
541 0 : break;
542 0 : default:
543 0 : GNUNET_assert (0); /* should be impossible */
544 : }
545 0 : a2s = TALER_amount_to_string (a2);
546 0 : fprintf (stderr,
547 : "Aborting audit due to fatal error in function %s at %s:%d trying to subtract %s from %s: %s\n",
548 : functionname,
549 : filename,
550 : line,
551 : a2s,
552 : TALER_amount2s (a1),
553 : msg);
554 0 : GNUNET_free (a2s);
555 0 : exit (42);
556 : }
557 :
558 :
559 : enum TALER_ARL_SubtractionResult
560 676 : TALER_ARL_amount_subtract_neg_ (struct TALER_Amount *diff,
561 : const struct TALER_Amount *a1,
562 : const struct TALER_Amount *a2,
563 : const char *filename,
564 : const char *functionname,
565 : unsigned int line)
566 : {
567 : enum TALER_AmountArithmeticResult aar;
568 : const char *msg;
569 : char *a2s;
570 :
571 676 : aar = TALER_amount_subtract (diff,
572 : a1,
573 : a2);
574 676 : switch (aar)
575 : {
576 663 : case TALER_AAR_RESULT_POSITIVE:
577 663 : return TALER_ARL_SR_POSITIVE;
578 5 : case TALER_AAR_RESULT_ZERO:
579 5 : return TALER_ARL_SR_ZERO;
580 8 : case TALER_AAR_INVALID_NEGATIVE_RESULT:
581 8 : return TALER_ARL_SR_INVALID_NEGATIVE;
582 0 : case TALER_AAR_INVALID_NORMALIZATION_FAILED:
583 0 : msg =
584 : "normalization failed in amount subtraction (likely the database is corrupt, see manual)";
585 0 : break;
586 0 : case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE:
587 0 : msg =
588 : "currencies incompatible in amount subtraction (likely bad configuration and auditor code missing a sanity check, see manual)";
589 0 : break;
590 0 : default:
591 0 : GNUNET_assert (0); /* should be impossible */
592 : }
593 0 : a2s = TALER_amount_to_string (a2);
594 0 : fprintf (stderr,
595 : "Aborting audit due to fatal error in function %s at %s:%d trying to subtract %s from %s: %s\n",
596 : functionname,
597 : filename,
598 : line,
599 : a2s,
600 : TALER_amount2s (a1),
601 : msg);
602 0 : GNUNET_free (a2s);
603 0 : exit (42);
604 : }
605 :
606 :
607 : enum GNUNET_GenericReturnValue
608 574 : TALER_ARL_init (const struct GNUNET_CONFIGURATION_Handle *c)
609 : {
610 574 : TALER_ARL_cfg = c;
611 574 : start_time = GNUNET_TIME_absolute_get ();
612 :
613 574 : if (GNUNET_OK !=
614 574 : GNUNET_CONFIGURATION_get_value_string (TALER_ARL_cfg,
615 : "auditor",
616 : "BASE_URL",
617 : &TALER_ARL_auditor_url))
618 : {
619 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
620 : "auditor",
621 : "BASE_URL");
622 0 : return GNUNET_SYSERR;
623 : }
624 574 : if (GNUNET_OK !=
625 574 : GNUNET_CONFIGURATION_get_value_string (TALER_ARL_cfg,
626 : "exchange",
627 : "BASE_URL",
628 : &TALER_ARL_exchange_url))
629 : {
630 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
631 : "exchange",
632 : "BASE_URL");
633 0 : return GNUNET_SYSERR;
634 : }
635 :
636 574 : if (GNUNET_is_zero (&TALER_ARL_master_pub))
637 : {
638 : /* -m option not given, try configuration */
639 : char *master_public_key_str;
640 :
641 574 : if (GNUNET_OK !=
642 574 : GNUNET_CONFIGURATION_get_value_string (TALER_ARL_cfg,
643 : "exchange",
644 : "MASTER_PUBLIC_KEY",
645 : &master_public_key_str))
646 : {
647 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
648 : "Pass option -m or set MASTER_PUBLIC_KEY in the configuration!\n");
649 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
650 : "exchange",
651 : "MASTER_PUBLIC_KEY");
652 0 : return GNUNET_SYSERR;
653 : }
654 574 : if (GNUNET_OK !=
655 574 : GNUNET_CRYPTO_eddsa_public_key_from_string (
656 : master_public_key_str,
657 : strlen (master_public_key_str),
658 : &TALER_ARL_master_pub.eddsa_pub))
659 : {
660 0 : GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
661 : "exchange",
662 : "MASTER_PUBLIC_KEY",
663 : "invalid key");
664 0 : GNUNET_free (master_public_key_str);
665 0 : return GNUNET_SYSERR;
666 : }
667 574 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
668 : "Running auditor against exchange master public key `%s'\n",
669 : master_public_key_str);
670 574 : GNUNET_free (master_public_key_str);
671 : } /* end of -m not given */
672 :
673 574 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
674 : "Taler auditor running for exchange master public key %s\n",
675 : TALER_B2S (&TALER_ARL_master_pub));
676 :
677 574 : if (GNUNET_is_zero (&TALER_ARL_auditor_pub))
678 : {
679 : char *auditor_public_key_str;
680 :
681 574 : if (GNUNET_OK ==
682 574 : GNUNET_CONFIGURATION_get_value_string (c,
683 : "auditor",
684 : "PUBLIC_KEY",
685 : &auditor_public_key_str))
686 : {
687 574 : if (GNUNET_OK !=
688 574 : GNUNET_CRYPTO_eddsa_public_key_from_string (
689 : auditor_public_key_str,
690 : strlen (auditor_public_key_str),
691 : &TALER_ARL_auditor_pub.eddsa_pub))
692 : {
693 0 : GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
694 : "auditor",
695 : "PUBLIC_KEY",
696 : "invalid key");
697 0 : GNUNET_free (auditor_public_key_str);
698 0 : return GNUNET_SYSERR;
699 : }
700 574 : GNUNET_free (auditor_public_key_str);
701 : }
702 : }
703 :
704 574 : if (GNUNET_is_zero (&TALER_ARL_auditor_pub))
705 : {
706 : /* public key not configured */
707 : /* try loading private key and deriving public key */
708 : char *fn;
709 :
710 0 : if (GNUNET_OK ==
711 0 : GNUNET_CONFIGURATION_get_value_filename (c,
712 : "auditor",
713 : "AUDITOR_PRIV_FILE",
714 : &fn))
715 : {
716 : struct TALER_AuditorPrivateKeyP auditor_priv;
717 :
718 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
719 : "Loading offline private key from `%s' to get auditor public key\n",
720 : fn);
721 0 : if (GNUNET_OK ==
722 0 : GNUNET_CRYPTO_eddsa_key_from_file (fn,
723 : GNUNET_NO, /* do NOT create it! */
724 : &auditor_priv.eddsa_priv))
725 : {
726 0 : GNUNET_CRYPTO_eddsa_key_get_public (&auditor_priv.eddsa_priv,
727 : &TALER_ARL_auditor_pub.eddsa_pub);
728 : }
729 0 : GNUNET_free (fn);
730 : }
731 : }
732 :
733 574 : if (GNUNET_is_zero (&TALER_ARL_auditor_pub))
734 : {
735 0 : GNUNET_log_config_missing (GNUNET_ERROR_TYPE_INFO,
736 : "auditor",
737 : "PUBLIC_KEY/AUDITOR_PRIV_FILE");
738 0 : return GNUNET_SYSERR;
739 : }
740 :
741 574 : if (GNUNET_OK !=
742 574 : TALER_config_get_currency (TALER_ARL_cfg,
743 : "exchange",
744 : &TALER_ARL_currency))
745 : {
746 0 : return GNUNET_SYSERR;
747 : }
748 : {
749 574 : if ( (GNUNET_OK !=
750 574 : TALER_config_get_amount (TALER_ARL_cfg,
751 : "exchange",
752 : "CURRENCY_ROUND_UNIT",
753 574 : &TALER_ARL_currency_round_unit)) ||
754 574 : ( (0 != TALER_ARL_currency_round_unit.fraction) &&
755 574 : (0 != TALER_ARL_currency_round_unit.value) ) )
756 : {
757 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
758 : "Need non-zero value in section `exchange' under `CURRENCY_ROUND_UNIT'\n");
759 0 : return GNUNET_SYSERR;
760 : }
761 : }
762 574 : if (NULL ==
763 574 : (TALER_ARL_edb = TALER_EXCHANGEDB_plugin_load (TALER_ARL_cfg,
764 : false)))
765 : {
766 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
767 : "Failed to initialize exchange database plugin.\n");
768 0 : TALER_ARL_done ();
769 0 : return GNUNET_SYSERR;
770 : }
771 574 : if (NULL ==
772 574 : (TALER_ARL_adb = TALER_AUDITORDB_plugin_load (TALER_ARL_cfg,
773 : false)))
774 : {
775 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
776 : "Failed to initialize auditor database plugin.\n");
777 0 : TALER_ARL_done ();
778 0 : return GNUNET_SYSERR;
779 : }
780 574 : if (GNUNET_SYSERR ==
781 574 : TALER_ARL_adb->preflight (TALER_ARL_adb->cls))
782 : {
783 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
784 : "Failed to start session with auditor database.\n");
785 0 : TALER_ARL_done ();
786 0 : return GNUNET_SYSERR;
787 : }
788 574 : return GNUNET_OK;
789 : }
790 :
791 :
792 : void
793 574 : TALER_ARL_done ()
794 : {
795 574 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
796 : "Audit complete\n");
797 574 : if (NULL != TALER_ARL_adb)
798 : {
799 574 : TALER_AUDITORDB_plugin_unload (TALER_ARL_adb);
800 574 : TALER_ARL_adb = NULL;
801 : }
802 574 : if (NULL != TALER_ARL_edb)
803 : {
804 574 : TALER_EXCHANGEDB_plugin_unload (TALER_ARL_edb);
805 574 : TALER_ARL_edb = NULL;
806 : }
807 574 : GNUNET_free (TALER_ARL_exchange_url);
808 574 : GNUNET_free (TALER_ARL_auditor_url);
809 574 : }
810 :
811 :
812 : /* end of report-lib.c */
|