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