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