2012/12/18  <scm-com...@wald.intevation.org>:
> Author: jan
> Date: 2012-12-18 22:31:13 +0100 (Tue, 18 Dec 2012)
> New Revision: 14885
>
> Modified:
>    trunk/openvas-libraries/COPYING
>    trunk/openvas-libraries/ChangeLog
>    trunk/openvas-libraries/base/cvss.c
>    trunk/openvas-libraries/base/cvss.h
> Log:
> * COPYING: Added cvss module.
> * base/cvss.c (cvss_as_str): New.
> * base/cvss.h: Added proto accordingly.

Hello,

I have some concerns regarding this new cvss.c file.

  - It doesn't match the style and coding standards of the codebase.
  - It doesn't leverage the glib functions.
  - The final free(token) seems broken. Unless I miss something we
have the following pattern:
  while (token != NULL)
  { ... }
  free(token); <-- ??
  - Readability is not optimal.

I tried to improve it a bit. Please find a patch attached. If people
prefer this version I can polish the documentation and commit it.

I've added a standalone version (cvss_prog.c) to ease testing. That's
exactly the same file, with a main version to take a cvss base vector
as argv[1] and print out the corresponding score.

Regards

-- 
Henri

Attachment: cvss_cleanup.diff
Description: Binary data

/* openvas-libraries/base
 * $Id$
 * Description: CVSS utility functions
 *
 * Authors:
 * Preeti Subramanian
 *
 * Copyright:
 * Copyright (C) 2012 Greenbone Networks GmbH
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2,
 * or, at your option, any later version as published by the Free
 * Software Foundation
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 */

/**
 * @file cvss.c
 * @brief CVSS utility functions
 *
 * This file contains utitlity functions for handlung CVSS.
 * Namels a calculator for the CVSS base score from a CVSS base
 * vector.
 *
 * The base equation is the foundation of CVSS scoring. The base equation is:
 * BaseScore6 = round_to_1_decimal(((0.6*Impact)+(0.4*Exploitability)–1.5)*f(Impact))
 * Impact = 10.41*(1-(1-ConfImpact)*(1-IntegImpact)*(1-AvailImpact))
 * Exploitability = 20* AccessVector*AccessComplexity*Authentication
 *
 * f(impact)= 0 if Impact=0, 1.176 otherwise
 * AccessVector     = case AccessVector of
 *                       requires local access: 0.395
 *                       adjacent network accessible: 0.646
 *                       network accessible: 1.0
 * AccessComplexity = case AccessComplexity of
 *                       high: 0.35
 *                       medium: 0.61
 *                       low: 0.71
 * Authentication   = case Authentication of
 *                       requires multiple instances of authentication: 0.45
 *                       requires single instance of authentication: 0.56
 *                       requires no authentication: 0.704
 * ConfImpact       = case ConfidentialityImpact of
 *                       none:              0.0
 *                       partial:           0.275
 *                       complete:          0.660
 * IntegImpact      = case IntegrityImpact of
 *                        none:              0.0
 *                        partial:           0.275
 *                        complete:          0.660
 * AvailImpact      = case AvailabilityImpact of
 *                       none:              0.0
 *                       partial:           0.275
 *                       complete:          0.660
 */

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include <glib.h>


/* AccessVector (AV) Constants */
#define AV_NETWORK          1.0
#define AV_ADJACENT_NETWORK 0.646
#define AV_LOCAL            0.395

/* AccessComplexity (AC) Constants */
#define AC_LOW    0.71
#define AC_MEDIUM 0.61
#define AC_HIGH   0.35

/* Authentication (Au) Constants */
#define Au_MULTIPLE_INSTANCES 0.45
#define Au_SINGLE_INSTANCE    0.56
#define Au_NONE               0.704

/* ConfidentialityImpact (C) Constants */
#define C_NONE     0.0
#define C_PARTIAL  0.275
#define C_COMPLETE 0.660

/* IntegrityImpact (I) Constants */
#define I_NONE     0.0
#define I_PARTIAL  0.275
#define I_COMPLETE 0.660

/* AvailabilityImpact (A) Constants */
#define A_NONE     0.0
#define A_PARTIAL  0.275
#define A_COMPLETE 0.660

enum base_metrics { A, I, C, Au, AC, AV };

struct impact_item
{
  const char *name;
  double nvalue;
};

static const struct impact_item impact_map[][3] = {
   [A] = {
       {"N", A_NONE},
       {"P", A_PARTIAL},
       {"C", A_COMPLETE},
   },
   [I] = {
       {"N", I_NONE},
       {"P", I_PARTIAL},
       {"C", I_COMPLETE},
   },
   [C] = {
       {"N", C_NONE},
       {"P", C_PARTIAL},
       {"C", C_COMPLETE},
   },
   [Au] = {
       {"N", Au_NONE},
       {"M", Au_MULTIPLE_INSTANCES},
       {"C", Au_SINGLE_INSTANCE},
   },
   [AV] = {
       {"N", AV_NETWORK},
       {"A", AV_ADJACENT_NETWORK},
       {"L", AV_LOCAL},
   },
   [AC] = {
       {"L", AC_LOW},
       {"M", AC_MEDIUM},
       {"H", AC_HIGH},
   },
};

