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