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