struct cvss
{
  double conf_impact;
  double integ_impact;
  double avail_impact;
  double access_vector;
  double access_complexity;
  double authentication;
};

/**
 * @brief Determin base metric enumeration from a string.
 *
 * @param str Base metric in string form, for example "A".
 *
 * @return The respective base_metric enumeration for the
 *         string. -1 in case parsing the string failed.
 */
static enum base_metrics
metricname2enum (char * str)
{
 if (g_strcmp0(str, "A") == 0)
   return A;
 else if (g_strcmp0(str, "I") == 0)
   return I;
 else if (g_strcmp0(str, "C") == 0)
   return C;
 else if (g_strcmp0(str, "Au") == 0)
   return Au;
 else if (g_strcmp0(str, "AV") == 0)
   return AV;
 else if (g_strcmp0(str, "AC") == 0)
   return AC;
 return -1;
}

/**
 * @brief Calculate Impact Sub Score.
 *
 * @return The resulting sub score.
 */
static double
get_impact_subscore (const struct cvss *cvss)
{
  return (10.41 * (1 -
                   (1 - cvss->conf_impact) *
                   (1 - cvss->integ_impact) *
                   (1 - cvss->avail_impact)));
}

/**
 * @brief Calculate Exploitability Sub Score.
 *
 * @return The resulting sub score.
 */
static double
get_exploitability_subscore (const struct cvss *cvss)
{
  return (20 * cvss->access_vector *
          cvss->access_complexity * cvss->authentication);
}

static inline int
get_impact_from_str (const char *value, enum base_metrics metric,
                     struct cvss *cvss)
{
  int i;

  for (i = 0; i < 3; i++)
    {
      const struct impact_item *impact;

      impact = &impact_map[metric][i];

      if (g_strcmp0 (impact->name, value) == 0)
        {
          switch (metric)
            {
              case A:
                cvss->avail_impact = impact->nvalue;
                break;

              case I:
                cvss->integ_impact = impact->nvalue;
                break;

              case C:
                cvss->conf_impact = impact->nvalue;
                break;

              case Au:
                cvss->authentication = impact->nvalue;
                break;

              case AV:
                cvss->access_vector = impact->nvalue;
                break;

              case AC:
                cvss->access_complexity = impact->nvalue;
                break;

              default:
                return -1;
            }
          return 0;
        }
    }
  return -1;
}

static double
__get_cvss_score (struct cvss *cvss)
{
  double impact = 1.176;
  double impact_sub;
  double exploitability_sub;

  impact_sub = get_impact_subscore (cvss);
  exploitability_sub = get_exploitability_subscore (cvss);

  if (impact_sub < 0.1)
    impact = 0.0;

  return (((0.6 * impact_sub) + (0.4 * exploitability_sub) - 1.5) * impact);
}

/**
 * @brief Calculate CVSS Score.
 *
 * @param base_metrics Base vector string from which to compute score.
 *
 * @return The resulting score. -1 upon error during parsing.
 */
double
get_cvss_score_from_base_metrics (char *base_metrics)
{
  struct cvss cvss;
  char *token, *base_str;

  memset(&cvss, 0x00, sizeof(struct cvss));

  if (base_metrics == NULL)
    return 0.0;

  base_str = base_metrics = g_strdup_printf ("%s/", base_metrics);

  while ((token = strchr (base_metrics, '/')) != NULL)
    {
      char *token2 = strtok (base_metrics, ":");
      char *metric_name = token2;
      char *metric_value;

      *token++ = '\0';

      if (metric_name == NULL)
        return (double)-1;

      metric_value = strtok (NULL, ":");

      if (metric_value == NULL)
        return (double)-1;

      if (get_impact_from_str (metric_value, metricname2enum (metric_name), &cvss))
        return (double)-1;

      base_metrics = token;
    }

  free(base_str);

  return __get_cvss_score(&cvss);
}

int main(int ac, char **av) {
  if (ac < 2)
    {
      fprintf(stderr, "Usage: %s <CVSS base vector>\n", av[0]);
      return 1;
    }

  printf("CVSS for %s => %.03f\n", av[1], get_cvss_score_from_base_metrics(av[1]));
  return 0;
}

_______________________________________________
Openvas-devel mailing list
Openvas-devel@wald.intevation.org
https://lists.wald.intevation.org/cgi-bin/mailman/listinfo/openvas-devel

Reply via email to