PageRenderTime 24ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/cfengine-3.3.0/src/lastseen.c

#
C | 290 lines | 176 code | 60 blank | 54 comment | 29 complexity | 7a722a697fe62af80048e6cfbe7e7d6b MD5 | raw file
Possible License(s): GPL-3.0
  1. /*
  2. Copyright (C) Cfengine AS
  3. This file is part of Cfengine 3 - written and maintained by Cfengine AS.
  4. This program is free software; you can redistribute it and/or modify it
  5. under the terms of the GNU General Public License as published by the
  6. Free Software Foundation; version 3.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  14. To the extent this program is licensed as part of the Enterprise
  15. versions of Cfengine, the applicable Commerical Open Source License
  16. (COSL) may apply to this file if you as a licensee so wish it. See
  17. included file COSL.txt.
  18. */
  19. #include "cf3.defs.h"
  20. #include "lastseen.h"
  21. void UpdateLastSawHost(const char *hostkey, const char *address,
  22. bool incoming, time_t timestamp);
  23. /*
  24. * Lastseen database schema:
  25. *
  26. * "Quality of connection" entries
  27. *
  28. * key: q<direction><hostkey> (direction: 'i' for incoming, 'o' for outgoing)
  29. * value: struct KeyHostSeen
  30. *
  31. * "Hostkey" entries
  32. *
  33. * key: k<hostkey> ("MD5-ffffefefeefef..." or "SHA-abacabaca...")
  34. * value: <address> (IPv4 or IPv6)
  35. *
  36. * "Address", or reverse, entries
  37. *
  38. * key: a<address> (IPv6 or IPv6)
  39. * value: <hostkey>
  40. */
  41. void LastSaw(char *ipaddress, unsigned char digest[EVP_MAX_MD_SIZE + 1], enum roles role)
  42. {
  43. char databuf[CF_BUFSIZE];
  44. char *mapip;
  45. if (strlen(ipaddress) == 0)
  46. {
  47. CfOut(cf_inform, "", "LastSeen registry for empty IP with role %d", role);
  48. return;
  49. }
  50. ThreadLock(cft_output);
  51. strlcpy(databuf, HashPrint(CF_DEFAULT_DIGEST, digest), CF_BUFSIZE);
  52. ThreadUnlock(cft_output);
  53. mapip = MapAddress(ipaddress);
  54. UpdateLastSawHost(databuf, mapip, role == cf_accept, time(NULL));
  55. }
  56. void UpdateLastSawHost(const char *hostkey, const char *address,
  57. bool incoming, time_t timestamp)
  58. {
  59. DBHandle *db = NULL;
  60. if (!OpenDB(&db, dbid_lastseen))
  61. {
  62. CfOut(cf_error, "", " !! Unable to open last seen db");
  63. return;
  64. }
  65. /* Update quality-of-connection entry */
  66. char quality_key[CF_BUFSIZE];
  67. snprintf(quality_key, CF_BUFSIZE, "q%c%s", incoming ? 'i' : 'o', hostkey);
  68. KeyHostSeen newq = { .lastseen = timestamp };
  69. KeyHostSeen q;
  70. if (ReadDB(db, quality_key, &q, sizeof(q)))
  71. {
  72. newq.Q = QAverage(q.Q, newq.lastseen - q.lastseen, 0.4);
  73. }
  74. else
  75. {
  76. /* FIXME: more meaningful default value? */
  77. newq.Q = QDefinite(0);
  78. }
  79. WriteDB(db, quality_key, &newq, sizeof(newq));
  80. /* Update forward mapping */
  81. char hostkey_key[CF_BUFSIZE];
  82. snprintf(hostkey_key, CF_BUFSIZE, "k%s", hostkey);
  83. WriteDB(db, hostkey_key, address, strlen(address) + 1);
  84. /* Update reverse mapping */
  85. char address_key[CF_BUFSIZE];
  86. snprintf(address_key, CF_BUFSIZE, "a%s", address);
  87. WriteDB(db, address_key, hostkey, strlen(hostkey) + 1);
  88. CloseDB(db);
  89. }
  90. bool RemoveHostFromLastSeen(const char *hostkey)
  91. {
  92. DBHandle *db;
  93. if (!OpenDB(&db, dbid_lastseen))
  94. {
  95. CfOut(cf_error, "", "Unable to open lastseen database");
  96. return false;
  97. }
  98. /* Lookup corresponding address entry */
  99. char hostkey_key[CF_BUFSIZE];
  100. snprintf(hostkey_key, CF_BUFSIZE, "k%s", hostkey);
  101. char address[CF_BUFSIZE];
  102. if (ReadDB(db, hostkey_key, &address, sizeof(address)) == true)
  103. {
  104. /* Remove address entry */
  105. char address_key[CF_BUFSIZE];
  106. snprintf(address_key, CF_BUFSIZE, "a%s", address);
  107. DeleteDB(db, address_key);
  108. }
  109. /* Remove quality-of-connection entries */
  110. char quality_key[CF_BUFSIZE];
  111. snprintf(quality_key, CF_BUFSIZE, "qi%s", hostkey);
  112. DeleteDB(db, quality_key);
  113. snprintf(quality_key, CF_BUFSIZE, "qo%s", hostkey);
  114. DeleteDB(db, quality_key);
  115. /* Remove main entry */
  116. DeleteDB(db, hostkey_key);
  117. CloseDB(db);
  118. return true;
  119. }
  120. static bool Address2HostkeyInDB(DBHandle *db, const char *address, char *result)
  121. {
  122. char address_key[CF_BUFSIZE];
  123. char hostkey[CF_BUFSIZE];
  124. /* Address key: "a" + address */
  125. snprintf(address_key, CF_BUFSIZE, "a%s", address);
  126. if (!ReadDB(db, address_key, &hostkey, sizeof(hostkey)))
  127. {
  128. return false;
  129. }
  130. char hostkey_key[CF_BUFSIZE];
  131. char back_address[CF_BUFSIZE];
  132. /* Hostkey key: "k" + hostkey */
  133. snprintf(hostkey_key, CF_BUFSIZE, "k%s", hostkey);
  134. if (!ReadDB(db, hostkey_key, &back_address, sizeof(back_address)))
  135. {
  136. /* There is no key -> address mapping. Remove reverse mapping and return failure. */
  137. DeleteDB(db, address_key);
  138. return false;
  139. }
  140. if (strcmp(address, back_address) != 0)
  141. {
  142. /* Forward and reverse mappings do not match. Remove reverse mapping and return failure. */
  143. DeleteDB(db, address_key);
  144. return false;
  145. }
  146. strlcpy(result, hostkey, CF_BUFSIZE);
  147. return true;
  148. }
  149. bool Address2Hostkey(const char *address, char *result)
  150. {
  151. if (strcmp(address, "127.0.0.1") == 0 || strcmp(address, "::1") == 0 || strcmp(address, VIPADDRESS) == 0)
  152. {
  153. if (PUBKEY)
  154. {
  155. unsigned char digest[EVP_MAX_MD_SIZE + 1];
  156. HashPubKey(PUBKEY, digest, CF_DEFAULT_DIGEST);
  157. snprintf(result, CF_MAXVARSIZE, "%s", HashPrint(CF_DEFAULT_DIGEST, digest));
  158. return true;
  159. }
  160. else
  161. {
  162. return false;
  163. }
  164. }
  165. DBHandle *db;
  166. if (!OpenDB(&db, dbid_lastseen))
  167. {
  168. return false;
  169. }
  170. bool ret = Address2HostkeyInDB(db, address, result);
  171. CloseDB(db);
  172. return ret;
  173. }
  174. bool ScanLastSeenQuality(LastSeenQualityCallback callback, void *ctx)
  175. {
  176. DBHandle *db;
  177. DBCursor *cursor;
  178. if (!OpenDB(&db, dbid_lastseen))
  179. {
  180. CfOut(cf_error, "", "!! Unable to open lastseen database");
  181. return false;
  182. }
  183. if (!NewDBCursor(db, &cursor))
  184. {
  185. CfOut(cf_error, "", " !! Unable to create lastseen database cursor");
  186. CloseDB(db);
  187. return false;
  188. }
  189. char *key;
  190. void *value;
  191. int ksize, vsize;
  192. while (NextDB(db, cursor, &key, &ksize, &value, &vsize))
  193. {
  194. /* Only look for "keyhost" entries */
  195. if (key[0] != 'k')
  196. {
  197. continue;
  198. }
  199. const char *hostkey = key + 1;
  200. const char *address = value;
  201. char incoming_key[CF_BUFSIZE];
  202. snprintf(incoming_key, CF_BUFSIZE, "qi%s", hostkey);
  203. KeyHostSeen incoming;
  204. if (ReadDB(db, incoming_key, &incoming, sizeof(incoming)))
  205. {
  206. if (!(*callback)(hostkey, address, true, &incoming, ctx))
  207. {
  208. break;
  209. }
  210. }
  211. char outgoing_key[CF_BUFSIZE];
  212. snprintf(outgoing_key, CF_BUFSIZE, "qo%s", hostkey);
  213. KeyHostSeen outgoing;
  214. if (ReadDB(db, outgoing_key, &outgoing, sizeof(outgoing)))
  215. {
  216. if (!(*callback)(hostkey, address, false, &outgoing, ctx))
  217. {
  218. break;
  219. }
  220. }
  221. }
  222. DeleteDBCursor(db, cursor);
  223. CloseDB(db);
  224. return true;
  225. }