Commit 29110260 authored by Sophie Brun's avatar Sophie Brun

New upstream version 9.0.2

parent 796d2f29
version: 2
jobs:
build:
docker:
- image: wiegandm/openvas-libraries-9.0-core-debian-jessie
steps:
- checkout
- run:
name: Configure and Compile
command: mkdir build && cd build/ && cmake -DCMAKE_BUILD_TYPE=Release .. && make install
openvas-libraries 9.0.2 (2018-03-07)
This is the second maintenance release of the openvas-libraries 9.0
module for the Open Vulnerability Assessment System 9 (OpenVAS-9).
Many thanks to everyone who contributed to this release:
Hani Benhabiles, Francesco Colista, Juan Jose Nicola, Timo Pollmeier and Björn
Ricks, Michael Wiegand, Jan-Oliver Wagner, Matt Mundell and Albrecht Dreß.
Main changes compared to 9.0.1:
* Several memory management issues have been addressed.
* NASL cryptography support has been updated.
* Signature handling has been improved.
* Child process signal handling has been improved.
* Support for retrieving the prompt during keyboard-interactive SSH
authentication has been added.
* An issue which caused a segmentation fault in the NASL command
'get_port_state' under certain circumstances has been addressed.
* An issue which caused incorrect NTLMSSP hashes under certain circumstances has
been addressed.
* Handling of connections closed by the client has been improved.
* The default connection timeout when detecting services has been increased.
* The handling of a number of frequently requested knowledge base keys has been
improved.
* More context to NVT/NASL related log messages has been added.
* An issue which caused an error during close() call on UDP sockets from a NASL
script has been addressed.
* Support for retrieving vendor version information through a NASL command has
been added.
* Handling of SIGPIPE from hiredis in case of a socket disconnect has been added.
* Handling of Redis connection error has been improved.
* An issue which caused several running processes on scanned host under
certain circumstances has been addressed.
* Support for ldap search during the authentication process has been added.
* Simplify scanner signatures verification. NVT's detached signatures were
replaced with a digitally signed file with the hash list of the NVTs.
* Full nvticache has been moved from .nvti files to Redis
* Support for radcli library has been added.
* Cleanup and handle of the kb content has been improved.
openvas-libraries 9.0.1 (2017-03-07)
This is the first maintenance release of the openvas-libraries 9.0
......
......@@ -96,7 +96,7 @@ set (CPACK_PACKAGE_VERSION_MAJOR "9")
set (CPACK_PACKAGE_VERSION_MINOR "0")
# Use this scheme for stable releases:
set (CPACK_PACKAGE_VERSION_PATCH "1${SVN_REVISION}")
set (CPACK_PACKAGE_VERSION_PATCH "2${SVN_REVISION}")
set (CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
# Use this scheme for +betaN and +rcN releases:
#set (CPACK_PACKAGE_VERSION_PATCH "+beta1${SVN_REVISION}")
......
This diff is collapsed.
......@@ -29,6 +29,8 @@
#include <assert.h>
#include "../base/nvti.h" /* for nvti_t */
/**
* @brief Default KB location.
*
......@@ -49,6 +51,29 @@ enum kb_item_type {
KB_TYPE_CNT,
};
/**
* @brief Possible positions of nvt values in cache list.
*/
enum kb_nvt_pos {
NVT_FILENAME_POS,
NVT_REQUIRED_KEYS_POS,
NVT_MANDATORY_KEYS_POS,
NVT_EXCLUDED_KEYS_POS,
NVT_REQUIRED_UDP_PORTS_POS,
NVT_REQUIRED_PORTS_POS,
NVT_DEPENDENCIES_POS,
NVT_TAGS_POS,
NVT_CVES_POS,
NVT_BIDS_POS,
NVT_XREFS_POS,
NVT_CATEGORY_POS,
NVT_TIMEOUT_POS,
NVT_FAMILY_POS,
NVT_COPYRIGHT_POS,
NVT_NAME_POS,
NVT_VERSION_POS,
};
/**
* @brief Knowledge base item (defined by name, type (int/char*) and value).
* Implemented as a singly linked list
......@@ -95,22 +120,25 @@ struct kb_operations
/* ctor/dtor */
int (*kb_new) (kb_t *, const char *);
int (*kb_delete) (kb_t);
kb_t (*kb_find) (const char *, const char *);
/* Actual kb operations */
struct kb_item *(*kb_get_single) (kb_t, const char *, enum kb_item_type);
char *(*kb_get_str) (kb_t, const char *);
int (*kb_get_int) (kb_t, const char *);
char *(*kb_get_nvt) (kb_t, const char *, enum kb_nvt_pos);
struct kb_item * (*kb_get_all) (kb_t, const char *);
struct kb_item * (*kb_get_pattern) (kb_t, const char *);
int (*kb_add_str) (kb_t, const char *, const char *);
int (*kb_set_str) (kb_t, const char *, const char *);
int (*kb_add_int) (kb_t, const char *, int);
int (*kb_set_int) (kb_t, const char *, int);
int (*kb_add_nvt) (kb_t, const nvti_t *, const char *);
int (*kb_del_items) (kb_t, const char *);
/* Utils */
int (*kb_lnk_reset) (kb_t);
int (*kb_flush) (kb_t);
int (*kb_flush) (kb_t, const char *);
};
/**
......@@ -142,6 +170,54 @@ static inline int kb_new (kb_t *kb, const char *kb_path)
return KBDefaultOperations->kb_new (kb, kb_path);
}
/**
* @brief Find an existing Knowledge Base object with key.
* @param[in] kb_path Path to KB.
* @param[in] key Marker key to search for in KB objects.
* @return Knowledge Base object, NULL otherwise.
*/
static inline kb_t kb_find (const char *kb_path, const char *key)
{
assert (KBDefaultOperations);
assert (KBDefaultOperations->kb_find);
return KBDefaultOperations->kb_find (kb_path, key);
}
/**
* @brief Insert a new nvt.
* @param[in] kb KB handle where to store the nvt.
* @param[in] nvt nvt to store.
* @param[in] filename Path to nvt to store.
* @return 0 on success, non-null on error.
*/
static inline int
kb_nvt_add (kb_t kb, const nvti_t *nvt, const char *filename)
{
assert (kb);
assert (kb->kb_ops);
assert (kb->kb_ops->kb_add_nvt);
return kb->kb_ops->kb_add_nvt (kb, nvt, filename);
}
/**
* @brief Get field of a NVT.
* @param[in] kb KB handle where to store the nvt.
* @param[in] oid OID of NVT to get from.
* @param[in] field Name of field to get.
* @return Value of field, NULL otherwise.
*/
static inline char *
kb_nvt_get (kb_t kb, const char *oid, enum kb_nvt_pos position)
{
assert (kb);
assert (kb->kb_ops);
assert (kb->kb_ops->kb_add_nvt);
return kb->kb_ops->kb_get_nvt (kb, oid, position);
}
/**
* @brief Delete all entries and release ownership on the namespace.
* @param[in] kb KB handle to release.
......@@ -347,10 +423,11 @@ static inline int kb_lnk_reset (kb_t kb)
/**
* @brief Flush all the KB's content. Delete all namespaces.
* @param[in] kb KB handle.
* @param[in] kb KB handle.
* @param[in] except Don't flush DB with except key.
* @return 0 on success, non-null on error.
*/
static inline int kb_flush (kb_t kb)
static inline int kb_flush (kb_t kb, const char *except)
{
int rc = 0;
......@@ -358,7 +435,7 @@ static inline int kb_flush (kb_t kb)
assert (kb->kb_ops);
if (kb->kb_ops->kb_flush != NULL)
rc = kb->kb_ops->kb_flush (kb);
rc = kb->kb_ops->kb_flush (kb, except);
return rc;
}
......
......@@ -95,7 +95,7 @@ struct redis_tx
static int redis_delete_all (struct kb_redis *);
static int redis_lnk_reset (kb_t);
static int redis_flush_all (kb_t);
static int redis_flush_all (kb_t, const char *);
static redisReply *redis_cmd (struct kb_redis *kbr, const char *fmt, ...)
__attribute__((__format__(__printf__, 2, 3)));
......@@ -443,6 +443,60 @@ redis_new (kb_t *kb, const char *kb_path)
return rc;
}
static kb_t
redis_find (const char *kb_path, const char *key)
{
struct kb_redis *kbr;
unsigned int i = 1;
redisReply *rep;
kbr = g_malloc0 (sizeof (struct kb_redis) + strlen (kb_path) + 1);
kbr->kb.kb_ops = &KBRedisOperations;
strncpy (kbr->path, kb_path, strlen (kb_path));
do
{
kbr->rctx = redisConnectUnix (kbr->path);
if (kbr->rctx == NULL || kbr->rctx->err)
{
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"%s: redis connection error: %s", __func__,
kbr->rctx ? kbr->rctx->errstr : strerror (ENOMEM));
redisFree (kbr->rctx);
g_free (kbr);
return NULL;
}
kbr->db = i;
rep = redisCommand (kbr->rctx, "HEXISTS %s %d", GLOBAL_DBINDEX_NAME, i);
if (rep == NULL || rep->type != REDIS_REPLY_INTEGER || rep->integer != 1)
{
if (rep != NULL)
freeReplyObject (rep);
i++;
continue;
}
freeReplyObject (rep);
rep = redisCommand (kbr->rctx, "SELECT %u", i);
if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
{
sleep (KB_RETRY_DELAY);
kbr->rctx = NULL;
}
else
{
freeReplyObject (rep);
if (key && kb_item_get_int (&kbr->kb, key) > 0)
return (kb_t) kbr;
}
redisFree (kbr->rctx);
i++;
}
while (i < kbr->max_db);
return NULL;
}
void
kb_item_free (struct kb_item *item)
{
......@@ -740,6 +794,26 @@ redis_get_int (kb_t kb, const char *name)
return -1;
}
static char *
redis_get_nvt (kb_t kb, const char *oid, enum kb_nvt_pos position)
{
struct kb_redis *kbr;
redisReply *rep;
char *res = NULL;
kbr = redis_kb (kb);
rep = redis_cmd (kbr, "LINDEX nvt:%s %d", oid, position);
if (!rep)
return NULL;
if (rep->type == REDIS_REPLY_INTEGER)
res = g_strdup_printf ("%lld", rep->integer);
else if (rep->type == REDIS_REPLY_STRING)
res = g_strdup (rep->str);
freeReplyObject (rep);
return res;
}
static struct kb_item *
redis_get_all (kb_t kb, const char *name)
{
......@@ -952,6 +1026,44 @@ out:
return rc;
}
static int
redis_add_nvt (kb_t kb, const nvti_t *nvt, const char *filename)
{
struct kb_redis *kbr;
redisReply *rep = NULL;
int rc = 0;
if (!nvt || !filename)
return -1;
kbr = redis_kb (kb);
rep = redis_cmd (kbr,
"RPUSH nvt:%s %s %s %s %s %s %s %s %s %s %s %s %d %d %s %s"
" %s %s",
nvti_oid (nvt), filename, nvti_required_keys (nvt) ?: "",
nvti_mandatory_keys (nvt) ?: "",
nvti_excluded_keys (nvt) ?: "",
nvti_required_udp_ports (nvt) ?: "",
nvti_required_keys (nvt) ?: "",
nvti_dependencies (nvt) ?: "", nvti_tag (nvt) ?: "",
nvti_cve (nvt) ?: "", nvti_bid (nvt) ?: "",
nvti_xref (nvt) ?: "", nvti_category (nvt),
nvti_timeout (nvt), nvti_family (nvt), nvti_copyright (nvt),
nvti_name (nvt), nvti_version (nvt));
if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
rc = -1;
if (rep != NULL)
freeReplyObject (rep);
rep = redis_cmd (kbr, "SADD filename:%s:oid %s", filename, nvti_oid (nvt));
if (rep == NULL || rep->type == REDIS_REPLY_ERROR)
rc = -1;
if (rep != NULL)
freeReplyObject (rep);
return rc;
}
static int
redis_lnk_reset (kb_t kb)
{
......@@ -969,30 +1081,68 @@ redis_lnk_reset (kb_t kb)
}
static int
redis_flush_all (kb_t kb)
redis_flush_all (kb_t kb, const char *except)
{
int rc;
unsigned int i = 1;
struct kb_redis *kbr;
redisReply *rep;
kbr = redis_kb (kb);
if (kbr->rctx)
redisFree (kbr->rctx);
g_debug ("%s: deleting all DBs at %s", __func__, kbr->path);
rep = redis_cmd (kbr, "FLUSHALL");
if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
g_debug ("%s: deleting all DBs at %s except %s", __func__, kbr->path, except);
do
{
rc = -1;
goto err_cleanup;
}
rc = 0;
kbr->rctx = redisConnectUnix (kbr->path);
if (kbr->rctx == NULL || kbr->rctx->err)
{
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"%s: redis connection error: %s", __func__,
kbr->rctx ? kbr->rctx->errstr : strerror (ENOMEM));
redisFree (kbr->rctx);
kbr->rctx = NULL;
return -1;
}
err_cleanup:
if (rep != NULL)
freeReplyObject (rep);
kbr->db = i;
rep = redisCommand (kbr->rctx, "HEXISTS %s %d", GLOBAL_DBINDEX_NAME, i);
if (rep == NULL || rep->type != REDIS_REPLY_INTEGER || rep->integer != 1)
{
freeReplyObject (rep);
redisFree (kbr->rctx);
i++;
continue;
}
freeReplyObject (rep);
rep = redisCommand (kbr->rctx, "SELECT %u", i);
if (rep == NULL || rep->type != REDIS_REPLY_STATUS)
{
freeReplyObject (rep);
sleep (KB_RETRY_DELAY);
redisFree (kbr->rctx);
kbr->rctx = NULL;
}
else
{
freeReplyObject (rep);
/* Don't remove DB if it has "except" key. */
if (except && kb_item_get_int (kb, except) > 0)
{
i++;
redisFree (kbr->rctx);
continue;
}
redis_delete_all (kbr);
redis_release_db (kbr);
redisFree (kbr->rctx);
}
i++;
}
while (i < kbr->max_db);
return rc;
g_free (kb);
return 0;
}
int
......@@ -1000,6 +1150,15 @@ redis_delete_all (struct kb_redis *kbr)
{
int rc;
redisReply *rep;
struct sigaction new_action, original_action;
/* Ignore SIGPIPE, in case of a lost connection. */
new_action.sa_flags = 0;
if (sigemptyset (&new_action.sa_mask))
return -1;
new_action.sa_handler = SIG_IGN;
if (sigaction (SIGPIPE, &new_action, &original_action))
return -1;
g_debug ("%s: deleting all elements from KB #%u", __func__, kbr->db);
rep = redis_cmd (kbr, "FLUSHDB");
......@@ -1012,6 +1171,8 @@ redis_delete_all (struct kb_redis *kbr)
rc = 0;
err_cleanup:
if (sigaction (SIGPIPE, &original_action, NULL))
return -1;
if (rep != NULL)
freeReplyObject (rep);
......@@ -1021,16 +1182,19 @@ err_cleanup:
static const struct kb_operations KBRedisOperations = {
.kb_new = redis_new,
.kb_find = redis_find,
.kb_delete = redis_delete,
.kb_get_single = redis_get_single,
.kb_get_str = redis_get_str,
.kb_get_int = redis_get_int,
.kb_get_nvt = redis_get_nvt,
.kb_get_all = redis_get_all,
.kb_get_pattern = redis_get_pattern,
.kb_add_str = redis_add_str,
.kb_set_str = redis_set_str,
.kb_add_int = redis_add_int,
.kb_set_int = redis_set_int,
.kb_add_nvt = redis_add_nvt,
.kb_del_items = redis_del_items,
.kb_lnk_reset = redis_lnk_reset,
.kb_flush = redis_flush_all,
......
......@@ -1115,255 +1115,6 @@ nvti_add_pref (nvti_t * n, nvtpref_t * np)
return (0);
}
/**
* @brief Read NVT Info from a keyfile.
*
* @param keyfile Keyfile.
* @param name Key name.
* @param nvti NVTI.
* @param set Set function.
*/
static void
set_from_key (GKeyFile *keyfile, const gchar *name,
nvti_t *nvti, int set (nvti_t * n, const gchar * oid))
{
gchar *utf8;
utf8 = g_key_file_get_string (keyfile, "NVT Info", name, NULL);
if (utf8)
{
gsize size;
gchar *iso;
iso = g_convert (utf8, -1, "ISO_8859-1", "UTF-8", NULL, &size, NULL);
set (nvti, iso);
g_free (iso);
g_free (utf8);
}
}
/**
* @brief Read NVT Info from a keyfile.
*
* @param fn The filename to read from.
*
* @return A newly allocated nvti_t object.
* The nvti_t needs to be freed with nvti_free().
*/
nvti_t *
nvti_from_keyfile (const gchar * fn)
{
GKeyFile *keyfile = g_key_file_new ();
nvti_t *n;
GError *error = NULL;
gchar **keys;
int i;
if (!g_key_file_load_from_file (keyfile, fn, G_KEY_FILE_NONE, &error))
{
g_warning ("%s: %s", fn, error->message);
return NULL;
}
n = nvti_new ();
set_from_key (keyfile, "OID", n, nvti_set_oid);
set_from_key (keyfile, "Version", n, nvti_set_version);
set_from_key (keyfile, "Name", n, nvti_set_name);
set_from_key (keyfile, "Copyright", n, nvti_set_copyright);
set_from_key (keyfile, "CVEs", n, nvti_set_cve);
set_from_key (keyfile, "BIDs", n, nvti_set_bid);
set_from_key (keyfile, "XREFs", n, nvti_set_xref);
set_from_key (keyfile, "Tags", n, nvti_set_tag);
set_from_key (keyfile, "Dependencies", n, nvti_set_dependencies);
set_from_key (keyfile, "RequiredKeys", n, nvti_set_required_keys);
set_from_key (keyfile, "MandatoryKeys", n, nvti_set_mandatory_keys);
set_from_key (keyfile, "ExcludedKeys", n, nvti_set_excluded_keys);
set_from_key (keyfile, "RequiredPorts", n, nvti_set_required_ports);
set_from_key (keyfile, "RequiredUDPPorts", n, nvti_set_required_udp_ports);
set_from_key (keyfile, "Family", n, nvti_set_family);
nvti_set_timeout (n,
g_key_file_get_integer (keyfile, "NVT Info", "Timeout",
NULL));
nvti_set_category (n,
g_key_file_get_integer (keyfile, "NVT Info", "Category",
NULL));
if (g_key_file_has_group (keyfile, "NVT Prefs"))
{
keys = g_key_file_get_keys (keyfile, "NVT Prefs", NULL, NULL);
for (i = 0; keys[i]; i++)
{
gsize len;
gchar *name, *type, *dflt;
gchar **items =
g_key_file_get_string_list (keyfile, "NVT Prefs", keys[i], &len,
NULL);
if (len != 3)
continue; // format error for this pref.
name = g_convert (items[0], -1, "ISO_8859-1", "UTF-8", NULL, &len,
NULL);
type = g_convert (items[1], -1, "ISO_8859-1", "UTF-8", NULL, &len,
NULL);
dflt = g_convert (items[2], -1, "ISO_8859-1", "UTF-8", NULL, &len,
NULL);
nvtpref_t *np = nvtpref_new (name, type, dflt);
nvti_add_pref (n, np);
g_strfreev (items);
g_free (name);
g_free (type);
g_free (dflt);
}
g_strfreev (keys);
}
g_key_file_free (keyfile);
return (n);
}
/**
* @brief Set value in keyfile.
*
* @param keyfile Keyfile.
* @param name Key name.
* @param value Value.
*/
static void
set_keyfile_info (GKeyFile *keyfile, const gchar *name, const gchar *value)
{
if (value)
{
gsize size;
gchar *utf8;
utf8 = g_convert (value, -1, "UTF-8", "ISO_8859-1", NULL, &size, NULL);
g_key_file_set_string (keyfile, "NVT Info", name, utf8);
g_free (utf8);
}
}
/**
* @brief Store NVT Info into a keyfile.
*
* @param n The NVT Info object to store.
*
* @param fn The filename to write to.
*
* @return 0 on success. @todo Anything else indicates an error.
*/
int
nvti_to_keyfile (const nvti_t * n, const char *src, const gchar *fn)
{
GKeyFile *keyfile = g_key_file_new ();
gchar *text;
GError *error = NULL;
unsigned int i;
set_keyfile_info (keyfile, "OID", n->oid);
set_keyfile_info (keyfile, "Version", n->version);
set_keyfile_info (keyfile, "Name", n->name);
set_keyfile_info (keyfile, "Copyright", n->copyright);
set_keyfile_info (keyfile, "CVEs", n->cve);
set_keyfile_info (keyfile, "BIDs", n->bid);
set_keyfile_info (keyfile, "XREFs", n->xref);
set_keyfile_info (keyfile, "Tags", n->tag);
set_keyfile_info (keyfile, "Dependencies", n->dependencies);
set_keyfile_info (keyfile, "RequiredKeys", n->required_keys);
set_keyfile_info (keyfile, "MandatoryKeys", n->mandatory_keys);
set_keyfile_info (keyfile, "ExcludedKeys", n->excluded_keys);
set_keyfile_info (keyfile, "RequiredPorts", n->required_ports);
set_keyfile_info (keyfile, "RequiredUDPPorts", n->required_udp_ports);
set_keyfile_info (keyfile, "Family", n->family);
if (n->timeout > 0)
g_key_file_set_integer (keyfile, "NVT Info", "Timeout", n->timeout);
if (n->category > 0)
g_key_file_set_integer (keyfile, "NVT Info", "Category", n->category);
for (i = 0; i < nvti_pref_len (n); i++)
{
const nvtpref_t *np = nvti_pref (n, i);
gchar *lst[3];
gchar buf[10];
gsize size;
lst[0] = g_convert (((nvtpref_t *) np)->name, -1, "UTF-8", "ISO_8859-1",
NULL, &size, NULL);
lst[1] = g_convert (((nvtpref_t *) np)->type, -1, "UTF-8", "ISO_8859-1",
NULL, &size, NULL);
lst[2] = g_convert (((nvtpref_t *) np)->dflt, -1, "UTF-8", "ISO_8859-1",
NULL, &size, NULL);
g_snprintf (buf, 10, "P%u", i);
g_key_file_set_string_list ((GKeyFile *) keyfile, "NVT Prefs", buf,
(const gchar **) lst, 3);
// g_key_file_set_string_list((GKeyFile *)keyfile, "NVT Prefs", (gchar *)lst[0], (const gchar **)lst, 3);
g_free (lst[0]);
g_free (lst[1]);
g_free (lst[2]);
}
text = g_key_file_to_data (keyfile, NULL, &error);
if (error != NULL)
{
g_warning ("Error occurred while preparing %s: %s\n", fn, error->message);
g_error_free (error);
}
else
{
FILE *fp = fopen (fn, "w");
if (!fp)
{ // second try: maybe the directory was missing.
gchar *cache_dir = g_path_get_dirname (fn);
if ((g_mkdir_with_parents (cache_dir, 0755) < 0) && (errno != EEXIST))
{
g_warning ("mkdir(%s) : %s\n", cache_dir, strerror (errno));
g_free (cache_dir);
g_free (text);
g_key_file_free (keyfile);
return (1);
}
g_free (cache_dir);
fp = fopen (fn, "w");
}
if (!fp)
{ // again failed
g_warning ("fopen(%s) : %s\n", fn, strerror (errno));
g_free (text);
g_key_file_free (keyfile);
return (2);
}
fputs (text, fp);
fclose (fp);
/* Set timestamp of cache file to the timestamp of the original NVT, if
* possible */
if (src)
{
struct stat src_stat;
if (stat (src, &src_stat) == 0)
{
struct utimbuf src_timestamp;
src_timestamp.actime = src_stat.st_atime;
src_timestamp.modtime = src_stat.st_mtime;
if (utime (fn, &src_timestamp) != 0)
g_warning ("utime(%s) : %s