LCOV - code coverage report
Current view: top level - src - audit.c (source / functions) Hit Total Coverage
Test: rapport Lines: 31 287 10.8 %
Date: 2021-12-10 16:22:55 Functions: 1 6 16.7 %
Branches: 8 156 5.1 %

           Branch data     Line data    Source code
       1                 :            : /*-
       2                 :            :  * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
       3                 :            :  * Copyright (c) 2014-2015 Matthew Seaman <matthew@FreeBSD.org>
       4                 :            :  * Copyright (c) 2014 Vsevolod Stakhov <vsevolod@FreeBSD.org>
       5                 :            :  * All rights reserved.
       6                 :            :  * 
       7                 :            :  * Redistribution and use in source and binary forms, with or without
       8                 :            :  * modification, are permitted provided that the following conditions
       9                 :            :  * are met:
      10                 :            :  * 1. Redistributions of source code must retain the above copyright
      11                 :            :  *    notice, this list of conditions and the following disclaimer
      12                 :            :  *    in this position and unchanged.
      13                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      14                 :            :  *    notice, this list of conditions and the following disclaimer in the
      15                 :            :  *    documentation and/or other materials provided with the distribution.
      16                 :            :  * 
      17                 :            :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
      18                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      19                 :            :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      20                 :            :  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
      21                 :            :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      22                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      23                 :            :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      24                 :            :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      25                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      26                 :            :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      27                 :            :  */
      28                 :            : 
      29                 :            : #include "pkg_config.h"
      30                 :            : 
      31                 :            : #include <sys/param.h>
      32                 :            : #include <sys/queue.h>
      33                 :            : #include <sys/stat.h>
      34                 :            : #include <sys/mman.h>
      35                 :            : 
      36                 :            : #include <archive.h>
      37                 :            : #include <err.h>
      38                 :            : #include <errno.h>
      39                 :            : #include <fcntl.h>
      40                 :            : #include <fnmatch.h>
      41                 :            : #include <getopt.h>
      42                 :            : #include <stdbool.h>
      43                 :            : #include <stdio.h>
      44                 :            : #include <string.h>
      45                 :            : #include <unistd.h>
      46                 :            : #include <utlist.h>
      47                 :            : #include <ucl.h>
      48                 :            : 
      49                 :            : #ifdef HAVE_SYS_CAPSICUM_H
      50                 :            : #include <sys/capsicum.h>
      51                 :            : #endif
      52                 :            : 
      53                 :            : #ifdef HAVE_CAPSICUM
      54                 :            : #include <sys/capsicum.h>
      55                 :            : #endif
      56                 :            : 
      57                 :            : #include <pkg.h>
      58                 :            : #include <pkg/audit.h>
      59                 :            : #include "pkgcli.h"
      60                 :            : #include "xmalloc.h"
      61                 :            : #include "pkghash.h"
      62                 :            : 
      63                 :            : static const char* vop_names[] = {
      64                 :            :         [0] = "",
      65                 :            :         [EQ] = "=",
      66                 :            :         [LT] = "<",
      67                 :            :         [LTE] = "<=",
      68                 :            :         [GT] = ">",
      69                 :            :         [GTE] = ">="
      70                 :            : };
      71                 :            : 
      72                 :            : void
      73                 :          0 : usage_audit(void)
      74                 :            : {
      75                 :          0 :         fprintf(stderr, "Usage: pkg audit [-RFqr] [--raw[=format]|-R[format]| [-f file] <pattern>\n\n");
      76                 :          0 :         fprintf(stderr, "For more information see 'pkg help audit'.\n");
      77                 :          0 : }
      78                 :            : 
      79                 :            : static void
      80                 :          0 : add_to_check(pkghash *check, struct pkg *pkg)
      81                 :            : {
      82                 :            :         const char *uid;
      83                 :            : 
      84                 :          0 :         pkg_get(pkg, PKG_UNIQUEID, &uid);
      85   [ #  #  #  # ]:          0 :         pkghash_safe_add(check, uid, pkg, NULL);
      86                 :          0 : }
      87                 :            : 
      88                 :            : static void
      89                 :          0 : print_recursive_rdeps(pkghash *head, struct pkg *p, pkghash *seen, bool top, ucl_object_t *array)
      90                 :            : {
      91                 :            :         pkghash_entry *e;
      92                 :          0 :         struct pkg_dep *dep = NULL;
      93                 :            : 
      94         [ #  # ]:          0 :         while(pkg_rdeps(p, &dep) == EPKG_OK) {
      95                 :          0 :                 const char *name = pkg_dep_get(dep, PKG_DEP_NAME);
      96                 :            : 
      97         [ #  # ]:          0 :                 if (pkghash_get(seen, name) != NULL)
      98                 :          0 :                         continue;
      99                 :            : 
     100         [ #  # ]:          0 :                 if ((e = pkghash_get(head, name)) == NULL)
     101                 :          0 :                         continue;
     102                 :            : 
     103   [ #  #  #  # ]:          0 :                 pkghash_safe_add(seen, name, NULL, NULL);
     104         [ #  # ]:          0 :                 if (array == NULL) {
     105         [ #  # ]:          0 :                         if (!top)
     106                 :          0 :                                 printf(", ");
     107                 :            : 
     108                 :          0 :                         printf("%s", name);
     109                 :          0 :                 } else {
     110                 :          0 :                         ucl_array_append(array, ucl_object_fromstring(name));
     111                 :            :                 }
     112                 :            : 
     113                 :          0 :                 print_recursive_rdeps(head, (struct pkg *)e->value, seen, false, array);
     114                 :            : 
     115                 :          0 :                 top = false;
     116                 :            :         }
     117                 :          0 : }
     118                 :            : 
     119                 :            : static void
     120                 :          0 : print_issue(struct pkg *p, struct pkg_audit_issue *issue)
     121                 :            : {
     122                 :            :         const char *version;
     123                 :            :         struct pkg_audit_versions_range *vers;
     124                 :            :         const struct pkg_audit_entry *e;
     125                 :            :         struct pkg_audit_cve *cve;
     126                 :            : 
     127                 :          0 :         pkg_get(p, PKG_VERSION, &version);
     128                 :            : 
     129                 :          0 :         e = issue->audit;
     130         [ #  # ]:          0 :         if (version == NULL) {
     131                 :          0 :                 printf("  Affected versions:\n");
     132         [ #  # ]:          0 :                 LL_FOREACH(e->versions, vers) {
     133   [ #  #  #  # ]:          0 :                         if (vers->v1.type > 0 && vers->v2.type > 0)
     134                 :          0 :                                 printf("  %s %s : %s %s\n",
     135                 :          0 :                                     vop_names[vers->v1.type], vers->v1.version,
     136                 :          0 :                                     vop_names[vers->v2.type], vers->v2.version);
     137         [ #  # ]:          0 :                         else if (vers->v1.type > 0)
     138                 :          0 :                                 printf("  %s %s\n",
     139                 :          0 :                                     vop_names[vers->v1.type], vers->v1.version);
     140                 :            :                         else
     141                 :          0 :                                 printf("  %s %s\n",
     142                 :          0 :                                     vop_names[vers->v2.type], vers->v2.version);
     143                 :          0 :                 }
     144                 :          0 :         }
     145                 :          0 :         printf("  %s\n", e->desc);
     146         [ #  # ]:          0 :         LL_FOREACH(e->cve, cve) {
     147                 :          0 :                 printf("  CVE: %s\n", cve->cvename);
     148                 :          0 :         }
     149         [ #  # ]:          0 :         if (e->url)
     150                 :          0 :                 printf("  WWW: %s\n\n", e->url);
     151         [ #  # ]:          0 :         else if (e->id)
     152                 :          0 :                 printf("  WWW: https://vuxml.FreeBSD.org/freebsd/%s.html\n\n", e->id);
     153                 :          0 : }
     154                 :            : 
     155                 :            : static void
     156                 :          0 : format_issue(struct pkg *p, struct pkg_audit_issue *issue, ucl_object_t *array)
     157                 :            : {
     158                 :            :         const char *version;
     159                 :            :         struct pkg_audit_versions_range *vers;
     160                 :            :         const struct pkg_audit_entry *e;
     161                 :            :         struct pkg_audit_cve *cve;
     162                 :          0 :         ucl_object_t *o = ucl_object_typed_new(UCL_OBJECT);
     163                 :          0 :         ucl_object_t *affected_versions = ucl_object_typed_new(UCL_ARRAY);
     164                 :            : 
     165                 :          0 :         pkg_get(p, PKG_VERSION, &version);
     166                 :          0 :         ucl_array_append(array, o);
     167                 :            : 
     168                 :          0 :         e = issue->audit;
     169                 :          0 :         ucl_object_insert_key(o, affected_versions, "Affected versions", 17, false);
     170         [ #  # ]:          0 :         LL_FOREACH(e->versions, vers) {
     171                 :            :                 char *ver;
     172   [ #  #  #  # ]:          0 :                 if (vers->v1.type > 0 && vers->v2.type > 0)
     173                 :          0 :                         xasprintf(&ver, "%s %s : %s %s",
     174                 :          0 :                             vop_names[vers->v1.type], vers->v1.version,
     175                 :          0 :                             vop_names[vers->v2.type], vers->v2.version);
     176         [ #  # ]:          0 :                 else if (vers->v1.type > 0)
     177                 :          0 :                         xasprintf(&ver, "%s %s",
     178                 :          0 :                             vop_names[vers->v1.type], vers->v1.version);
     179                 :            :                 else
     180                 :          0 :                         xasprintf(&ver, "%s %s",
     181                 :          0 :                             vop_names[vers->v2.type], vers->v2.version);
     182                 :          0 :                 ucl_array_append(affected_versions, ucl_object_fromstring(ver));
     183                 :          0 :                 free(ver);
     184                 :          0 :         }
     185                 :          0 :         ucl_object_insert_key(o, ucl_object_fromstring(e->desc), "description", 11, false);
     186         [ #  # ]:          0 :         if (e->cve) {
     187                 :          0 :                 ucl_object_t *acve = ucl_object_typed_new(UCL_ARRAY);
     188         [ #  # ]:          0 :                 LL_FOREACH(e->cve, cve) {
     189                 :          0 :                         ucl_array_append(acve, ucl_object_fromstring(cve->cvename));
     190                 :          0 :                 }
     191                 :          0 :                 ucl_object_insert_key(o, acve, "cve", 3, false);
     192                 :          0 :         }
     193         [ #  # ]:          0 :         if (e->url)
     194                 :          0 :                 ucl_object_insert_key(o, ucl_object_fromstring(e->url), "url", 3, false);
     195         [ #  # ]:          0 :         else if (e->id) {
     196                 :            :                 char *url;
     197                 :          0 :                 xasprintf(&url, "https://vuxml.FreeBSD.org/freebsd/%s.html\n\n", e->id);
     198                 :          0 :                 ucl_object_insert_key(o, ucl_object_fromstring(url), "url", 3, false);
     199                 :          0 :                 free(url);
     200                 :          0 :         }
     201                 :          0 : }
     202                 :            : 
     203                 :            : int
     204                 :          4 : exec_audit(int argc, char **argv)
     205                 :            : {
     206                 :            :         struct pkg_audit        *audit;
     207                 :            :         struct pkg_audit_issues *issues;
     208                 :            :         struct pkg_audit_issue  *issue;
     209                 :          4 :         struct pkgdb            *db = NULL;
     210                 :          4 :         struct pkgdb_it         *it = NULL;
     211                 :          4 :         struct pkg              *pkg = NULL;
     212                 :            :         char                    *name;
     213                 :            :         char                    *version;
     214                 :          4 :         char                    *audit_file = NULL;
     215                 :          4 :         int                      affected = 0, vuln = 0;
     216                 :          4 :         bool                     fetch = false, recursive = false;
     217                 :            :         int                      ch, i;
     218                 :            :         int                      raw;
     219                 :          4 :         int                      ret = EXIT_SUCCESS;
     220                 :          4 :         pkghash                 *check = NULL;
     221                 :            :         pkghash_it              hit;
     222                 :          4 :         ucl_object_t            *top = NULL, *vuln_objs = NULL;
     223                 :          4 :         ucl_object_t            *obj = NULL;
     224                 :            : 
     225                 :          4 :         struct option longopts[] = {
     226                 :            :                 { "fetch",    no_argument,            NULL,   'F' },
     227                 :            :                 { "file",     required_argument,      NULL,   'f' },
     228                 :            :                 { "recursive",        no_argument,    NULL,   'r' },
     229                 :            :                 { "raw",      optional_argument,      NULL,   'R' },
     230                 :            :                 { "quiet",    no_argument,            NULL,   'q' },
     231                 :            :                 { NULL,         0,                      NULL,   0   },
     232                 :            :         };
     233                 :            : 
     234         [ +  + ]:          8 :         while ((ch = getopt_long(argc, argv, "+Ff:qrR::", longopts, NULL)) != -1) {
     235   [ +  -  -  -  :          4 :                 switch (ch) {
                   -  - ]
     236                 :            :                 case 'F':
     237                 :          4 :                         fetch = true;
     238                 :          4 :                         break;
     239                 :            :                 case 'f':
     240                 :          0 :                         audit_file = optarg;
     241                 :          0 :                         break;
     242                 :            :                 case 'q':
     243                 :          0 :                         quiet = true;
     244                 :          0 :                         break;
     245                 :            :                 case 'r':
     246                 :          0 :                         recursive = true;
     247                 :          0 :                         break;
     248                 :            :                 case 'R':
     249         [ #  # ]:          0 :                         if (optarg == NULL) {
     250                 :          0 :                                 raw = UCL_EMIT_CONFIG;
     251         [ #  # ]:          0 :                         } else if (strcasecmp(optarg, "ucl") == 0) {
     252                 :          0 :                                 raw = UCL_EMIT_CONFIG;
     253         [ #  # ]:          0 :                         } else if (strcasecmp(optarg, "json") == 0) {
     254                 :          0 :                                 raw = UCL_EMIT_JSON;
     255         [ #  # ]:          0 :                         } else if (strcasecmp(optarg, "json-compact") == 0) {
     256                 :          0 :                                 raw = UCL_EMIT_JSON_COMPACT;
     257         [ #  # ]:          0 :                         } else if (strcasecmp(optarg, "yaml") == 0) {
     258                 :          0 :                                 raw = UCL_EMIT_YAML;
     259                 :          0 :                         } else {
     260                 :          0 :                                 errx(EXIT_FAILURE, "invalid argument %s for --raw option", optarg);
     261                 :            :                         }
     262                 :          0 :                         top = ucl_object_typed_new(UCL_OBJECT);
     263                 :          0 :                         break;
     264                 :            :                 default:
     265                 :          0 :                         usage_audit();
     266                 :          0 :                         return(EXIT_FAILURE);
     267                 :            :                 }
     268                 :            :         }
     269                 :          4 :         argc -= optind;
     270                 :          4 :         argv += optind;
     271                 :            : 
     272                 :          4 :         audit = pkg_audit_new();
     273                 :            : 
     274         [ -  + ]:          4 :         if (fetch == true) {
     275         [ -  + ]:          4 :                 if (pkg_audit_fetch(NULL, audit_file) != EPKG_OK) {
     276                 :          0 :                         pkg_audit_free(audit);
     277                 :          0 :                         return (EXIT_FAILURE);
     278                 :            :                 }
     279                 :          4 :         }
     280                 :            : 
     281         [ -  + ]:          4 :         if (pkg_audit_load(audit, audit_file) != EPKG_OK) {
     282         [ #  # ]:          0 :                 if (errno == ENOENT)
     283                 :          0 :                         warnx("vulnxml file %s does not exist. "
     284                 :            :                                         "Try running 'pkg audit -F' first",
     285                 :          0 :                                         audit_file);
     286                 :            :                 else
     287                 :          0 :                         warn("unable to open vulnxml file %s",
     288                 :          0 :                                         audit_file);
     289                 :            : 
     290                 :          0 :                 pkg_audit_free(audit);
     291                 :          0 :                 return (EXIT_FAILURE);
     292                 :            :         }
     293                 :            : 
     294                 :          4 :         check = pkghash_new();
     295         [ -  + ]:          4 :         if (argc >= 1) {
     296         [ #  # ]:          0 :                 for (i = 0; i < argc; i ++) {
     297                 :          0 :                         name = argv[i];
     298                 :          0 :                         version = strrchr(name, '-');
     299         [ #  # ]:          0 :                         if (version != NULL) {
     300                 :          0 :                                 version[0] = '\0';
     301                 :          0 :                                 version++;
     302                 :          0 :                         }
     303         [ #  # ]:          0 :                         if (pkg_new(&pkg, PKG_FILE) != EPKG_OK)
     304                 :          0 :                                 err(EXIT_FAILURE, "malloc");
     305         [ #  # ]:          0 :                         if (version != NULL)
     306                 :          0 :                                 pkg_set(pkg, PKG_NAME, name, PKG_VERSION, version);
     307                 :            :                         else
     308                 :          0 :                                 pkg_set(pkg, PKG_NAME, name);
     309                 :            :                         /* Fake uniqueid */
     310                 :          0 :                         pkg_set(pkg, PKG_UNIQUEID, name);
     311                 :          0 :                         add_to_check(check, pkg);
     312                 :          0 :                         pkg = NULL;
     313                 :          0 :                 }
     314                 :          0 :         }
     315                 :            :         else {
     316                 :            : 
     317                 :            :                 /*
     318                 :            :                  * if the database doesn't exist it just means there are no
     319                 :            :                  * packages to audit.
     320                 :            :                  */
     321                 :            : 
     322                 :          4 :                 ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL);
     323         [ +  - ]:          4 :                 if (ret == EPKG_ENODB) {
     324                 :          4 :                         pkg_audit_free(audit);
     325                 :          4 :                         pkghash_destroy(check);
     326                 :          4 :                         return (EXIT_SUCCESS);
     327         [ #  # ]:          0 :                 } else if (ret == EPKG_ENOACCESS) {
     328                 :          0 :                         warnx("Insufficient privileges to read the package database");
     329                 :          0 :                         pkg_audit_free(audit);
     330                 :          0 :                         pkghash_destroy(check);
     331                 :          0 :                         return (EXIT_FAILURE);
     332         [ #  # ]:          0 :                 } else if (ret != EPKG_OK) {
     333                 :          0 :                         warnx("Error accessing the package database");
     334                 :          0 :                         pkg_audit_free(audit);
     335                 :          0 :                         pkghash_destroy(check);
     336                 :          0 :                         return (EXIT_FAILURE);
     337                 :            :                 }
     338                 :            : 
     339         [ #  # ]:          0 :                 if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) {
     340                 :          0 :                         pkg_audit_free(audit);
     341                 :          0 :                         pkghash_destroy(check);
     342                 :          0 :                         return (EXIT_FAILURE);
     343                 :            :                 }
     344                 :            : 
     345         [ #  # ]:          0 :                 if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) {
     346                 :          0 :                         pkgdb_close(db);
     347                 :          0 :                         pkg_audit_free(audit);
     348                 :          0 :                         pkghash_destroy(check);
     349                 :          0 :                         warnx("Cannot get a read lock on a database, it is locked by another process");
     350                 :          0 :                         return (EXIT_FAILURE);
     351                 :            :                 }
     352                 :            : 
     353         [ #  # ]:          0 :                 if ((it = pkgdb_query(db, NULL, MATCH_ALL)) == NULL) {
     354                 :          0 :                         warnx("Error accessing the package database");
     355                 :          0 :                         ret = EXIT_FAILURE;
     356                 :          0 :                 }
     357                 :            :                 else {
     358   [ #  #  #  # ]:          0 :                         while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC|PKG_LOAD_RDEPS)
     359                 :          0 :                                                         == EPKG_OK) {
     360                 :          0 :                                 add_to_check(check, pkg);
     361                 :          0 :                                 pkg = NULL;
     362                 :            :                         }
     363                 :          0 :                         ret = EXIT_SUCCESS;
     364                 :            :                 }
     365         [ #  # ]:          0 :                 if (db != NULL) {
     366                 :          0 :                         pkgdb_it_free(it);
     367                 :          0 :                         pkgdb_release_lock(db, PKGDB_LOCK_READONLY);
     368                 :          0 :                         pkgdb_close(db);
     369                 :          0 :                 }
     370         [ #  # ]:          0 :                 if (ret != EXIT_SUCCESS) {
     371                 :          0 :                         pkg_audit_free(audit);
     372                 :          0 :                         pkghash_destroy(check);
     373                 :          0 :                         return (ret);
     374                 :            :                 }
     375                 :            :         }
     376                 :            : 
     377                 :          0 :         drop_privileges();
     378                 :            : 
     379                 :            :         /* Now we have vulnxml loaded and check list formed */
     380                 :            : #ifdef HAVE_CAPSICUM
     381                 :            : #ifndef PKG_COVERAGE
     382                 :            :         if (cap_enter() < 0 && errno != ENOSYS) {
     383                 :            :                 warn("cap_enter() failed");
     384                 :            :                 pkg_audit_free(audit);
     385                 :            :                 pkghash_destroy(check);
     386                 :            :                 return (EPKG_FATAL);
     387                 :            :         }
     388                 :            : #endif
     389                 :            : #endif
     390                 :            : 
     391         [ #  # ]:          0 :         if (pkg_audit_process(audit) == EPKG_OK) {
     392                 :          0 :                 hit = pkghash_iterator(check);
     393         [ #  # ]:          0 :                 while (pkghash_next(&hit)) {
     394                 :          0 :                         issues = NULL;
     395                 :          0 :                         pkg = (struct pkg *) hit.value;
     396         [ #  # ]:          0 :                         if (pkg_audit_is_vulnerable(audit, pkg, &issues, quiet)) {
     397                 :            :                                 const char *version;
     398                 :          0 :                                 const char *name = NULL;
     399                 :          0 :                                 ucl_object_t *array = NULL;
     400                 :          0 :                                 vuln ++;
     401                 :            : 
     402         [ #  # ]:          0 :                                 if (top == NULL) {
     403                 :          0 :                                         affected += issues->count;
     404                 :          0 :                                         pkg_get(pkg, PKG_VERSION, &version);
     405         [ #  # ]:          0 :                                         if (quiet) {
     406         [ #  # ]:          0 :                                                 if (version != NULL)
     407                 :          0 :                                                         pkg_printf("%n-%v\n", pkg, pkg);
     408                 :            :                                                         else
     409                 :          0 :                                                 pkg_printf("%s\n", pkg);
     410                 :          0 :                                                 continue;
     411                 :            :                                         }
     412                 :            : 
     413                 :          0 :                                         pkg_printf("%n", pkg);
     414         [ #  # ]:          0 :                                         if (version != NULL)
     415                 :          0 :                                                 pkg_printf("-%v", pkg);
     416         [ #  # ]:          0 :                                         if (!quiet)
     417                 :          0 :                                                 printf(" is vulnerable");
     418                 :          0 :                                         printf(":\n");
     419                 :          0 :                                 } else {
     420         [ #  # ]:          0 :                                         if (vuln_objs == NULL)
     421                 :          0 :                                                 vuln_objs = ucl_object_typed_new(UCL_OBJECT);
     422                 :          0 :                                         obj = ucl_object_typed_new(UCL_OBJECT);
     423                 :          0 :                                         pkg_get(pkg, PKG_NAME, &name, PKG_VERSION, &version);
     424         [ #  # ]:          0 :                                         if (version != NULL)
     425                 :          0 :                                                 ucl_object_insert_key(obj, ucl_object_fromstring(version), "version", 7 , false);
     426                 :          0 :                                         ucl_object_insert_key(obj, ucl_object_fromint(issues->count), "issue_count", 11, false);
     427                 :            :                                 }
     428                 :            : 
     429         [ #  # ]:          0 :                                 if (top != NULL)
     430                 :          0 :                                         array = ucl_object_typed_new(UCL_ARRAY);
     431         [ #  # ]:          0 :                                 LL_FOREACH(issues->issues, issue) {
     432         [ #  # ]:          0 :                                         if (top == NULL)
     433                 :          0 :                                                 print_issue(pkg, issue);
     434                 :            :                                         else
     435                 :          0 :                                                 format_issue(pkg, issue, array);
     436                 :          0 :                                 }
     437         [ #  # ]:          0 :                                 if (top != NULL)
     438                 :          0 :                                         ucl_object_insert_key(obj, array, "issues", 6, false);
     439                 :          0 :                                 array = NULL;
     440                 :            : 
     441   [ #  #  #  # ]:          0 :                                 if (top != NULL || recursive) {
     442                 :          0 :                                         pkghash *seen = pkghash_new();
     443                 :            : 
     444         [ #  # ]:          0 :                                         if (name == NULL)
     445                 :          0 :                                                 pkg_get(pkg, PKG_NAME, &name);
     446         [ #  # ]:          0 :                                         if (top == NULL) {
     447                 :          0 :                                                 printf("  Packages that depend on %s: ", name);
     448                 :          0 :                                         } else {
     449                 :          0 :                                                 array = ucl_object_typed_new(UCL_ARRAY);
     450                 :            :                                         }
     451                 :          0 :                                         print_recursive_rdeps(check, pkg , seen, true, array);
     452         [ #  # ]:          0 :                                         if (top == NULL)
     453                 :          0 :                                                 printf("\n\n");
     454                 :            : 
     455                 :          0 :                                         pkghash_destroy(seen);
     456                 :          0 :                                 }
     457         [ #  # ]:          0 :                                 if (top != NULL) {
     458                 :          0 :                                         ucl_object_insert_key(obj, array, "reverse dependencies", 20, false);
     459                 :          0 :                                         ucl_object_insert_key(vuln_objs, obj, xstrdup(name), strlen(name), false);
     460                 :          0 :                                 }
     461                 :          0 :                         }
     462                 :          0 :                         pkg_audit_issues_free(issues);
     463                 :          0 :                         pkg_free(pkg);
     464                 :            :                 }
     465                 :          0 :                 pkghash_destroy(check);
     466                 :            : 
     467   [ #  #  #  # ]:          0 :                 if (ret == EPKG_END && vuln == 0)
     468                 :          0 :                         ret = EXIT_SUCCESS;
     469                 :            : 
     470         [ #  # ]:          0 :                 if (top == NULL) {
     471         [ #  # ]:          0 :                         if (!quiet)
     472                 :          0 :                                 printf("%u problem(s) in %u installed package(s) found.\n",
     473                 :          0 :                                    affected, vuln);
     474                 :            :         
     475                 :          0 :                 } else {
     476                 :          0 :                         ucl_object_insert_key(top, ucl_object_fromint(vuln), "pkg_count", 9, false );
     477                 :          0 :                         ucl_object_insert_key(top, vuln_objs, "packages", 8, false);
     478                 :          0 :                         fprintf(stdout, "%s\n", ucl_object_emit(top, raw));
     479                 :          0 :                         ucl_object_unref(top);
     480                 :            :                 }
     481                 :          0 :         } else {
     482                 :          0 :                 warnx("cannot process vulnxml");
     483                 :          0 :                 ret = EXIT_FAILURE;
     484                 :          0 :                 pkghash_destroy(check);
     485                 :            :         }
     486                 :            : 
     487                 :          0 :         pkg_audit_free(audit);
     488         [ #  # ]:          0 :         if (vuln != 0)
     489                 :          0 :                 ret = EXIT_FAILURE;
     490                 :            : 
     491                 :          0 :         return (ret);
     492                 :          4 : }

Generated by: LCOV version 1.15