LCOV - code coverage report
Current view: top level - libpkg - pkg_repo.c (source / functions) Hit Total Coverage
Test: plop Lines: 372 826 45.0 %
Date: 2024-12-28 18:40:32 Functions: 15 22 68.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 157 422 37.2 %

           Branch data     Line data    Source code
       1                 :            : /*-
       2                 :            :  * Copyright (c) 2011-2024 Baptiste Daroussin <bapt@FreeBSD.org>
       3                 :            :  * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
       4                 :            :  * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
       5                 :            :  * Copyright (c) 2012-2015 Matthew Seaman <matthew@FreeBSD.org>
       6                 :            :  * Copyright (c) 2014 Vsevolod Stakhov <vsevolod@FreeBSD.org>
       7                 :            :  * Copyright (c) 2023 Serenity Cyber Security, LLC
       8                 :            :  *                    Author: Gleb Popov <arrowd@FreeBSD.org>
       9                 :            :  *
      10                 :            :  * All rights reserved.
      11                 :            :  *
      12                 :            :  * Redistribution and use in source and binary forms, with or without
      13                 :            :  * modification, are permitted provided that the following conditions
      14                 :            :  * are met:
      15                 :            :  * 1. Redistributions of source code must retain the above copyright
      16                 :            :  *    notice, this list of conditions and the following disclaimer
      17                 :            :  *    in this position and unchanged.
      18                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      19                 :            :  *    notice, this list of conditions and the following disclaimer in the
      20                 :            :  *    documentation and/or other materials provided with the distribution.
      21                 :            :  *
      22                 :            :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
      23                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      24                 :            :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      25                 :            :  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
      26                 :            :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      27                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      28                 :            :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      29                 :            :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      30                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      31                 :            :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      32                 :            :  */
      33                 :            : 
      34                 :            : #include <sys/types.h>
      35                 :            : #include <sys/stat.h>
      36                 :            : #include <sys/uio.h>
      37                 :            : 
      38                 :            : #include <archive_entry.h>
      39                 :            : #include <assert.h>
      40                 :            : #include <fts.h>
      41                 :            : #include <libgen.h>
      42                 :            : #include <sqlite3.h>
      43                 :            : #include <string.h>
      44                 :            : #include <dirent.h>
      45                 :            : #define _WITH_GETLINE
      46                 :            : #include <stdio.h>
      47                 :            : #include <stdbool.h>
      48                 :            : #include <unistd.h>
      49                 :            : #include <errno.h>
      50                 :            : #include <sys/mman.h>
      51                 :            : #include <fcntl.h>
      52                 :            : 
      53                 :            : #include "pkg.h"
      54                 :            : #include "private/event.h"
      55                 :            : #include "private/utils.h"
      56                 :            : #include "private/pkg.h"
      57                 :            : #include "private/pkgdb.h"
      58                 :            : #include "private/fetch.h"
      59                 :            : #include "private/pkgsign.h"
      60                 :            : 
      61                 :            : struct sig_cert {
      62                 :            :         char name[MAXPATHLEN];
      63                 :            :         char *type;
      64                 :            :         char *sig;
      65                 :            :         int64_t siglen;
      66                 :            :         char *cert;
      67                 :            :         int64_t certlen;
      68                 :            :         bool cert_allocated;
      69                 :            :         bool trusted;
      70                 :            : };
      71                 :            : 
      72                 :            : int
      73                 :        297 : pkg_repo_fetch_remote_tmp(struct pkg_repo *repo,
      74                 :            :   const char *filename, const char *extension, time_t *t, int *rc, bool silent)
      75                 :            : {
      76                 :            :         struct fetch_item fi;
      77                 :            :         char url[MAXPATHLEN];
      78                 :            :         char tmp[MAXPATHLEN];
      79                 :            :         int fd;
      80                 :            :         const char *tmpdir, *dot;
      81                 :            : 
      82                 :        297 :         memset(&fi, 0, sizeof(struct fetch_item));
      83                 :            : 
      84                 :            :         /*
      85                 :            :          * XXX: here we support old naming scheme, such as filename.yaml
      86                 :            :          */
      87                 :        297 :         dot = strrchr(filename, '.');
      88         [ +  + ]:        297 :         if (dot != NULL) {
      89         [ -  + ]:         16 :                 snprintf(tmp, MIN(sizeof(tmp), dot - filename + 1), "%s", filename);
      90                 :         32 :                 snprintf(url, sizeof(url), "%s/%s.%s", pkg_repo_url(repo), tmp,
      91                 :         16 :                                 extension);
      92                 :         16 :         }
      93                 :            :         else {
      94                 :        562 :                 snprintf(url, sizeof(url), "%s/%s.%s", pkg_repo_url(repo), filename,
      95                 :        281 :                                 extension);
      96                 :            :         }
      97                 :            : 
      98                 :        297 :         tmpdir = getenv("TMPDIR");
      99         [ +  - ]:        297 :         if (tmpdir == NULL)
     100                 :          0 :                 tmpdir = "/tmp";
     101                 :        297 :         pkg_mkdirs(tmpdir);
     102                 :        297 :         snprintf(tmp, sizeof(tmp), "%s/%s.%s.XXXXXX", tmpdir, filename, extension);
     103                 :            : 
     104                 :        297 :         fd = mkstemp(tmp);
     105         [ +  - ]:        297 :         if (fd == -1) {
     106                 :          0 :                 pkg_emit_error("Could not create temporary file %s, "
     107                 :          0 :                     "aborting update.\n", tmp);
     108                 :          0 :                 *rc = EPKG_FATAL;
     109                 :          0 :                 return (-1);
     110                 :            :         }
     111                 :        297 :         (void)unlink(tmp);
     112                 :            : 
     113                 :        297 :         fi.url = url;
     114                 :        297 :         fi.mtime = *t;
     115         [ +  + ]:        297 :         if ((*rc = pkg_fetch_file_to_fd(repo, fd, &fi, silent)) != EPKG_OK) {
     116                 :        150 :                 close(fd);
     117                 :        150 :                 fd = -1;
     118                 :        150 :         }
     119         [ +  + ]:        297 :         if (fd != -1)
     120                 :        147 :                 *t = fi.mtime;
     121                 :            : 
     122                 :        297 :         return (fd);
     123                 :        297 : }
     124                 :            : 
     125                 :            : static bool
     126                 :          0 : pkg_repo_file_has_ext(const char *path, const char *ext)
     127                 :            : {
     128                 :            :         size_t n, l;
     129                 :          0 :         const char *p = NULL;
     130                 :            : 
     131                 :          0 :         n = strlen(path);
     132                 :          0 :         l = strlen(ext);
     133                 :          0 :         p = &path[n - l];
     134                 :            : 
     135         [ #  # ]:          0 :         if (STREQ(p, ext))
     136                 :          0 :                 return (true);
     137                 :            : 
     138                 :          0 :         return (false);
     139                 :          0 : }
     140                 :            : 
     141                 :            : static bool
     142                 :          3 : pkg_repo_check_fingerprint(struct pkg_repo *repo, pkghash *sc, bool fatal)
     143                 :            : {
     144                 :            :         char *hash;
     145                 :          3 :         int nbgood = 0;
     146                 :          3 :         struct sig_cert *s = NULL;
     147                 :          3 :         struct pkg_repo_meta_key *mk = NULL;
     148                 :            :         pkghash_it it;
     149                 :            : 
     150         [ +  - ]:          3 :         if (pkghash_count(sc) == 0) {
     151         [ #  # ]:          0 :                 if (fatal)
     152                 :          0 :                         pkg_emit_error("No signature found");
     153                 :          0 :                 return (false);
     154                 :            :         }
     155                 :            : 
     156                 :            :         /* load fingerprints */
     157         [ -  + ]:          3 :         if (repo->trusted_fp == NULL) {
     158         [ -  + ]:          3 :                 if (pkg_repo_load_fingerprints(repo) != EPKG_OK)
     159                 :          0 :                         return (false);
     160                 :          3 :         }
     161                 :            : 
     162                 :          3 :         it = pkghash_iterator(sc);
     163         [ +  + ]:          6 :         while (pkghash_next(&it)) {
     164                 :          3 :                 s = (struct sig_cert *) it.value;
     165   [ +  -  +  - ]:          3 :                 if (s->sig != NULL && s->cert == NULL) {
     166                 :            :                         /*
     167                 :            :                          * We may want to check meta
     168                 :            :                          */
     169   [ #  #  #  # ]:          0 :                         if (repo->meta != NULL && repo->meta->keys != NULL) {
     170                 :          0 :                                 mk = pkghash_get_value(repo->meta->keys, s->name);
     171                 :          0 :                         }
     172                 :            : 
     173   [ #  #  #  # ]:          0 :                         if (mk != NULL && mk->pubkey != NULL) {
     174                 :          0 :                                 s->cert = mk->pubkey;
     175                 :          0 :                                 s->certlen = strlen(mk->pubkey);
     176                 :          0 :                         }
     177                 :            :                         else {
     178         [ #  # ]:          0 :                                 if (fatal)
     179                 :          0 :                                         pkg_emit_error("No key with name %s has been found", s->name);
     180                 :          0 :                                 return (false);
     181                 :            :                         }
     182                 :          0 :                 }
     183         [ +  - ]:          3 :                 else if (s->sig == NULL) {
     184         [ #  # ]:          0 :                         if (fatal)
     185                 :          0 :                                 pkg_emit_error("No signature with name %s has been found", s->name);
     186                 :          0 :                         return (false);
     187                 :            :                 }
     188                 :            : 
     189                 :          3 :                 s->trusted = false;
     190                 :          3 :                 hash = pkg_checksum_data(s->cert, s->certlen,
     191                 :            :                     PKG_HASH_TYPE_SHA256_HEX);
     192         [ +  - ]:          3 :                 if (pkghash_get(repo->revoked_fp, hash) != NULL) {
     193         [ #  # ]:          0 :                         if (fatal)
     194                 :          0 :                                 pkg_emit_error("At least one of the "
     195                 :            :                                         "certificates has been revoked");
     196                 :            : 
     197                 :          0 :                         free(hash);
     198                 :          0 :                         return (false);
     199                 :            :                 }
     200                 :            : 
     201         [ -  + ]:          3 :                 if (pkghash_get(repo->trusted_fp, hash) != NULL) {
     202                 :          3 :                         nbgood++;
     203                 :          3 :                         s->trusted = true;
     204                 :          3 :                 }
     205                 :          3 :                 free(hash);
     206                 :            :         }
     207                 :            : 
     208         [ +  - ]:          3 :         if (nbgood == 0) {
     209         [ #  # ]:          0 :                 if (fatal)
     210                 :          0 :                         pkg_emit_error("No trusted public keys found");
     211                 :            : 
     212                 :          0 :                 return (false);
     213                 :            :         }
     214                 :            : 
     215                 :          3 :         return (true);
     216                 :          3 : }
     217                 :            : 
     218                 :            : static void
     219                 :          0 : pkg_repo_signatures_free(pkghash *sc)
     220                 :            : {
     221                 :            :         struct sig_cert *s;
     222                 :            :         pkghash_it it;
     223                 :            : 
     224         [ #  # ]:          0 :         if (sc == NULL)
     225                 :          0 :                 return;
     226                 :          0 :         it = pkghash_iterator(sc);
     227         [ #  # ]:          0 :         while (pkghash_next(&it)) {
     228                 :          0 :                 s = (struct sig_cert *)it.value;
     229                 :          0 :                 free(s->sig);
     230                 :          0 :                 free(s->type);
     231         [ #  # ]:          0 :                 if (s->cert_allocated)
     232                 :          0 :                         free(s->cert);
     233                 :          0 :                 free(s);
     234                 :            :         }
     235                 :          0 :         pkghash_destroy(sc);
     236                 :          0 : }
     237                 :            : 
     238                 :            : 
     239                 :            : struct pkg_extract_cbdata {
     240                 :            :         int afd;
     241                 :            :         int tfd;
     242                 :            :         const char *fname;
     243                 :            :         bool need_sig;
     244                 :            : };
     245                 :            : 
     246                 :            : #define PKGSIGN_DEFAULT_IMPL    "rsa"
     247                 :            : 
     248                 :            : static int
     249                 :          0 : pkg_repo_write_sig_from_archive(struct archive *a, int fd, size_t siglen)
     250                 :            : {
     251                 :          0 :         char sig[siglen];
     252                 :            : 
     253         [ #  # ]:          0 :         if (archive_read_data(a, sig, siglen) == -1) {
     254                 :          0 :                 pkg_emit_errno("pkg_repo_meta_extract_signature",
     255                 :            :                     "archive_read_data failed");
     256                 :          0 :                 return (EPKG_FATAL);
     257                 :            :         }
     258         [ #  # ]:          0 :         if (write(fd, sig, siglen) == -1) {
     259                 :          0 :                 pkg_emit_errno("pkg_repo_meta_extract_signature",
     260                 :            :                     "write failed");
     261                 :          0 :                 return (EPKG_FATAL);
     262                 :            :         }
     263                 :          0 :         return (EPKG_OK);
     264                 :          0 : }
     265                 :            : 
     266                 :            : static int
     267                 :          0 : pkg_repo_meta_extract_signature_pubkey(int fd, void *ud)
     268                 :            : {
     269                 :          0 :         struct archive *a = NULL;
     270                 :          0 :         struct archive_entry *ae = NULL;
     271                 :          0 :         struct pkg_extract_cbdata *cb = ud;
     272                 :            :         int siglen;
     273                 :          0 :         int rc = EPKG_FATAL;
     274                 :            : 
     275                 :          0 :         pkg_debug(1, "PkgRepo: extracting signature of repo in a sandbox");
     276                 :            : 
     277                 :          0 :         a = archive_read_new();
     278                 :          0 :         archive_read_support_filter_all(a);
     279                 :          0 :         archive_read_support_format_tar(a);
     280                 :            : 
     281                 :          0 :         archive_read_open_fd(a, cb->afd, 4096);
     282                 :            : 
     283         [ #  # ]:          0 :         while (archive_read_next_header(a, &ae) == ARCHIVE_OK) {
     284   [ #  #  #  # ]:          0 :                 if (cb->need_sig && STREQ(archive_entry_pathname(ae), "signature")) {
     285                 :          0 :                         siglen = archive_entry_size(ae);
     286                 :          0 :                         rc = pkg_repo_write_sig_from_archive(a, fd, siglen);
     287         [ #  # ]:          0 :                         if (rc != EPKG_OK)
     288                 :          0 :                                 break;
     289                 :          0 :                 }
     290         [ #  # ]:          0 :                 else if (STREQ(archive_entry_pathname(ae), cb->fname)) {
     291         [ #  # ]:          0 :                         if (archive_read_data_into_fd(a, cb->tfd) != 0) {
     292                 :          0 :                                 pkg_emit_error("Error extracting the archive: '%s'", archive_error_string(a));
     293                 :          0 :                                 rc = EPKG_FATAL;
     294                 :          0 :                                 break;
     295                 :            :                         }
     296         [ #  # ]:          0 :                         else if (!cb->need_sig) {
     297                 :          0 :                                 rc = EPKG_OK;
     298                 :          0 :                         }
     299                 :          0 :                 }
     300                 :            :         }
     301                 :            : 
     302                 :          0 :         close(cb->tfd);
     303                 :            :         /*
     304                 :            :          * XXX: do not free resources here since the sandbox is terminated anyway
     305                 :            :          */
     306                 :          0 :         return (rc);
     307                 :            : }
     308                 :            : /*
     309                 :            :  * We use here the following format:
     310                 :            :  * <type(0|1)><namelen(int)><name><sigtypelen(int)><sigtype><datalen(int)><data>
     311                 :            :  */
     312                 :            : static int
     313                 :          0 : pkg_repo_meta_extract_signature_fingerprints(int fd, void *ud)
     314                 :            : {
     315                 :          0 :         struct archive *a = NULL;
     316                 :          0 :         struct archive_entry *ae = NULL;
     317                 :          0 :         struct pkg_extract_cbdata *cb = ud;
     318                 :            :         const char *type;
     319                 :            :         int siglen, keylen, typelen;
     320                 :            :         uint8_t *sig, *sigdata;
     321                 :          0 :         int rc = EPKG_FATAL;
     322                 :            :         char key[MAXPATHLEN], t;
     323                 :            :         struct iovec iov[7];
     324                 :            : 
     325                 :          0 :         pkg_debug(1, "PkgRepo: extracting signature of repo in a sandbox");
     326                 :            : 
     327                 :          0 :         a = archive_read_new();
     328                 :          0 :         archive_read_support_filter_all(a);
     329                 :          0 :         archive_read_support_format_tar(a);
     330                 :            : 
     331                 :          0 :         archive_read_open_fd(a, cb->afd, 4096);
     332                 :            : 
     333         [ #  # ]:          0 :         while (archive_read_next_header(a, &ae) == ARCHIVE_OK) {
     334         [ #  # ]:          0 :                 if (pkg_repo_file_has_ext(archive_entry_pathname(ae), ".sig")) {
     335                 :          0 :                         snprintf(key, sizeof(key), "%.*s",
     336                 :          0 :                                         (int) strlen(archive_entry_pathname(ae)) - 4,
     337                 :          0 :                                         archive_entry_pathname(ae));
     338                 :          0 :                         type = NULL;
     339                 :          0 :                         siglen = archive_entry_size(ae);
     340                 :          0 :                         sigdata = sig = xmalloc(siglen);
     341         [ #  # ]:          0 :                         if (archive_read_data(a, sig, siglen) == -1) {
     342                 :          0 :                                 pkg_emit_errno("pkg_repo_meta_extract_signature",
     343                 :            :                                                 "archive_read_data failed");
     344                 :          0 :                                 free(sig);
     345                 :          0 :                                 return (EPKG_FATAL);
     346                 :            :                         }
     347         [ #  # ]:          0 :                         if (strncmp(sig, PKGSIGN_HEAD, strlen(PKGSIGN_HEAD)) == 0) {
     348                 :          0 :                                 type = sig + strlen(PKGSIGN_HEAD);
     349                 :          0 :                                 sigdata = memchr(type, '$', siglen - ((uint8_t *)type - sig));
     350         [ #  # ]:          0 :                                 if (sigdata != NULL) {
     351                 :          0 :                                         *sigdata++ = '\0';
     352                 :            : 
     353                 :          0 :                                         siglen -= sigdata - sig;
     354                 :          0 :                                 } else {
     355                 :            :                                         /* Malformed, proceed as if no header at all. */
     356                 :          0 :                                         sigdata = sig;
     357                 :          0 :                                         type = NULL;
     358                 :            :                                 }
     359                 :          0 :                         }
     360                 :            : 
     361         [ #  # ]:          0 :                         if (type == NULL)
     362                 :          0 :                                 type = "rsa";
     363                 :          0 :                         typelen = strlen(type);
     364                 :            :                         /* Signature type */
     365                 :          0 :                         t = 0;
     366                 :          0 :                         keylen = strlen(key);
     367                 :          0 :                         iov[0].iov_base = &t;
     368                 :          0 :                         iov[0].iov_len = sizeof(t);
     369                 :          0 :                         iov[1].iov_base = &keylen;
     370                 :          0 :                         iov[1].iov_len = sizeof(keylen);
     371                 :          0 :                         iov[2].iov_base = key;
     372                 :          0 :                         iov[2].iov_len = keylen;
     373                 :          0 :                         iov[3].iov_base = &typelen;
     374                 :          0 :                         iov[3].iov_len = sizeof(typelen);
     375                 :          0 :                         iov[4].iov_base = __DECONST(void *, type);
     376                 :          0 :                         iov[4].iov_len = typelen;
     377                 :          0 :                         iov[5].iov_base = &siglen;
     378                 :          0 :                         iov[5].iov_len = sizeof(siglen);
     379                 :          0 :                         iov[6].iov_base = sigdata;
     380                 :          0 :                         iov[6].iov_len = siglen;
     381         [ #  # ]:          0 :                         if (writev(fd, iov, NELEM(iov)) == -1) {
     382                 :          0 :                                 pkg_emit_errno("pkg_repo_meta_extract_signature",
     383                 :            :                                                 "writev failed");
     384                 :          0 :                                 free(sig);
     385                 :          0 :                                 return (EPKG_FATAL);
     386                 :            :                         }
     387                 :          0 :                         free(sig);
     388                 :          0 :                         rc = EPKG_OK;
     389                 :          0 :                 }
     390         [ #  # ]:          0 :                 else if (pkg_repo_file_has_ext(archive_entry_pathname(ae), ".pub")) {
     391                 :          0 :                         snprintf(key, sizeof(key), "%.*s",
     392                 :          0 :                                         (int) strlen(archive_entry_pathname(ae)) - 4,
     393                 :          0 :                                         archive_entry_pathname(ae));
     394                 :          0 :                         type = NULL;
     395                 :          0 :                         siglen = archive_entry_size(ae);
     396                 :          0 :                         sigdata = sig = xmalloc(siglen);
     397         [ #  # ]:          0 :                         if (archive_read_data(a, sig, siglen) == -1) {
     398                 :          0 :                                 pkg_emit_errno("pkg_repo_meta_extract_signature",
     399                 :            :                                                 "archive_read_data failed");
     400                 :          0 :                                 free(sig);
     401                 :          0 :                                 return (EPKG_FATAL);
     402                 :            :                         }
     403         [ #  # ]:          0 :                         if (strncmp(sig, PKGSIGN_HEAD, strlen(PKGSIGN_HEAD)) == 0) {
     404                 :          0 :                                 type = sig + strlen(PKGSIGN_HEAD);
     405                 :          0 :                                 sigdata = memchr(type, '$', siglen - ((uint8_t *)type - sig));
     406         [ #  # ]:          0 :                                 if (sigdata != NULL) {
     407                 :          0 :                                         *sigdata++ = '\0';
     408                 :            : 
     409                 :          0 :                                         siglen -= sigdata - sig;
     410                 :          0 :                                 } else {
     411                 :            :                                         /* Malformed, proceed as if no header at all. */
     412                 :          0 :                                         type = NULL;
     413                 :          0 :                                         sigdata = sig;
     414                 :            :                                 }
     415                 :          0 :                         }
     416                 :            : 
     417         [ #  # ]:          0 :                         if (type == NULL)
     418                 :          0 :                                 type = "rsa";
     419                 :          0 :                         typelen = strlen(type);
     420                 :            :                         /* Pubkey type */
     421                 :          0 :                         t = 1;
     422                 :          0 :                         keylen = strlen(key);
     423                 :          0 :                         iov[0].iov_base = &t;
     424                 :          0 :                         iov[0].iov_len = sizeof(t);
     425                 :          0 :                         iov[1].iov_base = &keylen;
     426                 :          0 :                         iov[1].iov_len = sizeof(keylen);
     427                 :          0 :                         iov[2].iov_base = key;
     428                 :          0 :                         iov[2].iov_len = keylen;
     429                 :          0 :                         iov[3].iov_base = &typelen;
     430                 :          0 :                         iov[3].iov_len = sizeof(typelen);
     431                 :          0 :                         iov[4].iov_base = __DECONST(char *, type);
     432                 :          0 :                         iov[4].iov_len = typelen;
     433                 :          0 :                         iov[5].iov_base = &siglen;
     434                 :          0 :                         iov[5].iov_len = sizeof(siglen);
     435                 :          0 :                         iov[6].iov_base = sigdata;
     436                 :          0 :                         iov[6].iov_len = siglen;
     437         [ #  # ]:          0 :                         if (writev(fd, iov, NELEM(iov)) == -1) {
     438                 :          0 :                                 pkg_emit_errno("pkg_repo_meta_extract_signature",
     439                 :            :                                                 "writev failed");
     440                 :          0 :                                 free(sig);
     441                 :          0 :                                 return (EPKG_FATAL);
     442                 :            :                         }
     443                 :          0 :                         free(sig);
     444                 :          0 :                         rc = EPKG_OK;
     445                 :          0 :                 }
     446                 :            :                 else {
     447         [ #  # ]:          0 :                         if (STREQ(archive_entry_pathname(ae), cb->fname)) {
     448         [ #  # ]:          0 :                                 if (archive_read_data_into_fd(a, cb->tfd) != 0) {
     449                 :          0 :                                         pkg_emit_error("Error extracting the archive: '%s'", archive_error_string(a));
     450                 :          0 :                                         rc = EPKG_FATAL;
     451                 :          0 :                                         break;
     452                 :            :                                 }
     453                 :          0 :                         }
     454                 :            :                 }
     455                 :            :         }
     456                 :          0 :         close(cb->tfd);
     457                 :            :         /*
     458                 :            :          * XXX: do not free resources here since the sandbox is terminated anyway
     459                 :            :          */
     460                 :          0 :         return (rc);
     461                 :          0 : }
     462                 :            : 
     463                 :            : static int
     464                 :          3 : pkg_repo_parse_sigkeys(const char *in, int inlen, pkghash **sc)
     465                 :            : {
     466                 :          3 :         const char *p = in, *end = in + inlen;
     467                 :          3 :         int rc = EPKG_OK;
     468                 :            :         enum {
     469                 :            :                 fp_parse_type,
     470                 :            :                 fp_parse_flen,
     471                 :            :                 fp_parse_file,
     472                 :            :                 fp_parse_sigtypelen,
     473                 :            :                 fp_parse_sigtype,
     474                 :            :                 fp_parse_siglen,
     475                 :            :                 fp_parse_sig
     476                 :          3 :         } state = fp_parse_type;
     477                 :          3 :         char type = 0;
     478                 :            :         unsigned char *sig;
     479                 :          3 :         int len = 0, sigtypelen = 0, tlen;
     480                 :          3 :         struct sig_cert *s = NULL;
     481                 :          3 :         bool new = false;
     482                 :            : 
     483         [ +  + ]:         45 :         while (p < end) {
     484   [ -  +  +  +  :         42 :                 switch (state) {
             +  +  +  + ]
     485                 :            :                 case fp_parse_type:
     486                 :          6 :                         type = *p;
     487   [ +  +  +  - ]:          6 :                         if (type != 0 && type != 1) {
     488                 :            :                                 /* Invalid type */
     489                 :          0 :                                 pkg_emit_error("%d is not a valid type for signature_fingerprints"
     490                 :          0 :                                                 " output", type);
     491                 :          0 :                                 return (EPKG_FATAL);
     492                 :            :                         }
     493                 :          6 :                         state = fp_parse_flen;
     494                 :          6 :                         s = NULL;
     495                 :          6 :                         p ++;
     496                 :          6 :                         break;
     497                 :            :                 case fp_parse_flen:
     498         [ +  - ]:          6 :                         if (end - p < sizeof (int)) {
     499                 :          0 :                                 pkg_emit_error("truncated reply for signature_fingerprints"
     500                 :            :                                                 " output");
     501                 :          0 :                                 return (EPKG_FATAL);
     502                 :            :                         }
     503                 :          6 :                         memcpy(&len, p, sizeof(int));
     504                 :          6 :                         state = fp_parse_file;
     505                 :          6 :                         p += sizeof(int);
     506                 :          6 :                         s = NULL;
     507                 :          6 :                         break;
     508                 :            :                 case fp_parse_file:
     509   [ +  -  -  + ]:          6 :                         if (end - p < len || len <= 0) {
     510                 :          0 :                                 pkg_emit_error("truncated reply for signature_fingerprints"
     511                 :          0 :                                                 " output, wanted %d bytes", len);
     512                 :          0 :                                 return (EPKG_FATAL);
     513                 :            :                         }
     514         [ -  + ]:          6 :                         else if (len >= MAXPATHLEN) {
     515                 :          0 :                                 pkg_emit_error("filename is incorrect for signature_fingerprints"
     516                 :          0 :                                                 " output: %d, wanted 5..%d bytes", type, len);
     517                 :          0 :                                 free(s);
     518                 :          0 :                                 return (EPKG_FATAL);
     519                 :            :                         }
     520                 :          6 :                         char *k = xstrndup(p, len);
     521                 :          6 :                         s = pkghash_get_value(*sc, k);
     522                 :          6 :                         free(k);
     523         [ +  + ]:          6 :                         if ( s == NULL) {
     524                 :          3 :                                 s = xcalloc(1, sizeof(struct sig_cert));
     525         [ +  - ]:          3 :                                 tlen = MIN(len, sizeof(s->name) - 1);
     526                 :          3 :                                 memcpy(s->name, p, tlen);
     527                 :          3 :                                 s->name[tlen] = '\0';
     528                 :          3 :                                 new = true;
     529                 :          3 :                         } else {
     530                 :          3 :                                 new = false;
     531                 :            :                         }
     532                 :          6 :                         state = fp_parse_sigtypelen;
     533                 :          6 :                         p += len;
     534                 :          6 :                         break;
     535                 :            :                 case fp_parse_sigtypelen:
     536         [ +  - ]:          6 :                         if (end - p < sizeof (int)) {
     537                 :          0 :                                 pkg_emit_error("truncated reply for signature_fingerprints"
     538                 :            :                                                 " output");
     539                 :          0 :                                 return (EPKG_FATAL);
     540                 :            :                         }
     541                 :          6 :                         memcpy(&sigtypelen, p, sizeof(int));
     542                 :          6 :                         state = fp_parse_sigtype;
     543                 :          6 :                         p += sizeof(int);
     544                 :          6 :                         break;
     545                 :            :                 case fp_parse_sigtype:
     546         [ -  + ]:          6 :                         if (s == NULL) {
     547                 :          0 :                                 pkg_emit_error("fatal state machine failure at pkg_repo_parse_sigkeys");
     548                 :          0 :                                 return (EPKG_FATAL);
     549                 :            :                         }
     550   [ +  -  +  - ]:          6 :                         if (end - p < sigtypelen || sigtypelen <= 0) {
     551                 :          0 :                                 pkg_emit_error("truncated reply for signature_fingerprints"
     552                 :          0 :                                                 " output, wanted %d bytes", sigtypelen);
     553                 :          0 :                                 return (EPKG_FATAL);
     554                 :            :                         }
     555                 :          6 :                         s->type = xstrndup(p, sigtypelen);
     556                 :          6 :                         state = fp_parse_siglen;
     557                 :          6 :                         p += sigtypelen;
     558                 :          6 :                         break;
     559                 :            :                 case fp_parse_siglen:
     560         [ -  + ]:          6 :                         if (s == NULL) {
     561                 :          0 :                                 pkg_emit_error("fatal state machine failure at pkg_repo_parse_sigkeys");
     562                 :          0 :                                 return (EPKG_FATAL);
     563                 :            :                         }
     564         [ +  - ]:          6 :                         if (end - p < sizeof (int)) {
     565                 :          0 :                                 pkg_emit_error("truncated reply for signature_fingerprints"
     566                 :            :                                                 "output");
     567                 :          0 :                                 free(s);
     568                 :          0 :                                 return (EPKG_FATAL);
     569                 :            :                         }
     570                 :          6 :                         memcpy(&len, p, sizeof(int));
     571                 :          6 :                         state = fp_parse_sig;
     572                 :          6 :                         p += sizeof(int);
     573                 :          6 :                         break;
     574                 :            :                 case fp_parse_sig:
     575         [ +  - ]:          6 :                         if (s == NULL) {
     576                 :          0 :                                 pkg_emit_error("fatal state machine failure at pkg_repo_parse_sigkeys");
     577                 :          0 :                                 return (EPKG_FATAL);
     578                 :            :                         }
     579   [ +  -  -  + ]:          6 :                         if (end - p < len || len <= 0) {
     580                 :          0 :                                 pkg_emit_error("truncated reply for signature_fingerprints"
     581                 :          0 :                                                 "output, wanted %d bytes", len);
     582                 :          0 :                                 free(s);
     583                 :          0 :                                 return (EPKG_FATAL);
     584                 :            :                         }
     585                 :          6 :                         sig = xmalloc(len);
     586                 :          6 :                         memcpy(sig, p, len);
     587         [ +  + ]:          6 :                         if (type == 0) {
     588                 :          3 :                                 s->sig = sig;
     589                 :          3 :                                 s->siglen = len;
     590                 :          3 :                         }
     591                 :            :                         else {
     592                 :          3 :                                 s->cert = sig;
     593                 :          3 :                                 s->certlen = len;
     594                 :          3 :                                 s->cert_allocated = true;
     595                 :            :                         }
     596                 :          6 :                         state = fp_parse_type;
     597                 :          6 :                         p += len;
     598                 :            : 
     599         [ +  + ]:          6 :                         if (new)
     600   [ -  +  #  # ]:          3 :                                 pkghash_safe_add(*sc, s->name, s, NULL);
     601                 :            : 
     602                 :          6 :                         break;
     603                 :            :                 }
     604                 :            :         }
     605                 :            : 
     606                 :          3 :         return (rc);
     607                 :          3 : }
     608                 :            : 
     609                 :            : static int
     610                 :         72 : pkg_repo_archive_extract_archive(int fd, const char *file,
     611                 :            :     struct pkg_repo *repo, int dest_fd,
     612                 :            :     pkghash **signatures)
     613                 :            : {
     614                 :         72 :         struct pkghash *sc = NULL;
     615                 :            :         struct sig_cert *s;
     616                 :            :         struct pkg_extract_cbdata cbdata;
     617                 :            : 
     618                 :         72 :         char *sig = NULL;
     619                 :         72 :         int rc = EPKG_OK;
     620                 :         72 :         int64_t siglen = 0;
     621                 :            : 
     622                 :            : 
     623                 :         72 :         pkg_debug(1, "PkgRepo: extracting %s of repo %s", file, pkg_repo_name(repo));
     624                 :            : 
     625                 :            :         /* Seek to the begin of file */
     626                 :         72 :         (void)lseek(fd, 0, SEEK_SET);
     627                 :            : 
     628                 :         72 :         cbdata.afd = fd;
     629                 :         72 :         cbdata.fname = file;
     630                 :         72 :         cbdata.tfd = dest_fd;
     631                 :            : 
     632         [ +  + ]:         72 :         if (pkg_repo_signature_type(repo) == SIG_PUBKEY) {
     633                 :          4 :                 cbdata.need_sig = true;
     634         [ -  + ]:          4 :                 if (pkg_emit_sandbox_get_string(pkg_repo_meta_extract_signature_pubkey,
     635         [ +  - ]:          4 :                                 &cbdata, (char **)&sig, &siglen) == EPKG_OK && sig != NULL) {
     636                 :          4 :                         s = xcalloc(1, sizeof(struct sig_cert));
     637         [ +  + ]:          4 :                         if (strncmp(sig, PKGSIGN_HEAD, strlen(PKGSIGN_HEAD)) == 0) {
     638                 :            :                                 char *sigtype, *sigstart;
     639                 :            : 
     640                 :          2 :                                 sigtype = sig + strlen(PKGSIGN_HEAD);
     641                 :          2 :                                 sigstart = memchr(sigtype, '$', siglen - (sigtype - sig));
     642         [ -  + ]:          2 :                                 if (sigstart != NULL) {
     643                 :          2 :                                         s->type = xstrndup(sigtype, sigstart - sigtype);
     644                 :          2 :                                         siglen -= (sigstart + 1) - sig;
     645                 :          2 :                                         memmove(sig, sigstart + 1, siglen);
     646                 :          2 :                                 }
     647                 :          2 :                         }
     648         [ +  + ]:          4 :                         if (s->type == NULL)
     649                 :          2 :                                 s->type = xstrdup("rsa");
     650                 :          4 :                         s->sig = sig;
     651                 :          4 :                         s->siglen = siglen;
     652                 :          4 :                         strlcpy(s->name, "signature", sizeof(s->name));
     653   [ -  +  #  # ]:          4 :                         pkghash_safe_add(sc, s->name, s, NULL);
     654                 :          4 :                 }
     655                 :          4 :         }
     656         [ +  + ]:         68 :         else if (pkg_repo_signature_type(repo) == SIG_FINGERPRINT) {
     657         [ -  + ]:          6 :                 if (pkg_emit_sandbox_get_string(pkg_repo_meta_extract_signature_fingerprints,
     658   [ +  -  -  + ]:          3 :                                 &cbdata, (char **)&sig, &siglen) == EPKG_OK && sig != NULL &&
     659                 :          3 :                                 siglen > 0) {
     660         [ -  + ]:          3 :                         if (pkg_repo_parse_sigkeys(sig, siglen, &sc) == EPKG_FATAL) {
     661                 :          0 :                                 return (EPKG_FATAL);
     662                 :            :                         }
     663                 :          3 :                         free(sig);
     664         [ +  - ]:          3 :                         if (!pkg_repo_check_fingerprint(repo, sc, true)) {
     665                 :          0 :                                 return (EPKG_FATAL);
     666                 :            :                         }
     667                 :          3 :                 }
     668                 :            :                 else {
     669                 :          0 :                         pkg_emit_error("No signature found");
     670                 :          0 :                         return (EPKG_FATAL);
     671                 :            :                 }
     672                 :          3 :         }
     673                 :            :         else {
     674                 :         65 :                 cbdata.need_sig = false;
     675   [ -  +  -  + ]:        130 :                 if (pkg_emit_sandbox_get_string(pkg_repo_meta_extract_signature_pubkey,
     676                 :         65 :                         &cbdata, (char **)&sig, &siglen) == EPKG_OK) {
     677                 :         65 :                         free(sig);
     678                 :         65 :                 }
     679                 :            :                 else {
     680                 :          0 :                         pkg_emit_error("Repo extraction failed");
     681                 :          0 :                         return (EPKG_FATAL);
     682                 :            :                 }
     683                 :            :         }
     684                 :         72 :         (void)lseek(fd, 0, SEEK_SET);
     685         [ -  + ]:         72 :         if (dest_fd != -1)
     686                 :         72 :                 (void)lseek(dest_fd, 0, SEEK_SET);
     687                 :            : 
     688         [ -  + ]:         72 :         if (rc == EPKG_OK) {
     689         [ +  - ]:         72 :                 if (signatures != NULL)
     690                 :         72 :                         *signatures = sc;
     691                 :            :                 else
     692                 :          0 :                         pkg_repo_signatures_free(sc);
     693                 :         72 :         }
     694                 :            :         else {
     695                 :          0 :                 pkg_repo_signatures_free(sc);
     696                 :            :         }
     697                 :            : 
     698                 :         72 :         return rc;
     699                 :         72 : }
     700                 :            : 
     701                 :            : static int
     702                 :         72 : pkg_repo_archive_extract_check_archive(int fd, const char *file,
     703                 :            :     struct pkg_repo *repo, int dest_fd)
     704                 :            : {
     705                 :         72 :         pkghash *sc = NULL;
     706                 :            :         struct sig_cert *s;
     707                 :            :         const struct pkgsign_ctx *sctx;
     708                 :            :         const char *rkey;
     709                 :            :         signature_t sigtype;
     710                 :            :         pkghash_it it;
     711                 :            :         int ret;
     712                 :            : 
     713                 :         72 :         ret = EPKG_OK;
     714                 :            : 
     715   [ -  +  -  + ]:        144 :         if (pkg_repo_archive_extract_archive(fd, file, repo, dest_fd, &sc)
     716                 :         72 :                         != EPKG_OK)
     717                 :          0 :                 return (EPKG_FATAL);
     718                 :            : 
     719                 :         72 :         sctx = NULL;
     720                 :         72 :         sigtype = pkg_repo_signature_type(repo);
     721                 :            : 
     722         [ +  + ]:         72 :         if (sigtype == SIG_PUBKEY) {
     723                 :          4 :                 rkey = pkg_repo_key(repo);
     724         [ +  - ]:          4 :                 if (rkey == NULL) {
     725                 :          0 :                         pkg_emit_error("No PUBKEY defined. Removing "
     726                 :            :                             "repository.");
     727                 :          0 :                         return (EPKG_FATAL);
     728                 :            :                 }
     729         [ +  - ]:          4 :                 if (sc == NULL) {
     730                 :          0 :                         pkg_emit_error("No signature found in the repository.  "
     731                 :          0 :                                         "Can not validate against %s key.", rkey);
     732                 :          0 :                         return (EPKG_FATAL);
     733                 :            :                 }
     734                 :          4 :                 it = pkghash_iterator(sc);
     735                 :          4 :                 pkghash_next(&it); /* check that there is content is already above */
     736                 :          4 :                 s = (struct sig_cert *)it.value;
     737                 :            : 
     738                 :          4 :                 ret = pkgsign_new_verify(s->type, &sctx);
     739         [ -  + ]:          4 :                 if (ret != EPKG_OK) {
     740                 :          0 :                         pkg_emit_error("'%s' signer not found", s->type);
     741                 :          0 :                         return (EPKG_FATAL);
     742                 :            :                 }
     743                 :            : 
     744                 :            :                 /*
     745                 :            :                  * Note that pkgsign_verify is not the same method or use-case
     746                 :            :                  * as pkgsign_verify_cert.
     747                 :            :                  *
     748                 :            :                  * The primary difference is that pkgsign_verify takes a file
     749                 :            :                  * to load the pubkey from, while pkgsign_verify_cert expects
     750                 :            :                  * that the key will simply be passed in for it to verify
     751                 :            :                  * against.
     752                 :            :                  *
     753                 :            :                  * Some versions of pkgsign_verify were also suboptimal, in the
     754                 :            :                  * sense that they signed the hex encoding of a SHA256 checksum
     755                 :            :                  * over the repo rather than raw.  This required some kludges
     756                 :            :                  * to work with, but future pkgsign_verify implementations
     757                 :            :                  * should not follow in its path.
     758                 :            :                  */
     759                 :          4 :                 ret = pkgsign_verify(sctx, rkey, s->sig, s->siglen, dest_fd);
     760         [ -  + ]:          4 :                 if (ret != EPKG_OK) {
     761                 :          0 :                         pkg_emit_error("Invalid signature, "
     762                 :            :                                         "removing repository.");
     763                 :          0 :                         return (EPKG_FATAL);
     764                 :            :                 }
     765                 :          4 :         }
     766         [ +  + ]:         68 :         else if (pkg_repo_signature_type(repo) == SIG_FINGERPRINT) {
     767                 :          3 :                 const char *signer_name = NULL;
     768                 :            : 
     769                 :          3 :                 it = pkghash_iterator(sc);
     770         [ -  + ]:          3 :                 while (pkghash_next(&it)) {
     771                 :          3 :                         s = (struct sig_cert *)it.value;
     772                 :            : 
     773                 :            :                         /*
     774                 :            :                          * Each signature may use a different signer, so we'll potentially
     775                 :            :                          * grab a new context for each one.  This is cheaper than it sounds,
     776                 :            :                          * verifying contexts are stashed in a pkghash for re-use.
     777                 :            :                          */
     778   [ -  +  #  # ]:          3 :                         if (sctx == NULL || !STREQ(s->type, signer_name)) {
     779                 :          3 :                                 ret = pkgsign_new_verify(s->type, &sctx);
     780         [ +  - ]:          3 :                                 if (ret != EPKG_OK) {
     781                 :          0 :                                         pkg_emit_error("'%s' signer not found", s->type);
     782                 :          0 :                                         return (EPKG_FATAL);
     783                 :            :                                 }
     784                 :            : 
     785                 :          3 :                                 signer_name = pkgsign_impl_name(sctx);
     786                 :          3 :                         }
     787                 :            : 
     788                 :          6 :                         ret = pkgsign_verify_cert(sctx, s->cert, s->certlen, s->sig,
     789                 :          3 :                              s->siglen, dest_fd);
     790   [ +  -  -  + ]:          3 :                         if (ret == EPKG_OK && s->trusted) {
     791                 :          3 :                                 break;
     792                 :            :                         }
     793                 :          0 :                         ret = EPKG_FATAL;
     794                 :            :                 }
     795         [ -  + ]:          3 :                 if (ret != EPKG_OK) {
     796                 :          0 :                         pkg_emit_error("No trusted certificate has been used "
     797                 :            :                             "to sign the repository");
     798                 :          0 :                         return (EPKG_FATAL);
     799                 :            :                 }
     800                 :          3 :         }
     801                 :            : 
     802                 :         72 :         return (EPKG_OK);
     803                 :         72 : }
     804                 :            : 
     805                 :            : int
     806                 :        134 : pkg_repo_fetch_data_fd(struct pkg_repo *repo, struct pkg_repo_content *prc)
     807                 :            : {
     808                 :            :         int fd;
     809                 :            :         const char *tmpdir;
     810                 :            :         char tmp[MAXPATHLEN];
     811                 :            :         struct stat st;
     812                 :        134 :         int rc = EPKG_OK;
     813                 :            : 
     814                 :        134 :         fd = pkg_repo_fetch_remote_tmp(repo, repo->meta->data, "pkg", &prc->mtime, &rc, false);
     815         [ +  + ]:        134 :         if (fd == -1) {
     816         [ +  + ]:         62 :                 if (rc == EPKG_UPTODATE)
     817                 :         54 :                         return (rc);
     818                 :         16 :                 fd = pkg_repo_fetch_remote_tmp(repo, repo->meta->data,
     819                 :          8 :                     packing_format_to_string(repo->meta->packing_format), &prc->mtime, &rc, false);
     820         [ -  + ]:          8 :                 if (fd == -1)
     821                 :          8 :                         return (EPKG_FATAL);
     822                 :          0 :         }
     823                 :            : 
     824                 :         72 :         tmpdir = getenv("TMPDIR");
     825         [ +  - ]:         72 :         if (tmpdir == NULL)
     826                 :          0 :                 tmpdir = "/tmp";
     827                 :         72 :         snprintf(tmp, sizeof(tmp), "%s/%s.XXXXXX", tmpdir, repo->meta->data);
     828                 :         72 :         prc->data_fd = mkstemp(tmp);
     829         [ +  - ]:         72 :         if (prc->data_fd == -1) {
     830                 :          0 :                 pkg_emit_error("Cound not create temporary file %s, "
     831                 :          0 :                     "aborting update.\n", tmp);
     832                 :          0 :                 close(fd);
     833                 :          0 :                 return (EPKG_FATAL);
     834                 :            :         }
     835                 :            : 
     836                 :         72 :         unlink(tmp);
     837         [ -  + ]:         72 :         if (pkg_repo_archive_extract_check_archive(fd, repo->meta->data, repo, prc->data_fd) != EPKG_OK) {
     838                 :          0 :                 close(prc->data_fd);
     839                 :          0 :                 close(fd);
     840                 :          0 :                 return (EPKG_FATAL);
     841                 :            :         }
     842                 :            : 
     843                 :         72 :         close(fd);
     844         [ +  - ]:         72 :         if (fstat(prc->data_fd, &st) == -1) {
     845                 :          0 :                 close(prc->data_fd);
     846                 :          0 :                 return (EPKG_FATAL);
     847                 :            :         }
     848                 :            : 
     849                 :         72 :         return (EPKG_OK);
     850                 :        134 : }
     851                 :            : 
     852                 :            : int
     853                 :          8 : pkg_repo_fetch_remote_extract_fd(struct pkg_repo *repo, struct pkg_repo_content *prc)
     854                 :            : {
     855                 :            :         int fd;
     856                 :            :         const char *tmpdir;
     857                 :            :         char tmp[MAXPATHLEN];
     858                 :            :         struct stat st;
     859                 :          8 :         int rc = EPKG_OK;
     860                 :            : 
     861                 :          8 :         fd = pkg_repo_fetch_remote_tmp(repo, repo->meta->manifests, "pkg", &prc->mtime, &rc, false);
     862         [ -  + ]:          8 :         if (fd == -1) {
     863         [ -  + ]:          8 :                 if (rc == EPKG_UPTODATE)
     864                 :          0 :                         return (rc);
     865                 :            : 
     866                 :         16 :                 fd = pkg_repo_fetch_remote_tmp(repo, repo->meta->manifests,
     867                 :          8 :                     packing_format_to_string(repo->meta->packing_format), &prc->mtime, &rc, false);
     868         [ -  + ]:          8 :                 if (fd == -1)
     869                 :          8 :                         return (EPKG_FATAL);
     870                 :          0 :         }
     871                 :            : 
     872                 :          0 :         tmpdir = getenv("TMPDIR");
     873         [ #  # ]:          0 :         if (tmpdir == NULL)
     874                 :          0 :                 tmpdir = "/tmp";
     875                 :          0 :         snprintf(tmp, sizeof(tmp), "%s/%s.XXXXXX", tmpdir, repo->meta->manifests);
     876                 :            : 
     877                 :          0 :         prc->manifest_fd = mkstemp(tmp);
     878         [ #  # ]:          0 :         if (prc->manifest_fd == -1) {
     879                 :          0 :                 pkg_emit_error("Could not create temporary file %s, "
     880                 :          0 :                                 "aborting update.\n", tmp);
     881                 :          0 :                 close(fd);
     882                 :          0 :                 return (EPKG_FATAL);
     883                 :            :         }
     884                 :            : 
     885                 :          0 :         (void)unlink(tmp);
     886   [ #  #  #  # ]:          0 :         if (pkg_repo_archive_extract_check_archive(fd, repo->meta->manifests, repo, prc->manifest_fd)
     887                 :          0 :                         != EPKG_OK) {
     888                 :          0 :                 close(prc->manifest_fd);
     889                 :          0 :                 close(fd);
     890                 :          0 :                 return (EPKG_FATAL);
     891                 :            :         }
     892                 :            : 
     893                 :            :         /* Thus removing archived file as well */
     894                 :          0 :         close(fd);
     895         [ #  # ]:          0 :         if (fstat(prc->manifest_fd, &st) == -1) {
     896                 :          0 :                 close(prc->manifest_fd);
     897                 :          0 :                 return (EPKG_FATAL);
     898                 :            :         }
     899                 :            : 
     900                 :          0 :         prc->manifest_len = st.st_size;
     901                 :            : 
     902                 :          0 :         return (EPKG_OK);
     903                 :          8 : }
     904                 :            : 
     905                 :            : struct pkg_repo_check_cbdata {
     906                 :            :         unsigned char *map;
     907                 :            :         size_t len;
     908                 :            :         const char *name;
     909                 :            : };
     910                 :            : 
     911                 :            : static int
     912                 :          0 : pkg_repo_meta_extract_pubkey(int fd, void *ud)
     913                 :            : {
     914                 :          0 :         struct pkg_repo_check_cbdata *cbdata = ud;
     915                 :            :         struct ucl_parser *parser;
     916                 :            :         ucl_object_t *top;
     917                 :            :         const ucl_object_t *obj, *cur, *elt;
     918                 :          0 :         ucl_object_iter_t iter = NULL;
     919                 :            :         struct iovec iov[2];
     920                 :          0 :         int rc = EPKG_OK;
     921                 :          0 :         int64_t res_len = 0;
     922                 :            : 
     923                 :          0 :         parser = ucl_parser_new(UCL_PARSER_NO_FILEVARS);
     924         [ #  # ]:          0 :         if (!ucl_parser_add_chunk(parser, cbdata->map, cbdata->len)) {
     925                 :          0 :                 pkg_emit_error("cannot parse repository meta from %s",
     926                 :          0 :                                 ucl_parser_get_error(parser));
     927                 :          0 :                 ucl_parser_free(parser);
     928                 :          0 :                 return (EPKG_FATAL);
     929                 :            :         }
     930                 :            : 
     931                 :          0 :         top = ucl_parser_get_object(parser);
     932                 :          0 :         ucl_parser_free(parser);
     933                 :            : 
     934                 :            :         /* Now search for the required key */
     935                 :          0 :         obj = ucl_object_find_key(top, "cert");
     936         [ #  # ]:          0 :         if (obj == NULL) {
     937                 :          0 :                 pkg_emit_error("cannot find key for signature %s in meta",
     938                 :          0 :                                 cbdata->name);
     939                 :          0 :                 ucl_object_unref(top);
     940                 :          0 :                 return (EPKG_FATAL);
     941                 :            :         }
     942         [ #  # ]:          0 :         while((cur = ucl_iterate_object(obj, &iter, false)) != NULL) {
     943                 :          0 :                 elt = ucl_object_find_key(cur, "name");
     944   [ #  #  #  # ]:          0 :                 if (elt == NULL || elt->type != UCL_STRING)
     945                 :          0 :                         continue;
     946         [ #  # ]:          0 :                 if (!STREQ(ucl_object_tostring(elt), cbdata->name))
     947                 :          0 :                         continue;
     948                 :          0 :                 elt = ucl_object_find_key(cur, "data");
     949   [ #  #  #  # ]:          0 :                 if (elt == NULL || elt->type != UCL_STRING)
     950                 :          0 :                         continue;
     951                 :            : 
     952                 :            :                 /* +1 to include \0 at the end */
     953                 :          0 :                 res_len = elt->len + 1;
     954                 :          0 :                 iov[0].iov_base = (void *)ucl_object_tostring(elt);
     955                 :          0 :                 iov[0].iov_len = res_len;
     956         [ #  # ]:          0 :                 if (writev(fd, iov, 1) == -1) {
     957                 :          0 :                         pkg_emit_errno("pkg_repo_meta_extract_pubkey",
     958                 :            :                                         "writev error");
     959                 :          0 :                         rc = EPKG_FATAL;
     960                 :          0 :                         break;
     961                 :            :                 }
     962                 :            :         }
     963                 :            : 
     964                 :          0 :         ucl_object_unref(top);
     965                 :            : 
     966                 :          0 :         return (rc);
     967                 :          0 : }
     968                 :            : 
     969                 :            : int
     970                 :        135 : pkg_repo_open(struct pkg_repo *repo)
     971                 :            : {
     972                 :            :         int reposfd;
     973                 :            : 
     974         [ -  + ]:        135 :         if (repo->dfd != -1)
     975                 :          0 :                 return (EPKG_OK);
     976                 :            : 
     977                 :        135 :         reposfd = pkg_get_reposdirfd();
     978         [ +  - ]:        135 :         if (reposfd == -1)
     979                 :          0 :                 return (EPKG_FATAL);
     980                 :            : 
     981                 :        135 :         repo->dfd = openat(reposfd, repo->name, O_DIRECTORY|O_CLOEXEC);
     982         [ +  + ]:        135 :         if (repo->dfd == -1) {
     983         [ +  - ]:         68 :                 if (mkdirat(reposfd, repo->name, 0755) == -1)
     984                 :          0 :                         return (EPKG_FATAL);
     985                 :            : 
     986                 :         68 :                 repo->dfd = openat(reposfd, repo->name, O_DIRECTORY|O_CLOEXEC);
     987         [ +  - ]:         68 :                 if (repo->dfd == -1)
     988                 :          0 :                         return (EPKG_FATAL);
     989                 :         68 :         }
     990                 :            : 
     991                 :        135 :         return (EPKG_OK);
     992                 :        135 : }
     993                 :            : 
     994                 :            : int
     995                 :        134 : pkg_repo_fetch_meta(struct pkg_repo *repo, time_t *t)
     996                 :            : {
     997                 :            :         char filepath[MAXPATHLEN];
     998                 :            :         struct pkg_repo_meta *nmeta;
     999                 :            :         const struct pkgsign_ctx *sctx;
    1000                 :            :         struct stat st;
    1001                 :        134 :         unsigned char *map = NULL;
    1002                 :            :         int fd, dbdirfd, metafd;
    1003                 :        134 :         int rc = EPKG_OK, ret;
    1004                 :        134 :         pkghash *sc = NULL;
    1005                 :            :         struct sig_cert *s;
    1006                 :            :         struct pkg_repo_check_cbdata cbdata;
    1007                 :        134 :         bool newscheme = false;
    1008                 :            :         pkghash_it it;
    1009                 :            : 
    1010                 :        134 :         dbdirfd = pkg_get_dbdirfd();
    1011                 :        134 :         sctx = NULL;
    1012         [ +  - ]:        134 :         if (repo->dfd == -1) {
    1013         [ #  # ]:          0 :                 if (pkg_repo_open(repo) == EPKG_FATAL)
    1014                 :          0 :                         return (EPKG_FATAL);
    1015                 :          0 :         }
    1016                 :        134 :         fd = pkg_repo_fetch_remote_tmp(repo, "meta", "conf", t, &rc, true);
    1017         [ +  + ]:        134 :         if (fd != -1) {
    1018                 :         75 :                 newscheme = true;
    1019                 :         75 :                 metafd = fd;
    1020                 :         75 :                 fd = openat(repo->dfd, "meta", O_RDWR|O_CREAT|O_TRUNC, 0644);
    1021         [ +  - ]:         75 :                 if (fd == -1) {
    1022                 :          0 :                         close(metafd);
    1023                 :          0 :                         return (EPKG_FATAL);
    1024                 :            :                 }
    1025                 :         75 :                 goto load_meta;
    1026         [ +  + ]:         59 :         } else if (rc == EPKG_UPTODATE) {
    1027                 :         54 :                 return (EPKG_UPTODATE);
    1028                 :            :         }
    1029                 :            : 
    1030                 :            :         /* TODO: remove this backward compatibility some day */
    1031                 :          5 :         fd = pkg_repo_fetch_remote_tmp(repo, "meta", "txz", t, &rc, false);
    1032         [ -  + ]:          5 :         if (fd == -1)
    1033                 :          5 :                 return (rc);
    1034                 :            : 
    1035                 :          0 :         metafd = openat(repo->dfd, "meta", O_RDWR|O_CREAT|O_TRUNC, 0644);
    1036         [ #  # ]:          0 :         if (metafd == -1) {
    1037                 :          0 :                 close(fd);
    1038                 :          0 :                 return (EPKG_FATAL);
    1039                 :            :         }
    1040                 :            : 
    1041         [ #  # ]:          0 :         if (pkg_repo_signature_type(repo) == SIG_PUBKEY) {
    1042         [ #  # ]:          0 :                 if ((rc = pkg_repo_archive_extract_check_archive(fd, "meta", repo, metafd)) != EPKG_OK) {
    1043                 :          0 :                         close (fd);
    1044                 :          0 :                         return (rc);
    1045                 :            :                 }
    1046                 :          0 :                 goto load_meta;
    1047                 :            :         }
    1048                 :            : 
    1049                 :            :         /*
    1050                 :            :          * For fingerprints we cannot just load pubkeys as they could be in metafile itself
    1051                 :            :          * To do it, we parse meta in sandbox and for each unloaded pubkey we try to return
    1052                 :            :          * a corresponding key from meta file.
    1053                 :            :          */
    1054                 :            : 
    1055   [ #  #  #  #  :          0 :         if ((rc = pkg_repo_archive_extract_archive(fd, "meta", repo,
                   #  # ]
    1056                 :          0 :             metafd, &sc)) != EPKG_OK) {
    1057                 :          0 :                 close(metafd);
    1058                 :          0 :                 unlinkat(dbdirfd, filepath, 0);
    1059                 :          0 :                 close (fd);
    1060                 :          0 :                 return (rc);
    1061                 :            :         }
    1062                 :          0 :         close(metafd);
    1063                 :          0 :         close(fd);
    1064                 :            : 
    1065   [ #  #  #  # ]:          0 :         if (repo->signature_type == SIG_FINGERPRINT && repo->trusted_fp == NULL) {
    1066         [ #  # ]:          0 :                 if (pkg_repo_load_fingerprints(repo) != EPKG_OK)
    1067                 :          0 :                         return (EPKG_FATAL);
    1068                 :          0 :         }
    1069                 :            : 
    1070                 :            :         /* Map meta file for extracting pubkeys from it */
    1071         [ #  # ]:          0 :         if ((metafd = openat(repo->dfd, "meta", O_RDONLY)) == -1) {
    1072                 :          0 :                 pkg_emit_errno("pkg_repo_fetch_meta", "cannot open meta fetched");
    1073                 :          0 :                 rc = EPKG_FATAL;
    1074                 :          0 :                 goto cleanup;
    1075                 :            :         }
    1076                 :            : 
    1077         [ #  # ]:          0 :         if (fstat(metafd, &st) == -1) {
    1078                 :          0 :                 pkg_emit_errno("pkg_repo_fetch_meta", "cannot stat meta fetched");
    1079                 :          0 :                 rc = EPKG_FATAL;
    1080                 :          0 :                 goto cleanup;
    1081                 :            :         }
    1082                 :            : 
    1083                 :          0 :         map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
    1084         [ #  # ]:          0 :         if (map == MAP_FAILED) {
    1085                 :          0 :                 pkg_emit_errno("pkg_repo_fetch_meta", "cannot mmap meta fetched");
    1086                 :          0 :                 rc = EPKG_FATAL;
    1087                 :          0 :                 goto cleanup;
    1088                 :            :         }
    1089                 :            : 
    1090         [ #  # ]:          0 :         if (repo->signature_type == SIG_FINGERPRINT) {
    1091                 :          0 :                 const char *signer_name = NULL;
    1092                 :            : 
    1093                 :          0 :                 cbdata.len = st.st_size;
    1094                 :          0 :                 cbdata.map = map;
    1095                 :          0 :                 it = pkghash_iterator(sc);
    1096         [ #  # ]:          0 :                 while (pkghash_next(&it)) {
    1097                 :          0 :                         s = (struct sig_cert *) it.value;
    1098   [ #  #  #  # ]:          0 :                         if (s->siglen != 0 && s->certlen == 0) {
    1099                 :            :                                 /*
    1100                 :            :                                  * We need to load this pubkey from meta
    1101                 :            :                                  */
    1102                 :          0 :                                 cbdata.name = s->name;
    1103   [ #  #  #  # ]:          0 :                                 if (pkg_emit_sandbox_get_string(pkg_repo_meta_extract_pubkey, &cbdata,
    1104                 :          0 :                                                 (char **)&s->cert, &s->certlen) != EPKG_OK) {
    1105                 :          0 :                                         rc = EPKG_FATAL;
    1106                 :          0 :                                         goto cleanup;
    1107                 :            :                                 }
    1108                 :          0 :                                 s->cert_allocated = true;
    1109                 :          0 :                         }
    1110                 :            :                 }
    1111                 :            : 
    1112         [ #  # ]:          0 :                 if (!pkg_repo_check_fingerprint(repo, sc, true)) {
    1113                 :          0 :                         rc = EPKG_FATAL;
    1114                 :          0 :                         goto cleanup;
    1115                 :            :                 }
    1116                 :            : 
    1117                 :          0 :                 ret = EPKG_FATAL;
    1118                 :          0 :                 it = pkghash_iterator(sc);
    1119         [ #  # ]:          0 :                 while (pkghash_next(&it)) {
    1120                 :          0 :                         s = (struct sig_cert *) it.value;
    1121                 :            : 
    1122                 :            :                         /*
    1123                 :            :                          * Just as above, each one may have a different type associated with
    1124                 :            :                          * it, so grab a new one each time.
    1125                 :            :                          */
    1126   [ #  #  #  # ]:          0 :                         if (sctx == NULL || !STREQ(s->type, signer_name)) {
    1127                 :          0 :                                 ret = pkgsign_new_verify(s->type, &sctx);
    1128         [ #  # ]:          0 :                                 if (ret != EPKG_OK) {
    1129                 :          0 :                                         pkg_emit_error("'%s' signer not found", s->type);
    1130                 :          0 :                                         rc = EPKG_FATAL;
    1131                 :          0 :                                         goto cleanup;
    1132                 :            :                                 }
    1133                 :            : 
    1134                 :          0 :                                 signer_name = pkgsign_impl_name(sctx);
    1135                 :          0 :                         }
    1136                 :            : 
    1137                 :          0 :                         ret = pkgsign_verify_cert(sctx, s->cert, s->certlen, s->sig, s->siglen,
    1138                 :          0 :                                 metafd);
    1139   [ #  #  #  # ]:          0 :                         if (ret == EPKG_OK && s->trusted)
    1140                 :          0 :                                 break;
    1141                 :          0 :                         ret = EPKG_FATAL;
    1142                 :            :                 }
    1143         [ #  # ]:          0 :                 if (ret != EPKG_OK) {
    1144                 :          0 :                         pkg_emit_error("No trusted certificate has been used "
    1145                 :            :                                 "to sign the repository");
    1146                 :          0 :                         rc = EPKG_FATAL;
    1147                 :          0 :                         goto cleanup;
    1148                 :            :                 }
    1149                 :          0 :         }
    1150                 :            : 
    1151                 :            : load_meta:
    1152         [ +  + ]:         75 :         if ((rc = pkg_repo_meta_load(metafd, &nmeta)) != EPKG_OK) {
    1153         [ +  - ]:          3 :                 if (map != NULL)
    1154                 :          0 :                         munmap(map, st.st_size);
    1155                 :            : 
    1156                 :          3 :                 return (rc);
    1157         [ -  + ]:         72 :         } else if (newscheme) {
    1158                 :         72 :                 pkg_repo_meta_dump_fd(nmeta, fd);
    1159                 :         72 :         }
    1160                 :            : 
    1161         [ +  - ]:         72 :         if (repo->meta != NULL)
    1162                 :         72 :                 pkg_repo_meta_free(repo->meta);
    1163                 :            : 
    1164                 :         72 :         repo->meta = nmeta;
    1165                 :            : 
    1166                 :            : cleanup:
    1167         [ +  - ]:         72 :         if (map != NULL)
    1168                 :          0 :                 munmap(map, st.st_size);
    1169                 :            : 
    1170         [ +  - ]:         72 :         if (sc != NULL)
    1171                 :          0 :                 pkg_repo_signatures_free(sc);
    1172                 :            : 
    1173         [ +  - ]:         72 :         if (rc != EPKG_OK)
    1174                 :          0 :                 unlinkat(dbdirfd, filepath, 0);
    1175                 :            : 
    1176                 :         72 :         return (rc);
    1177                 :        134 : }
    1178                 :            : 
    1179                 :            : static struct fingerprint *
    1180                 :          3 : pkg_repo_parse_fingerprint(ucl_object_t *obj)
    1181                 :            : {
    1182                 :            :         const ucl_object_t *cur;
    1183                 :          3 :         ucl_object_iter_t it = NULL;
    1184                 :          3 :         const char *function = NULL, *fp = NULL;
    1185                 :          3 :         hash_t fct = HASH_UNKNOWN;
    1186                 :          3 :         struct fingerprint *f = NULL;
    1187                 :            :         const char *key;
    1188                 :            : 
    1189         [ +  + ]:          9 :         while ((cur = ucl_iterate_object(obj, &it, true))) {
    1190                 :          6 :                 key = ucl_object_key(cur);
    1191         [ -  + ]:          6 :                 if (cur->type != UCL_STRING)
    1192                 :          0 :                         continue;
    1193                 :            : 
    1194         [ +  + ]:          6 :                 if (STRIEQ(key, "function")) {
    1195                 :          3 :                         function = ucl_object_tostring(cur);
    1196                 :          3 :                         continue;
    1197                 :            :                 }
    1198                 :            : 
    1199         [ -  + ]:          3 :                 if (STRIEQ(key, "fingerprint")) {
    1200                 :          3 :                         fp = ucl_object_tostring(cur);
    1201                 :          3 :                         continue;
    1202                 :            :                 }
    1203                 :            :         }
    1204                 :            : 
    1205   [ +  -  -  + ]:          3 :         if (fp == NULL || function == NULL)
    1206                 :          0 :                 return (NULL);
    1207                 :            : 
    1208         [ -  + ]:          3 :         if (STRIEQ(function, "sha256"))
    1209                 :          3 :                 fct = HASH_SHA256;
    1210                 :            : 
    1211         [ +  - ]:          3 :         if (fct == HASH_UNKNOWN) {
    1212                 :          0 :                 pkg_emit_error("Unsupported hashing function: %s", function);
    1213                 :          0 :                 return (NULL);
    1214                 :            :         }
    1215                 :            : 
    1216                 :          3 :         f = xcalloc(1, sizeof(struct fingerprint));
    1217                 :          3 :         f->type = fct;
    1218                 :          3 :         strlcpy(f->hash, fp, sizeof(f->hash));
    1219                 :            : 
    1220                 :          3 :         return (f);
    1221                 :          3 : }
    1222                 :            : 
    1223                 :            : static struct fingerprint *
    1224                 :          3 : pkg_repo_load_fingerprint(const char *dir, const char *filename)
    1225                 :            : {
    1226                 :          3 :         ucl_object_t *obj = NULL;
    1227                 :          3 :         struct ucl_parser *p = NULL;
    1228                 :            :         char path[MAXPATHLEN];
    1229                 :          3 :         struct fingerprint *f = NULL;
    1230                 :            :         int fd;
    1231                 :            : 
    1232                 :          3 :         snprintf(path, sizeof(path), "%s/%s", dir, filename);
    1233                 :          3 :         fd = openat(ctx.rootfd, RELATIVE_PATH(path), O_RDONLY);
    1234         [ +  - ]:          3 :         if (fd == -1) {
    1235                 :          0 :                 pkg_emit_error("cannot load fingerprints from %s: %s",
    1236                 :          0 :                                 path, strerror(errno));
    1237                 :          0 :                 return (NULL);
    1238                 :            :         }
    1239                 :            : 
    1240                 :          3 :         p = ucl_parser_new(UCL_PARSER_NO_FILEVARS);
    1241                 :            : 
    1242         [ +  - ]:          3 :         if (!ucl_parser_add_fd(p, fd)) {
    1243                 :          0 :                 pkg_emit_error("cannot parse fingerprints: %s", ucl_parser_get_error(p));
    1244                 :          0 :                 ucl_parser_free(p);
    1245                 :          0 :                 close(fd);
    1246                 :          0 :                 return (NULL);
    1247                 :            :         }
    1248                 :            : 
    1249                 :          3 :         obj = ucl_parser_get_object(p);
    1250                 :          3 :         close(fd);
    1251                 :            : 
    1252                 :            :         /* Silently return if obj is NULL */
    1253         [ +  - ]:          3 :         if (!obj)
    1254                 :          0 :                 return(NULL);
    1255                 :            : 
    1256         [ -  + ]:          3 :         if (obj->type == UCL_OBJECT)
    1257                 :          3 :                 f = pkg_repo_parse_fingerprint(obj);
    1258                 :            : 
    1259                 :          3 :         ucl_object_unref(obj);
    1260                 :          3 :         ucl_parser_free(p);
    1261                 :            : 
    1262                 :          3 :         return (f);
    1263                 :          3 : }
    1264                 :            : 
    1265                 :            : static int
    1266                 :          6 : pkg_repo_load_fingerprints_from_path(const char *path, pkghash **f)
    1267                 :            : {
    1268                 :            :         DIR *d;
    1269                 :            :         int fd;
    1270                 :            :         struct dirent *ent;
    1271                 :          6 :         struct fingerprint *finger = NULL;
    1272                 :            : 
    1273                 :          6 :         *f = NULL;
    1274                 :            : 
    1275         [ +  - ]:          6 :         if ((fd = openat(ctx.rootfd, RELATIVE_PATH(path), O_DIRECTORY)) == -1) {
    1276                 :          0 :                 pkg_emit_error("Error opening the trusted directory %s", path);
    1277                 :          0 :                 return (EPKG_FATAL);
    1278                 :            :         }
    1279         [ +  - ]:          6 :         if ((d = fdopendir(fd)) == NULL) {
    1280                 :          0 :                 pkg_emit_error("Error fdopening the trusted directory %s", path);
    1281                 :          0 :                 return (EPKG_FATAL);
    1282                 :            :         }
    1283                 :            : 
    1284         [ +  + ]:         21 :         while ((ent = readdir(d))) {
    1285   [ +  +  +  + ]:         15 :                 if (STREQ(ent->d_name, ".") ||
    1286                 :          9 :                     STREQ(ent->d_name, ".."))
    1287                 :         12 :                         continue;
    1288                 :          3 :                 finger = pkg_repo_load_fingerprint(path, ent->d_name);
    1289         [ -  + ]:          3 :                 if (finger != NULL)
    1290   [ -  +  #  # ]:          3 :                         pkghash_safe_add(*f, finger->hash, finger, NULL);
    1291                 :            :         }
    1292                 :            : 
    1293                 :          6 :         closedir(d);
    1294                 :            : 
    1295                 :          6 :         return (EPKG_OK);
    1296                 :          6 : }
    1297                 :            : 
    1298                 :            : int
    1299                 :          3 : pkg_repo_load_fingerprints(struct pkg_repo *repo)
    1300                 :            : {
    1301                 :            :         char path[MAXPATHLEN];
    1302                 :            :         struct stat st;
    1303                 :            : 
    1304                 :          3 :         snprintf(path, sizeof(path), "%s/trusted", pkg_repo_fingerprints(repo));
    1305                 :            : 
    1306         [ -  + ]:          3 :         if ((pkg_repo_load_fingerprints_from_path(path, &repo->trusted_fp)) != EPKG_OK) {
    1307                 :          0 :                 pkg_emit_error("Error loading trusted certificates");
    1308                 :          0 :                 return (EPKG_FATAL);
    1309                 :            :         }
    1310                 :            : 
    1311         [ +  - ]:          3 :         if (pkghash_count(repo->trusted_fp) == 0) {
    1312                 :          0 :                 pkg_emit_error("No trusted certificates");
    1313                 :          0 :                 return (EPKG_FATAL);
    1314                 :            :         }
    1315                 :            : 
    1316                 :          3 :         snprintf(path, sizeof(path), "%s/revoked", pkg_repo_fingerprints(repo));
    1317                 :            :         /* Absence of revoked certificates is not a fatal error */
    1318         [ -  + ]:          3 :         if (fstatat(ctx.rootfd, RELATIVE_PATH(path), &st, 0) != -1) {
    1319         [ -  + ]:          3 :                 if ((pkg_repo_load_fingerprints_from_path(path, &repo->revoked_fp)) != EPKG_OK) {
    1320                 :          0 :                         pkg_emit_error("Error loading revoked certificates");
    1321                 :          0 :                         return (EPKG_FATAL);
    1322                 :            :                 }
    1323                 :          3 :         }
    1324                 :            : 
    1325                 :          3 :         return (EPKG_OK);
    1326                 :          3 : }
    1327                 :            : 
    1328                 :            : 
    1329                 :            : int
    1330                 :         10 : pkg_repo_fetch_package(struct pkg *pkg)
    1331                 :            : {
    1332                 :            :         struct pkg_repo *repo;
    1333                 :            : 
    1334         [ +  - ]:         10 :         if (pkg->repo == NULL) {
    1335                 :          0 :                 pkg_emit_error("Trying to fetch package without repository");
    1336                 :          0 :                 return (EPKG_FATAL);
    1337                 :            :         }
    1338                 :            : 
    1339                 :         10 :         repo = pkg->repo;
    1340         [ +  - ]:         10 :         if (repo->ops->fetch_pkg == NULL) {
    1341                 :          0 :                 pkg_emit_error("Repository %s does not support fetching", repo->name);
    1342                 :          0 :                 return (EPKG_FATAL);
    1343                 :            :         }
    1344                 :            : 
    1345                 :         10 :         return (repo->ops->fetch_pkg(repo, pkg));
    1346                 :         10 : }
    1347                 :            : 
    1348                 :            : int
    1349                 :          0 : pkg_repo_mirror_package(struct pkg *pkg, const char *destdir)
    1350                 :            : {
    1351                 :            :         struct pkg_repo *repo;
    1352                 :            : 
    1353         [ #  # ]:          0 :         if (pkg->repo == NULL) {
    1354                 :          0 :                 pkg_emit_error("Trying to mirror package without repository");
    1355                 :          0 :                 return (EPKG_FATAL);
    1356                 :            :         }
    1357                 :            : 
    1358                 :          0 :         repo = pkg->repo;
    1359         [ #  # ]:          0 :         if (repo->ops->mirror_pkg == NULL) {
    1360                 :          0 :                 pkg_emit_error("Repository %s does not support mirroring", repo->name);
    1361                 :          0 :                 return (EPKG_FATAL);
    1362                 :            :         }
    1363                 :            : 
    1364                 :          0 :         return (repo->ops->mirror_pkg(repo, pkg, destdir));
    1365                 :          0 : }
    1366                 :            : 
    1367                 :            : int
    1368                 :        356 : pkg_repo_cached_name(struct pkg *pkg, char *dest, size_t destlen)
    1369                 :            : {
    1370                 :            :         struct pkg_repo *repo;
    1371                 :            : 
    1372         [ +  + ]:        356 :         if (pkg->repo == NULL)
    1373                 :         12 :                 return (EPKG_FATAL);
    1374                 :            : 
    1375                 :        344 :         repo = pkg->repo;
    1376         [ +  - ]:        344 :         if (repo->ops->get_cached_name == NULL)
    1377                 :          0 :                 return (EPKG_FATAL);
    1378                 :            : 
    1379                 :        344 :         return (repo->ops->get_cached_name(repo, pkg, dest, destlen));
    1380                 :        356 : }

Generated by: LCOV version 1.15