1 /* Copyright (C) 2009-2021 Greenbone Networks GmbH
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 /**
21 * @file
22 * @brief Implementation of API to handle NVT Info Cache
23 *
24 * This file contains all methods to handle NVT Information Cache
25 * (nvticache_t).
26 *
27 * The module consequently uses glib datatypes and api for memory
28 * management etc.
29 */
30
31 #include "nvticache.h"
32
33 #include "kb.h" /* for kb_del_items, kb_item_get_str, kb_item_add_int */
34
35 #include <assert.h> /* for assert */
36 #include <errno.h>
37 #include <stdio.h> /* for fopen */
38 #include <stdlib.h> /* for atoi */
39 #include <string.h> /* for strcmp */
40 #include <sys/stat.h> /* for stat, st_mtime */
41 #include <time.h> /* for time, time_t */
42
43 #undef G_LOG_DOMAIN
44 /**
45 * @brief GLib logging domain.
46 */
47 #define G_LOG_DOMAIN "libgvm util"
48
49 char *src_path = NULL; /**< The directory of the source files. */
50 kb_t cache_kb = NULL; /**< Cache KB handler. */
51 int cache_saved = 1; /**< If cache was saved. */
52
53 /**
54 * @brief Return whether the nvt cache is initialized.
55 *
56 * @return 1 if cache is initialized, 0 otherwise.
57 */
58 int
nvticache_initialized(void)59 nvticache_initialized (void)
60 {
61 return !!cache_kb;
62 }
63
64 /**
65 * @brief Initializes the nvti cache.
66 *
67 * @param src The directory that contains the nvt files.
68 * @param kb_path Path to kb socket.
69 *
70 * @return 0 in case of success, anything else indicates an error.
71 */
72 int
nvticache_init(const char * src,const char * kb_path)73 nvticache_init (const char *src, const char *kb_path)
74 {
75 assert (src);
76
77 if (src_path)
78 g_free (src_path);
79 src_path = g_strdup (src);
80 if (cache_kb)
81 kb_lnk_reset (cache_kb);
82 cache_kb = kb_find (kb_path, NVTICACHE_STR);
83 if (cache_kb)
84 return 0;
85
86 if (kb_new (&cache_kb, kb_path)
87 || kb_item_set_str (cache_kb, NVTICACHE_STR, "0", 0))
88 return -1;
89 return 0;
90 }
91
92 /**
93 * @brief Return the nvticache kb.
94 *
95 * @return Cache kb.
96 */
97 kb_t
nvticache_get_kb(void)98 nvticache_get_kb (void)
99 {
100 assert (cache_kb);
101 return cache_kb;
102 }
103
104 /**
105 * @brief Check if the nvt for the given filename exists in cache.
106 *
107 * @param filename The name of the original NVT without the path
108 * to the base location of NVTs (e.g.
109 * "scriptname1.nasl" or even
110 * "subdir1/subdir2/scriptname2.nasl" )
111 *
112 * @return 1 if nvt is in cache and up to date, 0 otherwise.
113 */
114 int
nvticache_check(const gchar * filename)115 nvticache_check (const gchar *filename)
116 {
117 assert (cache_kb);
118 char *src_file, *time_s;
119 struct stat src_stat;
120 int ret = 0;
121
122 src_file = g_build_filename (src_path, filename, NULL);
123 time_s = kb_nvt_get (cache_kb, filename, NVT_TIMESTAMP_POS);
124 if (time_s && src_file && stat (src_file, &src_stat) >= 0
125 && atoi (time_s) > src_stat.st_mtime)
126 ret = 1;
127 g_free (time_s);
128 g_free (src_file);
129 return ret;
130 }
131
132 /**
133 * @brief Reset connection to KB. To be called after a fork().
134 */
135 void
nvticache_reset()136 nvticache_reset ()
137 {
138 if (cache_kb)
139 kb_lnk_reset (cache_kb);
140 }
141
142 /**
143 * @brief Determine the version of the NVT feed.
144 *
145 * @return Feed version string if success, NULL otherwise.
146 */
147 static char *
nvt_feed_version()148 nvt_feed_version ()
149 {
150 char filename[2048], *fcontent = NULL, *plugin_set;
151 GError *error = NULL;
152 static int msg_shown = 0;
153
154 g_snprintf (filename, sizeof (filename), "%s/plugin_feed_info.inc", src_path);
155 if (!g_file_get_contents (filename, &fcontent, NULL, &error))
156 {
157 if (error && msg_shown == 0)
158 {
159 g_warning ("nvt_feed_version: %s", error->message);
160 msg_shown = 1;
161 }
162 g_error_free (error);
163 return NULL;
164 }
165 plugin_set = g_strrstr (fcontent, "PLUGIN_SET = ");
166 if (!plugin_set)
167 {
168 g_warning ("nvt_feed_version: Erroneous %s format", filename);
169 g_free (fcontent);
170 return NULL;
171 }
172 msg_shown = 0;
173 plugin_set = g_strndup (plugin_set + 14, 12);
174 if (g_strstr_len (plugin_set, -1, "\"") || g_strstr_len (plugin_set, -1, ";"))
175 {
176 g_warning ("nvt_feed_version: Erroneous %s format. Format of PLUGIN_SET "
177 "has to be yyyymmddhhmm. It has to be exactly 12 chars long.",
178 filename);
179 g_free (plugin_set);
180 g_free (fcontent);
181 return NULL;
182 }
183
184 g_free (fcontent);
185 return plugin_set;
186 }
187
188 /**
189 * @brief Save the nvticache to disk.
190 */
191 void
nvticache_save()192 nvticache_save ()
193 {
194 char *feed_version, *old_version;
195 if (cache_kb && !cache_saved)
196 {
197 kb_save (cache_kb);
198 cache_saved = 1;
199 }
200 old_version = nvticache_feed_version ();
201 feed_version = nvt_feed_version ();
202 if (feed_version && g_strcmp0 (old_version, feed_version))
203 {
204 kb_item_set_str (cache_kb, NVTICACHE_STR, feed_version, 0);
205 g_message ("Updated NVT cache from version %s to %s", old_version,
206 feed_version);
207 }
208 g_free (old_version);
209 g_free (feed_version);
210 }
211
212 /**
213 * @brief Add a NVT Information to the cache.
214 *
215 * @param nvti The NVT Information to add
216 *
217 * @param filename The name of the original NVT without the path
218 * to the base location of NVTs (e.g.
219 * "scriptname1.nasl" or even
220 * "subdir1/subdir2/scriptname2.nasl" )
221 *
222 * @return 0 in case of success, anything else indicates an error.
223 */
224 int
nvticache_add(const nvti_t * nvti,const char * filename)225 nvticache_add (const nvti_t *nvti, const char *filename)
226 {
227 char *oid, *dummy;
228
229 assert (cache_kb);
230 /* Check for duplicate OID. */
231 oid = nvti_oid (nvti);
232 dummy = nvticache_get_filename (oid);
233 if (dummy && strcmp (filename, dummy))
234 {
235 struct stat src_stat;
236 char *src_file = g_build_filename (src_path, dummy, NULL);
237
238 /* If .nasl file was duplicated, not moved. */
239 if (src_file && stat (src_file, &src_stat) >= 0)
240 g_warning ("NVT %s with duplicate OID %s will be replaced with %s",
241 src_file, oid, filename);
242 g_free (src_file);
243 }
244 if (dummy)
245 nvticache_delete (oid);
246
247 g_free (dummy);
248
249 if (kb_nvt_add (cache_kb, nvti, filename))
250 goto kb_fail;
251 cache_saved = 0;
252
253 return 0;
254 kb_fail:
255 return -1;
256 }
257
258 /**
259 * @brief Get the full source filename of an OID.
260 *
261 * @param oid The OID to look up.
262 *
263 * @return Filename with full path matching OID if found, NULL otherwise.
264 */
265 char *
nvticache_get_src(const char * oid)266 nvticache_get_src (const char *oid)
267 {
268 char *filename, *src;
269
270 assert (cache_kb);
271
272 filename = kb_nvt_get (cache_kb, oid, NVT_FILENAME_POS);
273 if (!filename)
274 return NULL;
275 src = g_build_filename (src_path, filename, NULL);
276 g_free (filename);
277 return src;
278 }
279
280 /**
281 * @brief Get the OID from a plugin filename.
282 *
283 * @param filename Filename to lookup.
284 *
285 * @return OID matching filename if found, NULL otherwise.
286 */
287 char *
nvticache_get_oid(const char * filename)288 nvticache_get_oid (const char *filename)
289 {
290 assert (cache_kb);
291
292 return kb_nvt_get (cache_kb, filename, NVT_OID_POS);
293 }
294
295 /**
296 * @brief Get the filename from a plugin OID.
297 *
298 * @param[in] oid OID to match.
299 *
300 * @return Filanem matching OID, NULL otherwise.
301 */
302 char *
nvticache_get_filename(const char * oid)303 nvticache_get_filename (const char *oid)
304 {
305 assert (cache_kb);
306 return kb_nvt_get (cache_kb, oid, NVT_FILENAME_POS);
307 }
308
309 /**
310 * @brief Get the Required Keys from a plugin OID.
311 *
312 * @param[in] oid OID to match.
313 *
314 * @return Required Keys matching OID, NULL otherwise.
315 */
316 char *
nvticache_get_required_keys(const char * oid)317 nvticache_get_required_keys (const char *oid)
318 {
319 assert (cache_kb);
320 return kb_nvt_get (cache_kb, oid, NVT_REQUIRED_KEYS_POS);
321 }
322
323 /**
324 * @brief Get the Mandatory Keys from a plugin OID.
325 *
326 * @param[in] oid OID to match.
327 *
328 * @return Mandatory Keys matching OID, NULL otherwise.
329 */
330 char *
nvticache_get_mandatory_keys(const char * oid)331 nvticache_get_mandatory_keys (const char *oid)
332 {
333 assert (cache_kb);
334 return kb_nvt_get (cache_kb, oid, NVT_MANDATORY_KEYS_POS);
335 }
336
337 /**
338 * @brief Get the Excluded Keys from a plugin OID.
339 *
340 * @param[in] oid OID to match.
341 *
342 * @return Excluded Keys matching OID, NULL otherwise.
343 */
344 char *
nvticache_get_excluded_keys(const char * oid)345 nvticache_get_excluded_keys (const char *oid)
346 {
347 assert (cache_kb);
348 return kb_nvt_get (cache_kb, oid, NVT_EXCLUDED_KEYS_POS);
349 }
350
351 /**
352 * @brief Get the Required udp ports from a plugin OID.
353 *
354 * @param[in] oid OID to match.
355 *
356 * @return Required udp ports matching OID, NULL otherwise.
357 */
358 char *
nvticache_get_required_udp_ports(const char * oid)359 nvticache_get_required_udp_ports (const char *oid)
360 {
361 assert (cache_kb);
362 return kb_nvt_get (cache_kb, oid, NVT_REQUIRED_UDP_PORTS_POS);
363 }
364
365 /**
366 * @brief Get the Required ports from a plugin OID.
367 *
368 * @param[in] oid OID to match.
369 *
370 * @return Required ports matching OID, NULL otherwise.
371 */
372 char *
nvticache_get_required_ports(const char * oid)373 nvticache_get_required_ports (const char *oid)
374 {
375 assert (cache_kb);
376 return kb_nvt_get (cache_kb, oid, NVT_REQUIRED_PORTS_POS);
377 }
378
379 /**
380 * @brief Get the Dependencies from a plugin OID.
381 *
382 * @param[in] oid OID to match.
383 *
384 * @return Dependencies matching OID, NULL otherwise.
385 */
386 char *
nvticache_get_dependencies(const char * oid)387 nvticache_get_dependencies (const char *oid)
388 {
389 assert (cache_kb);
390 return kb_nvt_get (cache_kb, oid, NVT_DEPENDENCIES_POS);
391 }
392
393 /**
394 * @brief Get the Category from a plugin OID.
395 *
396 * @param[in] oid OID to match.
397 *
398 * @return Category matching OID, -1 otherwise.
399 */
400 int
nvticache_get_category(const char * oid)401 nvticache_get_category (const char *oid)
402 {
403 int category;
404 char *category_s;
405
406 assert (cache_kb);
407 category_s = kb_nvt_get (cache_kb, oid, NVT_CATEGORY_POS);
408 category = atoi (category_s);
409 g_free (category_s);
410 return category;
411 }
412
413 /**
414 * @brief Get the Timeout from a plugin OID.
415 *
416 * @param[in] oid OID to match.
417 *
418 * @return Timeout matching OID, -1 otherwise.
419 */
420 int
nvticache_get_timeout(const char * oid)421 nvticache_get_timeout (const char *oid)
422 {
423 int timeout;
424 char *timeout_s;
425
426 assert (cache_kb);
427 timeout_s = kb_nvt_get (cache_kb, oid, NVT_TIMEOUT_POS);
428 timeout = atoi (timeout_s);
429 g_free (timeout_s);
430 return timeout;
431 }
432
433 /**
434 * @brief Get the name from a plugin OID.
435 *
436 * @param[in] oid OID to match.
437 *
438 * @return Name matching OID, NULL otherwise.
439 */
440 char *
nvticache_get_name(const char * oid)441 nvticache_get_name (const char *oid)
442 {
443 assert (cache_kb);
444 return kb_nvt_get (cache_kb, oid, NVT_NAME_POS);
445 }
446
447 /**
448 * @brief Get the cves from a plugin OID.
449 *
450 * @param[in] oid OID to match.
451 *
452 * @return CVEs matching OID, NULL otherwise.
453 */
454 char *
nvticache_get_cves(const char * oid)455 nvticache_get_cves (const char *oid)
456 {
457 assert (cache_kb);
458 return kb_nvt_get (cache_kb, oid, NVT_CVES_POS);
459 }
460
461 /**
462 * @brief Get the bids from a plugin OID.
463 *
464 * @param[in] oid OID to match.
465 *
466 * @return BIDs matching OID, NULL otherwise.
467 */
468 char *
nvticache_get_bids(const char * oid)469 nvticache_get_bids (const char *oid)
470 {
471 assert (cache_kb);
472 return kb_nvt_get (cache_kb, oid, NVT_BIDS_POS);
473 }
474
475 /**
476 * @brief Get the xrefs from a plugin OID.
477 *
478 * @param[in] oid OID to match.
479 *
480 * @return XREFs matching OID, NULL otherwise.
481 */
482 char *
nvticache_get_xrefs(const char * oid)483 nvticache_get_xrefs (const char *oid)
484 {
485 assert (cache_kb);
486 return kb_nvt_get (cache_kb, oid, NVT_XREFS_POS);
487 }
488
489 /**
490 * @brief Get the family from a plugin OID.
491 *
492 * @param[in] oid OID to match.
493 *
494 * @return Family matching OID, NULL otherwise.
495 */
496 char *
nvticache_get_family(const char * oid)497 nvticache_get_family (const char *oid)
498 {
499 assert (cache_kb);
500 return kb_nvt_get (cache_kb, oid, NVT_FAMILY_POS);
501 }
502
503 /**
504 * @brief Get the tags from a plugin OID.
505 *
506 * @param[in] oid OID to match.
507 *
508 * @return Tags matching OID, NULL otherwise.
509 */
510 char *
nvticache_get_tags(const char * oid)511 nvticache_get_tags (const char *oid)
512 {
513 assert (cache_kb);
514 return kb_nvt_get (cache_kb, oid, NVT_TAGS_POS);
515 }
516
517 /**
518 * @brief Get the nvti from a plugin OID.
519 *
520 * @param[in] oid OID to match.
521 *
522 * @return Full nvti matching OID, NULL otherwise.
523 */
524 nvti_t *
nvticache_get_nvt(const char * oid)525 nvticache_get_nvt (const char *oid)
526 {
527 assert (cache_kb);
528 return kb_nvt_get_all (cache_kb, oid);
529 }
530
531 /**
532 * @brief Get the prefs from a plugin OID.
533 *
534 * @param[in] oid OID to match.
535 *
536 * @return Prefs matching OID, NULL otherwise.
537 */
538 GSList *
nvticache_get_prefs(const char * oid)539 nvticache_get_prefs (const char *oid)
540 {
541 char pattern[4096];
542 struct kb_item *prefs, *element;
543 GSList *list = NULL;
544
545 assert (cache_kb);
546
547 g_snprintf (pattern, sizeof (pattern), "oid:%s:prefs", oid);
548 prefs = element = kb_item_get_all (cache_kb, pattern);
549 while (element)
550 {
551 nvtpref_t *np;
552 char **array = g_strsplit (element->v_str, "|||", -1);
553
554 assert (array[3]);
555 assert (!array[4]);
556 np = nvtpref_new (atoi (array[0]), array[1], array[2], array[3]);
557 g_strfreev (array);
558 list = g_slist_append (list, np);
559 element = element->next;
560 }
561 kb_item_free (prefs);
562
563 return list;
564 }
565
566 /**
567 * @brief Get the list of nvti OIDs.
568 *
569 * @return OIDs list.
570 */
571 GSList *
nvticache_get_oids()572 nvticache_get_oids ()
573 {
574 assert (cache_kb);
575
576 return kb_nvt_get_oids (cache_kb);
577 }
578
579 /**
580 * @brief Get the number of nvt's in the cache.
581 *
582 * @return Number of nvt's.
583 */
584 size_t
nvticache_count()585 nvticache_count ()
586 {
587 assert (cache_kb);
588
589 return kb_item_count (cache_kb, "nvt:*");
590 }
591
592 /**
593 * @brief Delete NVT from the cache.
594 *
595 * @param[in] oid OID to match.
596 */
597 void
nvticache_delete(const char * oid)598 nvticache_delete (const char *oid)
599 {
600 char pattern[4096];
601 char *filename;
602
603 assert (cache_kb);
604 assert (oid);
605
606 filename = nvticache_get_filename (oid);
607 g_snprintf (pattern, sizeof (pattern), "oid:%s:prefs", oid);
608 kb_del_items (cache_kb, pattern);
609 g_snprintf (pattern, sizeof (pattern), "nvt:%s", oid);
610 kb_del_items (cache_kb, pattern);
611
612 if (filename)
613 {
614 g_snprintf (pattern, sizeof (pattern), "filename:%s", filename);
615 kb_del_items (cache_kb, pattern);
616 }
617 g_free (filename);
618 }
619
620 /**
621 * @brief Get the NVT feed version.
622 *
623 * @return Feed version.
624 */
625 char *
nvticache_feed_version(void)626 nvticache_feed_version (void)
627 {
628 return kb_item_get_str (cache_kb, NVTICACHE_STR);
629 }
630
631 /**
632 * @brief Check if the plugins feed was newer than cached feed.
633 *
634 * @return 1 if new feed, 0 if matching feeds or error.
635 */
636 int
nvticache_check_feed(void)637 nvticache_check_feed (void)
638 {
639 char *cached, *current;
640 int ret;
641
642 if (!(current = nvt_feed_version ()))
643 return 0;
644 cached = kb_item_get_str (cache_kb, NVTICACHE_STR);
645 ret = strcmp (cached, current);
646 g_free (cached);
647 g_free (current);
648 return ret;
649 }
650