cfengine  3.15.4
About: CFEngine is a configuration management system for configuring and maintaining Unix-like computers (using an own high level policy language). Community version.
  Fossies Dox: cfengine-3.15.4.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

lastseen.c
Go to the documentation of this file.
1 /*
2  Copyright 2019 Northern.tech AS
3 
4  This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
5 
6  This program is free software; you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by the
8  Free Software Foundation; version 3.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 
19  To the extent this program is licensed as part of the Enterprise
20  versions of CFEngine, the applicable Commercial Open Source License
21  (COSL) may apply to this file if you as a licensee so wish it. See
22  included file COSL.txt.
23 */
24 
25 #include <cf3.defs.h>
26 
27 #include <lastseen.h>
28 #include <conversion.h>
29 #include <hash.h>
30 #include <locks.h>
31 #include <item_lib.h>
32 #include <known_dirs.h>
33 #ifdef LMDB
34 #include <lmdb.h>
35 #endif
36 
37 void UpdateLastSawHost(const char *hostkey, const char *address,
38  bool incoming, time_t timestamp);
39 
40 /*
41  * Lastseen database schema (version 1):
42  *
43  * Version entry
44  *
45  * key: "version\0"
46  * value: "1\0"
47  *
48  * "Quality of connection" entries
49  *
50  * key: q<direction><hostkey> (direction: 'i' for incoming, 'o' for outgoing)
51  * value: struct KeyHostSeen
52  *
53  * "Hostkey" entries
54  *
55  * key: k<hostkey> ("MD5-ffffefefeefef..." or "SHA-abacabaca...")
56  * value: <address> (IPv4 or IPv6)
57  *
58  * "Address", or reverse, entries (auxiliary)
59  *
60  * key: a<address> (IPv6 or IPv6)
61  * value: <hostkey>
62  *
63  *
64  *
65  * Schema version 0 mapped direction + hostkey to address + quality of
66  * connection. This approach had a number of drawbacks:
67  * - There were two potentially conflicting addresses for given hostkey.
68  * - There was no way to quickly lookup hostkey by address.
69  * - Address update required traversal of the whole database.
70  *
71  * In order to overcome these limitations, new schema normalized (in relational
72  * algebra sense) the data relations.
73  */
74 
75 /* TODO #ifndef NDEBUG check, report loudly, and fix consistency issues in every operation. */
76 
77 /*****************************************************************************/
78 
79 /**
80  * @brief Same as LastSaw() but the digest parameter is the hash as a
81  * "SHA=..." string, to avoid converting twice.
82  */
83 void LastSaw1(const char *ipaddress, const char *hashstr,
84  LastSeenRole role)
85 {
86  const char *mapip = MapAddress(ipaddress);
87  UpdateLastSawHost(hashstr, mapip, role == LAST_SEEN_ROLE_ACCEPT, time(NULL));
88 }
89 
90 void LastSaw(const char *ipaddress, const char *digest, LastSeenRole role)
91 {
92  char databuf[CF_HOSTKEY_STRING_SIZE];
93 
94  if (strlen(ipaddress) == 0)
95  {
96  Log(LOG_LEVEL_INFO, "LastSeen registry for empty IP with role %d", role);
97  return;
98  }
99 
100  HashPrintSafe(databuf, sizeof(databuf), digest, CF_DEFAULT_DIGEST, true);
101 
102  const char *mapip = MapAddress(ipaddress);
103 
104  UpdateLastSawHost(databuf, mapip, role == LAST_SEEN_ROLE_ACCEPT, time(NULL));
105 }
106 
107 /*****************************************************************************/
108 
109 void UpdateLastSawHost(const char *hostkey, const char *address,
110  bool incoming, time_t timestamp)
111 {
112  DBHandle *db = NULL;
113  if (!OpenDB(&db, dbid_lastseen))
114  {
115  Log(LOG_LEVEL_ERR, "Unable to open last seen db");
116  return;
117  }
118 
119  /* Update quality-of-connection entry */
120 
121  char quality_key[CF_BUFSIZE];
122  snprintf(quality_key, CF_BUFSIZE, "q%c%s", incoming ? 'i' : 'o', hostkey);
123 
124  KeyHostSeen newq = { .lastseen = timestamp };
125 
126  KeyHostSeen q;
127  if (ReadDB(db, quality_key, &q, sizeof(q)))
128  {
129  newq.Q = QAverage(q.Q, newq.lastseen - q.lastseen, 0.4);
130  }
131  else
132  {
133  /* FIXME: more meaningful default value? */
134  newq.Q = QDefinite(0);
135  }
136  WriteDB(db, quality_key, &newq, sizeof(newq));
137 
138  /* Update forward mapping */
139 
140  char hostkey_key[CF_BUFSIZE];
141  snprintf(hostkey_key, CF_BUFSIZE, "k%s", hostkey);
142 
143  WriteDB(db, hostkey_key, address, strlen(address) + 1);
144 
145  /* Update reverse mapping */
146 
147  char address_key[CF_BUFSIZE];
148  snprintf(address_key, CF_BUFSIZE, "a%s", address);
149 
150  WriteDB(db, address_key, hostkey, strlen(hostkey) + 1);
151 
152  CloseDB(db);
153 }
154 /*****************************************************************************/
155 
156 /* Lookup a reverse entry (IP->KeyHash) in lastseen database. */
157 static bool Address2HostkeyInDB(DBHandle *db, const char *address, char *result, size_t result_size)
158 {
159  char address_key[CF_BUFSIZE];
160  char hostkey[CF_BUFSIZE];
161 
162  /* Address key: "a" + address */
163  snprintf(address_key, CF_BUFSIZE, "a%s", address);
164 
165  if (!ReadDB(db, address_key, &hostkey, sizeof(hostkey)))
166  {
167  return false;
168  }
169 
170 #ifndef NDEBUG
171  /* Check for inconsistencies. Return success even if db is found
172  * inconsistent, since the reverse entry is already found. */
173 
174  char hostkey_key[CF_BUFSIZE];
175  char back_address[CF_BUFSIZE];
176 
177  /* Hostkey key: "k" + hostkey */
178  snprintf(hostkey_key, CF_BUFSIZE, "k%s", hostkey);
179 
180  if (!ReadDB(db, hostkey_key, &back_address, sizeof(back_address)))
181  {
182  Log(LOG_LEVEL_WARNING, "Lastseen db inconsistency: "
183  "no key entry '%s' for existing host entry '%s'",
184  hostkey_key, address_key);
185  }
186 #endif
187 
188  strlcpy(result, hostkey, result_size);
189  return true;
190 }
191 
192 /*****************************************************************************/
193 
194 /* Given an address it returns a key - its own key if address is 127.0.0.1,
195  * else it looks the "aADDRESS" entry in lastseen. */
196 bool Address2Hostkey(char *dst, size_t dst_size, const char *address)
197 {
198  bool retval = false;
199  dst[0] = '\0';
200 
201  if ((strcmp(address, "127.0.0.1") == 0) ||
202  (strcmp(address, "::1") == 0) ||
203  (strcmp(address, VIPADDRESS) == 0))
204  {
206  "Address2Hostkey: Returning local key for address %s",
207  address);
208 
209  if (PUBKEY)
210  {
211  unsigned char digest[EVP_MAX_MD_SIZE + 1];
213  HashPrintSafe(dst, dst_size, digest,
214  CF_DEFAULT_DIGEST, true);
215  retval = true;
216  }
217  else
218  {
220  "Local key not found, generate one with cf-key?");
221  retval = false;
222  }
223  }
224  else /* lastseen lookup */
225  {
226  DBHandle *db;
227  if (OpenDB(&db, dbid_lastseen))
228  {
229  retval = Address2HostkeyInDB(db, address, dst, dst_size);
230  CloseDB(db);
231 
232  if (!retval)
233  {
235  "Key digest for address '%s' was not found in lastseen db!",
236  address);
237  }
238  }
239  }
240 
241  return retval;
242 }
243 
244 /**
245  * @brief detects whether input is a host/ip name or a key digest
246  *
247  * @param[in] key digest (SHA/MD5 format) or free host name string
248  * (character '=' is optional but recommended)
249  * @retval true if a key digest, false otherwise
250  */
251 static bool IsDigestOrHost(const char *input)
252 {
253  if (strncmp(input, "SHA=", 3) == 0)
254  {
255  return true;
256  }
257  else if (strncmp(input, "MD5=", 3) == 0)
258  {
259  return true;
260  }
261  else
262  {
263  return false;
264  }
265 }
266 
267 /**
268  * @brief check whether the lastseen DB is coherent or not.
269  *
270  * It is allowed for a aIP1 -> KEY1 to not have a reverse kKEY1 -> IP.
271  * kKEY1 *must* exist, but may point to another IP.
272  * Same for IP values, they *must* appear as aIP entries, but we don't
273  * care where they point to.
274  * So for every aIP->KEY1 entry there should be a kKEY1->whatever entry.
275  * And for every kKEY->IP1 entry there should be a aIP1->whatever entry.
276  *
277  * If a host changes IP, then we have a new entry aIP2 -> KEY1 together
278  * with the aIP1 -> KEY1 entry. ALLOWED.
279  *
280  * If a host changes key, then its entry will become aIP1 -> KEY2.
281  * Then still it will exist kKEY1 -> IP1 but also kKEY2 -> IP1. ALLOWED
282  *
283  * Can I have a IP value of some kKEY that does not have any aIP entry?
284  * NO because at some time aIP it was written in the database.
285  * SO EVERY kIP must be found in aIPS.
286  * kIPS SUBSET OF aIPS
287  *
288  * Can I have a KEY value of some aIP that does not have any kKEY entry?
289  * NO for the same reason.
290  * SO EVERY akey must be found in kkeys.
291  * aKEYS SUBSET OF kKEYS
292  *
293  * FIN
294  *
295  * @TODO P.S. redesign lastseen. Really, these whole requirements are
296  * implemented on top of a simple key-value store, no wonder it's such a
297  * mess. I believe that reverse mapping is not even needed since only
298  * aIP entries are ever looked up. kKEY entries can be deprecated and
299  * forget all the false notion of "schema consistency" in this key-value
300  * store...
301  *
302  * @retval true if the lastseen DB is coherent, false otherwise.
303  */
305 {
306  DBHandle *db;
307  DBCursor *cursor;
308 
309  if (!OpenDB(&db, dbid_lastseen))
310  {
311  char *db_path = DBIdToPath(dbid_lastseen);
312  Log(LOG_LEVEL_ERR, "Unable to open lastseen database '%s'", db_path);
313  free(db_path);
314  return false;
315  }
316 
317  if (!NewDBCursor(db, &cursor))
318  {
319  Log(LOG_LEVEL_ERR, "Unable to create lastseen database cursor");
320  CloseDB(db);
321  return false;
322  }
323 
324  char *key;
325  void *value;
326  int ksize, vsize;
327 
328  Item *qKEYS = NULL;
329  Item *aKEYS = NULL;
330  Item *kKEYS = NULL;
331  Item *aIPS = NULL;
332  Item *kIPS = NULL;
333 
334  bool result = true;
335  while (NextDB(cursor, &key, &ksize, &value, &vsize))
336  {
337  if (strcmp(key, "version") != 0 &&
338  strncmp(key, "qi", 2) != 0 &&
339  strncmp(key, "qo", 2) != 0 &&
340  key[0] != 'k' &&
341  key[0] != 'a')
342  {
344  "lastseen db inconsistency, unexpected key: %s",
345  key);
346  result = false;
347  }
348 
349  if (key[0] == 'q' )
350  {
351  if (strncmp(key,"qiSHA=",5)==0 || strncmp(key,"qoSHA=",5)==0 ||
352  strncmp(key,"qiMD5=",5)==0 || strncmp(key,"qoMD5=",5)==0)
353  {
354  if (!IsItemIn(qKEYS, key+2))
355  {
356  PrependItem(&qKEYS, key+2, NULL);
357  }
358  }
359  }
360 
361  if (key[0] == 'k' )
362  {
363  if (strncmp(key, "kSHA=", 4)==0 || strncmp(key, "kMD5=", 4)==0)
364  {
365  if (!IsItemIn(kKEYS, key+1))
366  {
367  PrependItem(&kKEYS, key+1, NULL);
368  }
369  if (!IsItemIn(kIPS, value))
370  {
371  PrependItem(&kIPS, value, NULL);
372  }
373  }
374  }
375 
376  if (key[0] == 'a' )
377  {
378  if (!IsItemIn(aIPS, key+1))
379  {
380  PrependItem(&aIPS, key+1, NULL);
381  }
382  if (!IsItemIn(aKEYS, value))
383  {
384  PrependItem(&aKEYS, value, NULL);
385  }
386  }
387  }
388 
389  DeleteDBCursor(cursor);
390  CloseDB(db);
391 
392 
393  /* For every kKEY->IP1 entry there should be a aIP1->whatever entry.
394  * So basically: kIPS SUBSET OF aIPS. */
395  Item *kip = kIPS;
396  while (kip != NULL)
397  {
398  if (!IsItemIn(aIPS, kip->name))
399  {
401  "lastseen db inconsistency, found kKEY -> '%s' entry, "
402  "but no 'a%s' -> any key entry exists!",
403  kip->name, kip->name);
404 
405  result = false;
406  }
407 
408  kip = kip->next;
409  }
410 
411  /* For every aIP->KEY1 entry there should be a kKEY1->whatever entry.
412  * So basically: aKEYS SUBSET OF kKEYS. */
413  Item *akey = aKEYS;
414  while (akey != NULL)
415  {
416  if (!IsItemIn(kKEYS, akey->name))
417  {
419  "lastseen db inconsistency, found aIP -> '%s' entry, "
420  "but no 'k%s' -> any ip entry exists!",
421  akey->name, akey->name);
422 
423  result = false;
424  }
425 
426  akey = akey->next;
427  }
428 
429  DeleteItemList(qKEYS);
430  DeleteItemList(aKEYS);
431  DeleteItemList(kKEYS);
432  DeleteItemList(aIPS);
433  DeleteItemList(kIPS);
434 
435  return result;
436 }
437 
438 /**
439  * @brief removes all traces of host 'ip' from lastseen DB
440  *
441  * @param[in] ip : either in (SHA/MD5 format)
442  * @param[in,out] digest: return corresponding digest of input host.
443  * If NULL, return nothing
444  * @param[in] digest_size: size of digest parameter
445  * @retval true if entry was deleted, false otherwise
446  */
447 bool DeleteIpFromLastSeen(const char *ip, char *digest, size_t digest_size)
448 {
449  DBHandle *db;
450  bool res = false;
451 
452  if (!OpenDB(&db, dbid_lastseen))
453  {
454  char *db_path = DBIdToPath(dbid_lastseen);
455  Log(LOG_LEVEL_ERR, "Unable to open lastseen database '%s'", db_path);
456  free(db_path);
457  return false;
458  }
459 
460  char bufkey[CF_BUFSIZE + 1];
461  char bufhost[CF_BUFSIZE + 1];
462 
463  strcpy(bufhost, "a");
464  strlcat(bufhost, ip, CF_BUFSIZE);
465 
466  char key[CF_BUFSIZE];
467  if (ReadDB(db, bufhost, &key, sizeof(key)) == true)
468  {
469  strcpy(bufkey, "k");
470  strlcat(bufkey, key, CF_BUFSIZE);
471  if (HasKeyDB(db, bufkey, strlen(bufkey) + 1) == false)
472  {
473  res = false;
474  goto clean;
475  }
476  else
477  {
478  if (digest != NULL)
479  {
480  strlcpy(digest, bufkey + 1, digest_size);
481  }
482  DeleteDB(db, bufkey);
483  DeleteDB(db, bufhost);
484  res = true;
485  }
486  }
487  else
488  {
489  res = false;
490  goto clean;
491  }
492 
493  strcpy(bufkey, "qi");
494  strlcat(bufkey, key, CF_BUFSIZE);
495  DeleteDB(db, bufkey);
496 
497  strcpy(bufkey, "qo");
498  strlcat(bufkey, key, CF_BUFSIZE);
499  DeleteDB(db, bufkey);
500 
501 clean:
502  CloseDB(db);
503  return res;
504 }
505 
506 /**
507  * @brief removes all traces of key digest 'key' from lastseen DB
508  *
509  * @param[in] key : either in (SHA/MD5 format)
510  * @param[in,out] ip : return the key corresponding host.
511  * If NULL, return nothing
512  * @param[in] ip_size : length of ip parameter
513  * @param[in] a_entry_required : whether 'aIP_ADDR' entry is required for
514  * the 'kHOSTKEY' entry deletion
515  * @retval true if entry was deleted, false otherwise
516  */
517 bool DeleteDigestFromLastSeen(const char *key, char *ip, size_t ip_size, bool a_entry_required)
518 {
519  DBHandle *db;
520  bool res = false;
521 
522  if (!OpenDB(&db, dbid_lastseen))
523  {
524  char *db_path = DBIdToPath(dbid_lastseen);
525  Log(LOG_LEVEL_ERR, "Unable to open lastseen database '%s'", db_path);
526  free(db_path);
527  return false;
528  }
529  char bufkey[CF_BUFSIZE + 1];
530  char bufhost[CF_BUFSIZE + 1];
531 
532  strcpy(bufkey, "k");
533  strlcat(bufkey, key, CF_BUFSIZE);
534 
535  char host[CF_BUFSIZE];
536  if (ReadDB(db, bufkey, &host, sizeof(host)) == true)
537  {
538  strcpy(bufhost, "a");
539  strlcat(bufhost, host, CF_BUFSIZE);
540  if (a_entry_required && !HasKeyDB(db, bufhost, strlen(bufhost) + 1))
541  {
542  res = false;
543  goto clean;
544  }
545  else
546  {
547  if (ip != NULL)
548  {
549  strlcpy(ip, host, ip_size);
550  }
551  DeleteDB(db, bufhost);
552  DeleteDB(db, bufkey);
553  res = true;
554  }
555  }
556  else
557  {
558  res = false;
559  goto clean;
560  }
561 
562  strcpy(bufkey, "qi");
563  strlcat(bufkey, key, CF_BUFSIZE);
564  DeleteDB(db, bufkey);
565 
566  strcpy(bufkey, "qo");
567  strlcat(bufkey, key, CF_BUFSIZE);
568  DeleteDB(db, bufkey);
569 
570 clean:
571  CloseDB(db);
572  return res;
573 }
574 
575 /*****************************************************************************/
577 {
579  if (!lastseen_db)
580  {
581  return false;
582  }
583  MapIterator it = MapIteratorInit(lastseen_db->impl);
584  MapKeyValue *item;
585 
586  Seq *hostkeys = SeqNew(100, free);
587  while ((item = MapIteratorNext(&it)) != NULL)
588  {
589  char *key = item->key;
590  /* Only look for "keyhost" entries */
591  if (key[0] != 'k')
592  {
593  continue;
594  }
595 
596  SeqAppend(hostkeys, xstrdup(key + 1));
597  }
598  for (int i = 0; i < SeqLength(hostkeys); ++i)
599  {
600  const char *hostkey = SeqAt(hostkeys, i);
601 
602  char keyhost_key[CF_BUFSIZE];
603  snprintf(keyhost_key, CF_BUFSIZE, "k%s", hostkey);
604  char *address = NULL;
605  address = (char*)StringMapGet(lastseen_db, keyhost_key);
606  if (!address)
607  {
608  Log(LOG_LEVEL_ERR, "Failed to read address for key '%s'.", hostkey);
609  continue;
610  }
611 
612  char incoming_key[CF_BUFSIZE];
613  snprintf(incoming_key, CF_BUFSIZE, "qi%s", hostkey);
614  KeyHostSeen *incoming = NULL;
615  incoming = (KeyHostSeen*)StringMapGet(lastseen_db, incoming_key);
616  if (incoming)
617  {
618  if (!(*callback)(hostkey, address, true, incoming, ctx))
619  {
620  break;
621  }
622  }
623 
624  char outgoing_key[CF_BUFSIZE];
625  snprintf(outgoing_key, CF_BUFSIZE, "qo%s", hostkey);
626  KeyHostSeen *outgoing = NULL;
627  outgoing = (KeyHostSeen*)StringMapGet(lastseen_db, outgoing_key);
628  if (outgoing)
629  {
630  if (!(*callback)(hostkey, address, false, outgoing, ctx))
631  {
632  break;
633  }
634  }
635  }
636 
637  StringMapDestroy(lastseen_db);
638  SeqDestroy(hostkeys);
639 
640  return true;
641 }
642 
643 /*****************************************************************************/
644 
646 {
647  CF_DB *dbp;
648  CF_DBC *dbcp;
649  QPoint entry;
650  char *key;
651  void *value;
652  int ksize, vsize;
653 
654  int count = 0;
655 
656  if (OpenDB(&dbp, dbid_lastseen))
657  {
658  memset(&entry, 0, sizeof(entry));
659 
660  if (NewDBCursor(dbp, &dbcp))
661  {
662  while (NextDB(dbcp, &key, &ksize, &value, &vsize))
663  {
664  /* Only look for valid "hostkey" entries */
665 
666  if ((key[0] != 'k') || (value == NULL))
667  {
668  continue;
669  }
670 
671  count++;
672  }
673 
674  DeleteDBCursor(dbcp);
675  }
676 
677  CloseDB(dbp);
678  }
679 
680  return count;
681 }
682 /**
683  * @brief removes all traces of entry 'input' from lastseen DB
684  *
685  * @param[in] key digest (SHA/MD5 format) or free host name string
686  * @param[in] must_be_coherent. false : delete if lastseen is incoherent,
687  * true : don't if lastseen is incoherent
688  * @param[out] equivalent. If input is a host, return its corresponding
689  * digest. If input is a digest, return its
690  * corresponding host. CAN BE NULL! If equivalent
691  * is null, it stays as NULL
692  * @retval 0 if entry was deleted, <>0 otherwise
693  */
694 int RemoveKeysFromLastSeen(const char *input, bool must_be_coherent,
695  char *equivalent, size_t equivalent_size)
696 {
697  bool is_coherent = false;
698 
699  if (must_be_coherent == true)
700  {
701  is_coherent = IsLastSeenCoherent();
702  if (is_coherent == false)
703  {
704  Log(LOG_LEVEL_ERR, "Lastseen database is incoherent (there is not a 1-to-1 relationship between hosts and keys) and coherence check is enforced. Will not proceed to remove entries from it.");
705  return 254;
706  }
707  }
708 
709  bool is_digest;
710  is_digest = IsDigestOrHost(input);
711 
712  if (is_digest == true)
713  {
714  Log(LOG_LEVEL_VERBOSE, "Removing digest '%s' from lastseen database\n", input);
715  if (!DeleteDigestFromLastSeen(input, equivalent, equivalent_size, must_be_coherent))
716  {
717  Log(LOG_LEVEL_ERR, "Unable to remove digest from lastseen database.");
718  return 252;
719  }
720  }
721  else
722  {
723  Log(LOG_LEVEL_VERBOSE, "Removing host '%s' from lastseen database\n", input);
724  if (DeleteIpFromLastSeen(input, equivalent, equivalent_size) == false)
725  {
726  Log(LOG_LEVEL_ERR, "Unable to remove host from lastseen database.");
727  return 253;
728  }
729  }
730 
731  Log(LOG_LEVEL_INFO, "Removed corresponding entries from lastseen database.");
732 
733  return 0;
734 }
735 
char * xstrdup(const char *str)
Definition: alloc-mini.c:56
HashMethod CF_DEFAULT_DIGEST
Definition: cf3globals.c:88
static int input(void)
Definition: cf3lex.c:2154
void free(void *)
char VIPADDRESS[64]
Definition: cf3globals.c:81
const char * MapAddress(const char *unspec_address)
Definition: conversion.c:38
StringMap * LoadDatabaseToStringMap(dbid database_id)
Definition: dbm_api.c:665
bool NextDB(DBCursor *cursor, char **key, int *ksize, void **value, int *vsize)
Definition: dbm_api.c:601
bool DeleteDB(DBHandle *handle, const char *key)
Definition: dbm_api.c:583
bool OpenDB(DBHandle **dbp, dbid id)
Definition: dbm_api.c:441
char * DBIdToPath(dbid id)
Definition: dbm_api.c:171
bool ReadDB(DBHandle *handle, const char *key, void *dest, int destSz)
Definition: dbm_api.c:556
bool HasKeyDB(DBHandle *handle, const char *key, int key_size)
Definition: dbm_api.c:573
bool DeleteDBCursor(DBCursor *cursor)
Definition: dbm_api.c:617
bool WriteDB(DBHandle *handle, const char *key, const void *src, int srcSz)
Definition: dbm_api.c:561
void CloseDB(DBHandle *handle)
Definition: dbm_api.c:472
bool NewDBCursor(DBHandle *handle, DBCursor **cursor)
Definition: dbm_api.c:588
@ dbid_lastseen
Definition: dbm_api.h:45
#define CF_BUFSIZE
Definition: definitions.h:50
#define NULL
Definition: getopt1.c:56
void HashPubKey(const RSA *const key, unsigned char digest[EVP_MAX_MD_SIZE+1], const HashMethod type)
Definition: hash.c:530
char * HashPrintSafe(char *dst, size_t dst_size, const unsigned char *digest, HashMethod type, bool use_prefix)
Definition: hash.c:612
#define CF_HOSTKEY_STRING_SIZE
Definition: hash.h:151
void DeleteItemList(Item *item)
Definition: item_lib.c:808
bool IsItemIn(const Item *list, const char *item)
Definition: item_lib.c:226
Item * PrependItem(Item **liststart, const char *itemstring, const char *classes)
Definition: item_lib.c:372
static bool IsDigestOrHost(const char *input)
detects whether input is a host/ip name or a key digest
Definition: lastseen.c:251
bool DeleteIpFromLastSeen(const char *ip, char *digest, size_t digest_size)
removes all traces of host 'ip' from lastseen DB
Definition: lastseen.c:447
int RemoveKeysFromLastSeen(const char *input, bool must_be_coherent, char *equivalent, size_t equivalent_size)
removes all traces of entry 'input' from lastseen DB
Definition: lastseen.c:694
int LastSeenHostKeyCount(void)
Definition: lastseen.c:645
void UpdateLastSawHost(const char *hostkey, const char *address, bool incoming, time_t timestamp)
Definition: lastseen.c:109
void LastSaw(const char *ipaddress, const char *digest, LastSeenRole role)
Definition: lastseen.c:90
bool DeleteDigestFromLastSeen(const char *key, char *ip, size_t ip_size, bool a_entry_required)
removes all traces of key digest 'key' from lastseen DB
Definition: lastseen.c:517
bool IsLastSeenCoherent(void)
check whether the lastseen DB is coherent or not.
Definition: lastseen.c:304
static bool Address2HostkeyInDB(DBHandle *db, const char *address, char *result, size_t result_size)
Definition: lastseen.c:157
bool ScanLastSeenQuality(LastSeenQualityCallback callback, void *ctx)
Definition: lastseen.c:576
void LastSaw1(const char *ipaddress, const char *hashstr, LastSeenRole role)
Same as LastSaw() but the digest parameter is the hash as a "SHA=..." string, to avoid converting twi...
Definition: lastseen.c:83
bool Address2Hostkey(char *dst, size_t dst_size, const char *address)
Definition: lastseen.c:196
LastSeenRole
Definition: lastseen.h:37
@ LAST_SEEN_ROLE_ACCEPT
Definition: lastseen.h:39
bool(* LastSeenQualityCallback)(const char *hostkey, const char *address, bool incoming, const KeyHostSeen *quality, void *ctx)
Definition: lastseen.h:54
void Log(LogLevel level, const char *fmt,...)
Definition: logging.c:409
@ LOG_LEVEL_ERR
Definition: logging.h:42
@ LOG_LEVEL_DEBUG
Definition: logging.h:47
@ LOG_LEVEL_WARNING
Definition: logging.h:43
@ LOG_LEVEL_VERBOSE
Definition: logging.h:46
@ LOG_LEVEL_INFO
Definition: logging.h:45
MapIterator MapIteratorInit(Map *map)
Definition: map.c:325
void StringMapDestroy(StringMap *map)
Definition: map.c:359
char * StringMapGet(const StringMap *map, const char *key)
Definition: map.c:359
MapKeyValue * MapIteratorNext(MapIterator *i)
Definition: map.c:343
size_t SeqLength(const Seq *seq)
Length of the sequence.
Definition: sequence.c:354
Seq * SeqNew(size_t initialCapacity, void(ItemDestroy)(void *item))
Definition: sequence.c:31
void SeqDestroy(Seq *seq)
Destroy an existing Sequence.
Definition: sequence.c:60
void SeqAppend(Seq *seq, void *item)
Append a new item to the Sequence.
Definition: sequence.c:104
static void * SeqAt(const Seq *seq, int i)
Definition: sequence.h:57
QPoint QAverage(QPoint old, double new_q, double p)
Definition: statistics.c:44
QPoint QDefinite(double q)
Definition: statistics.c:61
size_t strlcat(char *dst, const char *src, size_t siz)
Definition: strlcat.c:36
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:34
Definition: item_lib.h:33
Item * next
Definition: item_lib.h:38
char * name
Definition: item_lib.h:34
time_t lastseen
Definition: db_structs.h:20
QPoint Q
Definition: db_structs.h:21
void * key
Definition: map_common.h:35
Sequence data-structure.
Definition: sequence.h:50
Definition: map.h:212
Map * impl
Definition: map.h:212
RSA * PUBKEY
Definition: tls_client.c:44