Line data Source code
1 : /*-
2 : * Copyright (c) 2011-2013 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 : *
8 : * All rights reserved.
9 : *
10 : * Redistribution and use in source and binary forms, with or without
11 : * modification, are permitted provided that the following conditions
12 : * are met:
13 : * 1. Redistributions of source code must retain the above copyright
14 : * notice, this list of conditions and the following disclaimer
15 : * in this position and unchanged.
16 : * 2. Redistributions in binary form must reproduce the above copyright
17 : * notice, this list of conditions and the following disclaimer in the
18 : * documentation and/or other materials provided with the distribution.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
21 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 : * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
24 : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 : */
31 :
32 : #include <sys/types.h>
33 : #include <sys/stat.h>
34 : #include <sys/sysctl.h>
35 : #include <sys/uio.h>
36 :
37 : #include <archive_entry.h>
38 : #include <assert.h>
39 : #include <fts.h>
40 : #include <libgen.h>
41 : #include <sqlite3.h>
42 : #include <string.h>
43 : #include <dirent.h>
44 : #define _WITH_GETLINE
45 : #include <stdio.h>
46 : #include <stdbool.h>
47 : #include <sysexits.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 :
59 : struct sig_cert {
60 : char name[MAXPATHLEN];
61 : char *sig;
62 : int64_t siglen;
63 : char *cert;
64 : int64_t certlen;
65 : bool cert_allocated;
66 : UT_hash_handle hh;
67 : bool trusted;
68 : };
69 :
70 : static int
71 16 : pkg_repo_fetch_remote_tmp(struct pkg_repo *repo,
72 : const char *filename, const char *extension, time_t *t, int *rc)
73 : {
74 : char url[MAXPATHLEN];
75 : char tmp[MAXPATHLEN];
76 : int fd;
77 : const char *tmpdir, *dot;
78 :
79 : /*
80 : * XXX: here we support old naming scheme, such as filename.yaml
81 : */
82 16 : dot = strrchr(filename, '.');
83 16 : if (dot != NULL) {
84 8 : snprintf(tmp, MIN(sizeof(tmp), dot - filename + 1), "%s", filename);
85 8 : snprintf(url, sizeof(url), "%s/%s.%s", pkg_repo_url(repo), tmp,
86 : extension);
87 : }
88 : else {
89 8 : snprintf(url, sizeof(url), "%s/%s.%s", pkg_repo_url(repo), filename,
90 : extension);
91 : }
92 :
93 16 : tmpdir = getenv("TMPDIR");
94 16 : if (tmpdir == NULL)
95 0 : tmpdir = "/tmp";
96 16 : mkdirs(tmpdir);
97 16 : snprintf(tmp, sizeof(tmp), "%s/%s.%s.XXXXXX", tmpdir, filename, extension);
98 :
99 16 : fd = mkstemp(tmp);
100 16 : if (fd == -1) {
101 0 : pkg_emit_error("Could not create temporary file %s, "
102 : "aborting update.\n", tmp);
103 0 : *rc = EPKG_FATAL;
104 0 : return (-1);
105 : }
106 16 : (void)unlink(tmp);
107 :
108 16 : if ((*rc = pkg_fetch_file_to_fd(repo, url, fd, t, -1, 0)) != EPKG_OK) {
109 2 : close(fd);
110 2 : fd = -1;
111 : }
112 :
113 16 : return (fd);
114 : }
115 :
116 : static bool
117 0 : pkg_repo_file_has_ext(const char *path, const char *ext)
118 : {
119 : size_t n, l;
120 0 : const char *p = NULL;
121 :
122 0 : n = strlen(path);
123 0 : l = strlen(ext);
124 0 : p = &path[n - l];
125 :
126 0 : if (strcmp(p, ext) == 0)
127 0 : return (true);
128 :
129 0 : return (false);
130 : }
131 :
132 : static bool
133 0 : pkg_repo_check_fingerprint(struct pkg_repo *repo, struct sig_cert *sc, bool fatal)
134 : {
135 0 : struct fingerprint *f = NULL;
136 : char *hash;
137 0 : int nbgood = 0;
138 0 : struct sig_cert *s = NULL, *stmp = NULL;
139 0 : struct pkg_repo_meta_key *mk = NULL;
140 :
141 0 : if (HASH_COUNT(sc) == 0) {
142 0 : if (fatal)
143 0 : pkg_emit_error("No signature found");
144 0 : return (false);
145 : }
146 :
147 : /* load fingerprints */
148 0 : if (repo->trusted_fp == NULL) {
149 0 : if (pkg_repo_load_fingerprints(repo) != EPKG_OK)
150 0 : return (false);
151 : }
152 :
153 0 : HASH_ITER(hh, sc, s, stmp) {
154 0 : if (s->sig != NULL && s->cert == NULL) {
155 : /*
156 : * We may want to check meta
157 : */
158 0 : if (repo->meta != NULL && repo->meta->keys != NULL)
159 0 : HASH_FIND_STR(repo->meta->keys, s->name, mk);
160 :
161 0 : if (mk != NULL && mk->pubkey != NULL) {
162 0 : s->cert = mk->pubkey;
163 0 : s->certlen = strlen(mk->pubkey);
164 : }
165 : else {
166 0 : if (fatal)
167 0 : pkg_emit_error("No key with name %s has been found", s->name);
168 0 : return (false);
169 : }
170 : }
171 0 : else if (s->sig == NULL) {
172 0 : if (fatal)
173 0 : pkg_emit_error("No signature with name %s has been found", s->name);
174 0 : return (false);
175 : }
176 :
177 0 : s->trusted = false;
178 0 : hash = pkg_checksum_data(s->cert, s->certlen,
179 : PKG_HASH_TYPE_SHA256_HEX);
180 0 : HASH_FIND_STR(repo->revoked_fp, hash, f);
181 0 : if (f != NULL) {
182 0 : if (fatal)
183 0 : pkg_emit_error("At least one of the "
184 : " certificates has been revoked");
185 :
186 0 : free(hash);
187 0 : return (false);
188 : }
189 :
190 0 : HASH_FIND_STR(repo->trusted_fp, hash, f);
191 0 : free(hash);
192 0 : if (f != NULL) {
193 0 : nbgood++;
194 0 : s->trusted = true;
195 : }
196 : }
197 :
198 0 : if (nbgood == 0) {
199 0 : if (fatal)
200 0 : pkg_emit_error("No trusted public keys found");
201 :
202 0 : return (false);
203 : }
204 :
205 0 : return (true);
206 : }
207 :
208 : static void
209 0 : pkg_repo_signatures_free(struct sig_cert *sc)
210 : {
211 : struct sig_cert *s, *stmp;
212 :
213 0 : HASH_ITER(hh, sc, s, stmp) {
214 0 : HASH_DELETE(hh, sc, s);
215 0 : free(s->sig);
216 0 : if (s->cert_allocated)
217 0 : free(s->cert);
218 0 : free(s);
219 : }
220 0 : }
221 :
222 :
223 : struct pkg_extract_cbdata {
224 : int afd;
225 : int tfd;
226 : const char *fname;
227 : bool need_sig;
228 : };
229 :
230 : static int
231 0 : pkg_repo_meta_extract_signature_pubkey(int fd, void *ud)
232 : {
233 0 : struct archive *a = NULL;
234 0 : struct archive_entry *ae = NULL;
235 0 : struct pkg_extract_cbdata *cb = ud;
236 : int siglen;
237 : void *sig;
238 0 : int rc = EPKG_FATAL;
239 :
240 0 : pkg_debug(1, "PkgRepo: extracting signature of repo in a sandbox");
241 :
242 0 : a = archive_read_new();
243 0 : archive_read_support_filter_all(a);
244 0 : archive_read_support_format_tar(a);
245 :
246 0 : archive_read_open_fd(a, cb->afd, 4096);
247 :
248 0 : while (archive_read_next_header(a, &ae) == ARCHIVE_OK) {
249 0 : if (cb->need_sig && strcmp(archive_entry_pathname(ae), "signature") == 0) {
250 0 : siglen = archive_entry_size(ae);
251 0 : sig = malloc(siglen);
252 0 : if (sig == NULL) {
253 0 : pkg_emit_errno("pkg_repo_meta_extract_signature",
254 : "malloc failed");
255 0 : return (EPKG_FATAL);
256 : }
257 0 : if (archive_read_data(a, sig, siglen) == -1) {
258 0 : pkg_emit_errno("pkg_repo_meta_extract_signature",
259 : "archive_read_data failed");
260 0 : free(sig);
261 0 : return (EPKG_FATAL);
262 : }
263 0 : if (write(fd, sig, siglen) == -1) {
264 0 : pkg_emit_errno("pkg_repo_meta_extract_signature",
265 : "write failed");
266 0 : free(sig);
267 0 : return (EPKG_FATAL);
268 : }
269 0 : free(sig);
270 0 : rc = EPKG_OK;
271 : }
272 0 : else if (strcmp(archive_entry_pathname(ae), cb->fname) == 0) {
273 0 : if (archive_read_data_into_fd(a, cb->tfd) != 0) {
274 0 : pkg_emit_errno("archive_read_extract", "extract error");
275 0 : rc = EPKG_FATAL;
276 0 : break;
277 : }
278 0 : else if (!cb->need_sig) {
279 0 : rc = EPKG_OK;
280 : }
281 : }
282 : }
283 :
284 0 : close(cb->tfd);
285 : /*
286 : * XXX: do not free resources here since the sandbox is terminated anyway
287 : */
288 0 : return (rc);
289 : }
290 : /*
291 : * We use here the following format:
292 : * <type(0|1)><namelen(int)><name><datalen(int)><data>
293 : */
294 : static int
295 0 : pkg_repo_meta_extract_signature_fingerprints(int fd, void *ud)
296 : {
297 0 : struct archive *a = NULL;
298 0 : struct archive_entry *ae = NULL;
299 0 : struct pkg_extract_cbdata *cb = ud;
300 : int siglen, keylen;
301 : void *sig;
302 0 : int rc = EPKG_FATAL;
303 : char key[MAXPATHLEN], t;
304 : struct iovec iov[5];
305 :
306 0 : pkg_debug(1, "PkgRepo: extracting signature of repo in a sandbox");
307 :
308 0 : a = archive_read_new();
309 0 : archive_read_support_filter_all(a);
310 0 : archive_read_support_format_tar(a);
311 :
312 0 : archive_read_open_fd(a, cb->afd, 4096);
313 :
314 0 : while (archive_read_next_header(a, &ae) == ARCHIVE_OK) {
315 0 : if (pkg_repo_file_has_ext(archive_entry_pathname(ae), ".sig")) {
316 0 : snprintf(key, sizeof(key), "%.*s",
317 0 : (int) strlen(archive_entry_pathname(ae)) - 4,
318 : archive_entry_pathname(ae));
319 0 : siglen = archive_entry_size(ae);
320 0 : sig = malloc(siglen);
321 0 : if (sig == NULL) {
322 0 : pkg_emit_errno("pkg_repo_meta_extract_signature",
323 : "malloc failed");
324 0 : return (EPKG_FATAL);
325 : }
326 0 : if (archive_read_data(a, sig, siglen) == -1) {
327 0 : pkg_emit_errno("pkg_repo_meta_extract_signature",
328 : "archive_read_data failed");
329 0 : free(sig);
330 0 : return (EPKG_FATAL);
331 : }
332 : /* Signature type */
333 0 : t = 0;
334 0 : keylen = strlen(key);
335 0 : iov[0].iov_base = &t;
336 0 : iov[0].iov_len = sizeof(t);
337 0 : iov[1].iov_base = &keylen;
338 0 : iov[1].iov_len = sizeof(keylen);
339 0 : iov[2].iov_base = key;
340 0 : iov[2].iov_len = keylen;
341 0 : iov[3].iov_base = &siglen;
342 0 : iov[3].iov_len = sizeof(siglen);
343 0 : iov[4].iov_base = sig;
344 0 : iov[4].iov_len = siglen;
345 0 : if (writev(fd, iov, NELEM(iov)) == -1) {
346 0 : pkg_emit_errno("pkg_repo_meta_extract_signature",
347 : "writev failed");
348 0 : free(sig);
349 0 : return (EPKG_FATAL);
350 : }
351 0 : free(sig);
352 0 : rc = EPKG_OK;
353 : }
354 0 : else if (pkg_repo_file_has_ext(archive_entry_pathname(ae), ".pub")) {
355 0 : snprintf(key, sizeof(key), "%.*s",
356 0 : (int) strlen(archive_entry_pathname(ae)) - 4,
357 : archive_entry_pathname(ae));
358 0 : siglen = archive_entry_size(ae);
359 0 : sig = malloc(siglen);
360 0 : if (sig == NULL) {
361 0 : pkg_emit_errno("pkg_repo_meta_extract_signature",
362 : "malloc failed");
363 0 : return (EPKG_FATAL);
364 : }
365 0 : if (archive_read_data(a, sig, siglen) == -1) {
366 0 : pkg_emit_errno("pkg_repo_meta_extract_signature",
367 : "archive_read_data failed");
368 0 : free(sig);
369 0 : return (EPKG_FATAL);
370 : }
371 : /* Pubkey type */
372 0 : t = 1;
373 0 : keylen = strlen(key);
374 0 : iov[0].iov_base = &t;
375 0 : iov[0].iov_len = sizeof(t);
376 0 : iov[1].iov_base = &keylen;
377 0 : iov[1].iov_len = sizeof(keylen);
378 0 : iov[2].iov_base = key;
379 0 : iov[2].iov_len = keylen;
380 0 : iov[3].iov_base = &siglen;
381 0 : iov[3].iov_len = sizeof(siglen);
382 0 : iov[4].iov_base = sig;
383 0 : iov[4].iov_len = siglen;
384 0 : if (writev(fd, iov, NELEM(iov)) == -1) {
385 0 : pkg_emit_errno("pkg_repo_meta_extract_signature",
386 : "writev failed");
387 0 : free(sig);
388 0 : return (EPKG_FATAL);
389 : }
390 0 : free(sig);
391 0 : rc = EPKG_OK;
392 : }
393 : else {
394 0 : if (strcmp(archive_entry_pathname(ae), cb->fname) == 0) {
395 0 : if (archive_read_data_into_fd(a, cb->tfd) != 0) {
396 0 : pkg_emit_errno("archive_read_extract", "extract error");
397 0 : rc = EPKG_FATAL;
398 0 : break;
399 : }
400 : }
401 : }
402 : }
403 0 : close(cb->tfd);
404 : /*
405 : * XXX: do not free resources here since the sandbox is terminated anyway
406 : */
407 0 : return (rc);
408 : }
409 :
410 : static int
411 0 : pkg_repo_parse_sigkeys(const char *in, int inlen, struct sig_cert **sc)
412 : {
413 0 : const char *p = in, *end = in + inlen;
414 0 : int rc = EPKG_OK;
415 : enum {
416 : fp_parse_type,
417 : fp_parse_flen,
418 : fp_parse_file,
419 : fp_parse_siglen,
420 : fp_parse_sig
421 0 : } state = fp_parse_type;
422 0 : char type = 0;
423 : unsigned char *sig;
424 0 : int len = 0, tlen;
425 0 : struct sig_cert *s = NULL;
426 0 : bool new = false;
427 :
428 0 : while (p < end) {
429 0 : switch (state) {
430 : case fp_parse_type:
431 0 : type = *p;
432 0 : if (type != 0 && type != 1) {
433 : /* Invalid type */
434 0 : pkg_emit_error("%d is not a valid type for signature_fingerprints"
435 : "output", type);
436 0 : return (EPKG_FATAL);
437 : }
438 0 : state = fp_parse_flen;
439 0 : s = NULL;
440 0 : p ++;
441 0 : break;
442 : case fp_parse_flen:
443 0 : if (end - p < sizeof (int)) {
444 0 : pkg_emit_error("truncated reply for signature_fingerprints"
445 : "output", type);
446 0 : return (EPKG_FATAL);
447 : }
448 0 : memcpy(&len, p, sizeof(int));
449 0 : state = fp_parse_file;
450 0 : p += sizeof(int);
451 0 : s = NULL;
452 0 : break;
453 : case fp_parse_file:
454 0 : if (end - p < len || len <= 0) {
455 0 : pkg_emit_error("truncated reply for signature_fingerprints"
456 : "output, wanted %d bytes", type, len);
457 0 : return (EPKG_FATAL);
458 : }
459 0 : else if (len >= MAXPATHLEN) {
460 0 : pkg_emit_error("filename is incorrect for signature_fingerprints"
461 : "output: %d, wanted 5..%d bytes", type, len, MAXPATHLEN);
462 0 : free(s);
463 0 : return (EPKG_FATAL);
464 : }
465 0 : HASH_FIND(hh, *sc, p, len, s);
466 0 : if (s == NULL) {
467 0 : s = calloc(1, sizeof(struct sig_cert));
468 0 : if (s == NULL) {
469 0 : pkg_emit_errno("pkg_repo_parse_sigkeys", "calloc failed");
470 0 : return (EPKG_FATAL);
471 : }
472 0 : tlen = MIN(len, sizeof(s->name) - 1);
473 0 : memcpy(s->name, p, tlen);
474 0 : s->name[tlen] = '\0';
475 0 : new = true;
476 : }
477 : else {
478 0 : new = false;
479 : }
480 0 : state = fp_parse_siglen;
481 0 : p += len;
482 0 : break;
483 : case fp_parse_siglen:
484 0 : if (s == NULL) {
485 0 : pkg_emit_error("fatal state machine failure at pkg_repo_parse_sigkeys");
486 0 : return (EPKG_FATAL);
487 : }
488 0 : if (end - p < sizeof (int)) {
489 0 : pkg_emit_error("truncated reply for signature_fingerprints"
490 : "output", type);
491 0 : free(s);
492 0 : return (EPKG_FATAL);
493 : }
494 0 : memcpy(&len, p, sizeof(int));
495 0 : state = fp_parse_sig;
496 0 : p += sizeof(int);
497 0 : break;
498 : case fp_parse_sig:
499 0 : if (s == NULL) {
500 0 : pkg_emit_error("fatal state machine failure at pkg_repo_parse_sigkeys");
501 0 : return (EPKG_FATAL);
502 : }
503 0 : if (end - p < len || len <= 0) {
504 0 : pkg_emit_error("truncated reply for signature_fingerprints"
505 : "output, wanted %d bytes", type, len);
506 0 : free(s);
507 0 : return (EPKG_FATAL);
508 : }
509 0 : sig = malloc(len);
510 0 : if (sig == NULL) {
511 0 : pkg_emit_errno("pkg_repo_parse_sigkeys", "malloc failed");
512 0 : free(s);
513 0 : return (EPKG_FATAL);
514 : }
515 0 : memcpy(sig, p, len);
516 0 : if (type == 0) {
517 0 : s->sig = sig;
518 0 : s->siglen = len;
519 : }
520 : else {
521 0 : s->cert = sig;
522 0 : s->certlen = len;
523 0 : s->cert_allocated = true;
524 : }
525 0 : state = fp_parse_type;
526 0 : p += len;
527 :
528 0 : if (new)
529 0 : HASH_ADD_STR(*sc, name, s);
530 :
531 0 : break;
532 : }
533 : }
534 :
535 0 : return (rc);
536 : }
537 :
538 : static int
539 14 : pkg_repo_archive_extract_archive(int fd, const char *file,
540 : const char *dest, struct pkg_repo *repo, int dest_fd,
541 : struct sig_cert **signatures)
542 : {
543 14 : struct sig_cert *sc = NULL, *s;
544 : struct pkg_extract_cbdata cbdata;
545 :
546 14 : char *sig = NULL;
547 14 : int rc = EPKG_OK;
548 14 : int64_t siglen = 0;
549 :
550 :
551 14 : pkg_debug(1, "PkgRepo: extracting %s of repo %s", file, pkg_repo_name(repo));
552 :
553 : /* Seek to the begin of file */
554 14 : (void)lseek(fd, 0, SEEK_SET);
555 :
556 14 : cbdata.afd = fd;
557 14 : cbdata.fname = file;
558 14 : if (dest_fd != -1) {
559 7 : cbdata.tfd = dest_fd;
560 : }
561 7 : else if (dest != NULL) {
562 7 : cbdata.tfd = open (dest, O_WRONLY | O_CREAT | O_TRUNC,
563 : 0644);
564 7 : if (cbdata.tfd == -1) {
565 0 : pkg_emit_errno("archive_read_extract", "open error");
566 0 : rc = EPKG_FATAL;
567 0 : goto cleanup;
568 : }
569 7 : fchown (fd, 0, 0);
570 : }
571 : else {
572 0 : pkg_emit_error("internal error: both fd and name are invalid");
573 0 : return (EPKG_FATAL);
574 : }
575 :
576 14 : if (pkg_repo_signature_type(repo) == SIG_PUBKEY) {
577 0 : cbdata.need_sig = true;
578 0 : if (pkg_emit_sandbox_get_string(pkg_repo_meta_extract_signature_pubkey,
579 0 : &cbdata, (char **)&sig, &siglen) == EPKG_OK && sig != NULL) {
580 0 : s = calloc(1, sizeof(struct sig_cert));
581 0 : if (s == NULL) {
582 0 : pkg_emit_errno("pkg_repo_archive_extract_archive",
583 : "malloc failed");
584 0 : rc = EPKG_FATAL;
585 0 : goto cleanup;
586 : }
587 0 : s->sig = sig;
588 0 : s->siglen = siglen;
589 0 : strlcpy(s->name, "signature", sizeof(s->name));
590 0 : HASH_ADD_STR(sc, name, s);
591 : }
592 : }
593 14 : else if (pkg_repo_signature_type(repo) == SIG_FINGERPRINT) {
594 0 : if (pkg_emit_sandbox_get_string(pkg_repo_meta_extract_signature_fingerprints,
595 0 : &cbdata, (char **)&sig, &siglen) == EPKG_OK && sig != NULL &&
596 0 : siglen > 0) {
597 0 : if (pkg_repo_parse_sigkeys(sig, siglen, &sc) == EPKG_FATAL) {
598 0 : return (EPKG_FATAL);
599 : }
600 0 : free(sig);
601 0 : if (!pkg_repo_check_fingerprint(repo, sc, true)) {
602 0 : return (EPKG_FATAL);
603 : }
604 : }
605 : else {
606 0 : pkg_emit_error("No signature found");
607 0 : return (EPKG_FATAL);
608 : }
609 : }
610 : else {
611 14 : cbdata.need_sig = false;
612 14 : if (pkg_emit_sandbox_get_string(pkg_repo_meta_extract_signature_pubkey,
613 : &cbdata, (char **)&sig, &siglen) == EPKG_OK) {
614 14 : free(sig);
615 : }
616 : else {
617 0 : pkg_emit_error("Repo extraction failed");
618 0 : return (EPKG_FATAL);
619 : }
620 : }
621 14 : (void)lseek(fd, 0, SEEK_SET);
622 14 : if (dest_fd != -1)
623 7 : (void)lseek(dest_fd, 0, SEEK_SET);
624 :
625 : cleanup:
626 14 : if (rc == EPKG_OK) {
627 14 : if (signatures != NULL)
628 14 : *signatures = sc;
629 : else
630 0 : pkg_repo_signatures_free(sc);
631 : }
632 : else {
633 0 : pkg_repo_signatures_free(sc);
634 : }
635 :
636 14 : if (rc != EPKG_OK)
637 0 : unlink(dest);
638 :
639 14 : return rc;
640 : }
641 :
642 : static int
643 7 : pkg_repo_archive_extract_check_archive(int fd, const char *file,
644 : const char *dest, struct pkg_repo *repo, int dest_fd)
645 : {
646 7 : struct sig_cert *sc = NULL, *s, *stmp;
647 : int ret, rc;
648 :
649 7 : ret = rc = EPKG_OK;
650 :
651 7 : if (pkg_repo_archive_extract_archive(fd, file, dest, repo, dest_fd, &sc)
652 : != EPKG_OK)
653 0 : return (EPKG_FATAL);
654 :
655 7 : if (pkg_repo_signature_type(repo) == SIG_PUBKEY) {
656 0 : if (pkg_repo_key(repo) == NULL) {
657 0 : pkg_emit_error("No PUBKEY defined. Removing "
658 : "repository.");
659 0 : rc = EPKG_FATAL;
660 0 : goto cleanup;
661 : }
662 0 : if (sc == NULL) {
663 0 : pkg_emit_error("No signature found in the repository. "
664 : "Can not validate against %s key.", pkg_repo_key(repo));
665 0 : rc = EPKG_FATAL;
666 0 : goto cleanup;
667 : }
668 : /*
669 : * Here are dragons:
670 : * 1) rsa_verify is NOT rsa_verify_cert
671 : * 2) siglen must be reduced by one to support this legacy method
672 : *
673 : * by @bdrewery
674 : */
675 0 : ret = rsa_verify(dest, pkg_repo_key(repo), sc->sig, sc->siglen - 1,
676 : dest_fd);
677 0 : if (ret != EPKG_OK) {
678 0 : pkg_emit_error("Invalid signature, "
679 : "removing repository.");
680 0 : rc = EPKG_FATAL;
681 0 : goto cleanup;
682 : }
683 : }
684 7 : else if (pkg_repo_signature_type(repo) == SIG_FINGERPRINT) {
685 0 : HASH_ITER(hh, sc, s, stmp) {
686 0 : ret = rsa_verify_cert(dest, s->cert, s->certlen, s->sig, s->siglen,
687 : dest_fd);
688 0 : if (ret == EPKG_OK && s->trusted) {
689 0 : break;
690 : }
691 0 : ret = EPKG_FATAL;
692 : }
693 0 : if (ret != EPKG_OK) {
694 0 : pkg_emit_error("No trusted certificate has been used "
695 : "to sign the repository");
696 0 : rc = EPKG_FATAL;
697 0 : goto cleanup;
698 : }
699 : }
700 :
701 : cleanup:
702 7 : if (rc != EPKG_OK && dest != NULL)
703 0 : unlink(dest);
704 :
705 7 : return rc;
706 : }
707 :
708 : static int
709 8 : pkg_repo_fetch_remote_extract_fd(struct pkg_repo *repo, const char *filename,
710 : time_t *t, int *rc)
711 : {
712 : int fd, dest_fd;
713 : const char *tmpdir;
714 : char tmp[MAXPATHLEN];
715 :
716 8 : fd = pkg_repo_fetch_remote_tmp(repo, filename,
717 8 : packing_format_to_string(repo->meta->packing_format), t, rc);
718 8 : if (fd == -1)
719 1 : return (-1);
720 :
721 7 : tmpdir = getenv("TMPDIR");
722 7 : if (tmpdir == NULL)
723 0 : tmpdir = "/tmp";
724 7 : snprintf(tmp, sizeof(tmp), "%s/%s.XXXXXX", tmpdir, filename);
725 :
726 7 : dest_fd = mkstemp(tmp);
727 7 : if (dest_fd == -1) {
728 0 : pkg_emit_error("Could not create temporary file %s, "
729 : "aborting update.\n", tmp);
730 0 : close(fd);
731 0 : *rc = EPKG_FATAL;
732 0 : return (-1);
733 : }
734 :
735 7 : (void)unlink(tmp);
736 7 : if (pkg_repo_archive_extract_check_archive(fd, filename, NULL, repo, dest_fd)
737 : != EPKG_OK) {
738 0 : *rc = EPKG_FATAL;
739 0 : close(dest_fd);
740 0 : close(fd);
741 0 : return (-1);
742 : }
743 :
744 : /* Thus removing archived file as well */
745 7 : close(fd);
746 :
747 7 : return (dest_fd);
748 : }
749 :
750 : unsigned char *
751 8 : pkg_repo_fetch_remote_extract_mmap(struct pkg_repo *repo, const char *filename,
752 : time_t *t, int *rc, size_t *sz)
753 : {
754 : int fd;
755 : struct stat st;
756 : unsigned char *map;
757 :
758 8 : fd = pkg_repo_fetch_remote_extract_fd(repo, filename, t, rc);
759 8 : if (fd == -1) {
760 1 : return (NULL);
761 : }
762 :
763 7 : if (fstat(fd, &st) == -1) {
764 0 : close(fd);
765 0 : return (MAP_FAILED);
766 : }
767 :
768 7 : *sz = st.st_size;
769 : if (st.st_size > SSIZE_MAX) {
770 : pkg_emit_error("%s too large", filename);
771 : close(fd);
772 : return (MAP_FAILED);
773 : }
774 :
775 7 : map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
776 7 : close(fd);
777 7 : if (map == MAP_FAILED) {
778 0 : pkg_emit_errno("pkg_repo_fetch_remote_mmap", "cannot mmap fetched");
779 0 : *rc = EPKG_FATAL;
780 0 : return (MAP_FAILED);
781 : }
782 :
783 7 : return (map);
784 : }
785 :
786 : FILE *
787 0 : pkg_repo_fetch_remote_extract_tmp(struct pkg_repo *repo, const char *filename,
788 : time_t *t, int *rc)
789 : {
790 : int dest_fd;
791 : FILE *res;
792 :
793 0 : dest_fd = pkg_repo_fetch_remote_extract_fd(repo, filename, t, rc);
794 0 : if (dest_fd == -1) {
795 0 : *rc = EPKG_FATAL;
796 0 : return (NULL);
797 : }
798 :
799 0 : res = fdopen(dest_fd, "r");
800 0 : if (res == NULL) {
801 0 : pkg_emit_errno("fdopen", "digest open failed");
802 0 : *rc = EPKG_FATAL;
803 0 : close(dest_fd);
804 0 : return (NULL);
805 : }
806 :
807 0 : *rc = EPKG_OK;
808 0 : return (res);
809 : }
810 :
811 : struct pkg_repo_check_cbdata {
812 : unsigned char *map;
813 : size_t len;
814 : const char *name;
815 : };
816 :
817 : static int
818 0 : pkg_repo_meta_extract_pubkey(int fd, void *ud)
819 : {
820 0 : struct pkg_repo_check_cbdata *cbdata = ud;
821 : struct ucl_parser *parser;
822 : ucl_object_t *top;
823 : const ucl_object_t *obj, *cur, *elt;
824 0 : ucl_object_iter_t iter = NULL;
825 : struct iovec iov[2];
826 0 : int rc = EPKG_OK;
827 0 : int64_t res_len = 0;
828 0 : bool found = false;
829 :
830 0 : parser = ucl_parser_new(0);
831 0 : if (!ucl_parser_add_chunk(parser, cbdata->map, cbdata->len)) {
832 0 : pkg_emit_error("cannot parse repository meta from %s",
833 : ucl_parser_get_error(parser));
834 0 : ucl_parser_free(parser);
835 0 : return (EPKG_FATAL);
836 : }
837 :
838 0 : top = ucl_parser_get_object(parser);
839 0 : ucl_parser_free(parser);
840 :
841 : /* Now search for the required key */
842 0 : obj = ucl_object_find_key(top, "cert");
843 0 : if (obj == NULL) {
844 0 : pkg_emit_error("cannot find key for signature %s in meta",
845 : cbdata->name);
846 0 : rc = EPKG_FATAL;
847 : }
848 : else {
849 0 : while(!found && (cur = ucl_iterate_object(obj, &iter, false)) != NULL) {
850 0 : elt = ucl_object_find_key(cur, "name");
851 0 : if (elt != NULL && elt->type == UCL_STRING) {
852 0 : if (strcmp(ucl_object_tostring(elt), cbdata->name) == 0) {
853 0 : elt = ucl_object_find_key(cur, "data");
854 0 : if (elt == NULL || elt->type != UCL_STRING)
855 0 : continue;
856 :
857 : /* +1 to include \0 at the end */
858 0 : res_len = elt->len + 1;
859 0 : iov[0].iov_base = (void *)ucl_object_tostring(elt);
860 0 : iov[0].iov_len = res_len;
861 0 : if (writev(fd, iov, 1) == -1) {
862 0 : pkg_emit_errno("pkg_repo_meta_extract_pubkey",
863 : "writev error");
864 0 : rc = EPKG_FATAL;
865 0 : break;
866 : }
867 0 : found = true;
868 : }
869 : }
870 : }
871 : }
872 :
873 0 : ucl_object_unref(top);
874 :
875 0 : return (rc);
876 : }
877 :
878 : int
879 8 : pkg_repo_fetch_meta(struct pkg_repo *repo, time_t *t)
880 : {
881 : char filepath[MAXPATHLEN];
882 : struct pkg_repo_meta *nmeta;
883 : struct stat st;
884 8 : const char *dbdir = NULL;
885 8 : unsigned char *map = NULL;
886 : int fd;
887 8 : int rc = EPKG_OK, ret;
888 8 : struct sig_cert *sc = NULL, *s, *stmp;
889 : struct pkg_repo_check_cbdata cbdata;
890 :
891 8 : dbdir = pkg_object_string(pkg_config_get("PKG_DBDIR"));
892 :
893 8 : fd = pkg_repo_fetch_remote_tmp(repo, "meta", "txz", t, &rc);
894 8 : if (fd == -1)
895 1 : return (rc);
896 :
897 7 : snprintf(filepath, sizeof(filepath), "%s/%s.meta", dbdir, pkg_repo_name(repo));
898 :
899 : /* Remove old metafile */
900 7 : if (unlink (filepath) == -1 && errno != ENOENT) {
901 0 : close(fd);
902 0 : return (EPKG_FATAL);
903 : }
904 :
905 7 : if (pkg_repo_signature_type(repo) == SIG_PUBKEY) {
906 0 : if ((rc = pkg_repo_archive_extract_check_archive(fd, "meta", filepath, repo, -1)) != EPKG_OK) {
907 0 : close (fd);
908 0 : return (rc);
909 : }
910 0 : goto load_meta;
911 : }
912 :
913 : /*
914 : * For fingerprints we cannot just load pubkeys as they could be in metafile itself
915 : * To do it, we parse meta in sandbox and for each unloaded pubkey we try to return
916 : * a corresponding key from meta file.
917 : */
918 :
919 7 : if ((rc = pkg_repo_archive_extract_archive(fd, "meta", filepath, repo, -1, &sc)) != EPKG_OK) {
920 0 : close (fd);
921 0 : return (rc);
922 : }
923 :
924 7 : close(fd);
925 :
926 7 : if (repo->signature_type == SIG_FINGERPRINT && repo->trusted_fp == NULL) {
927 0 : if (pkg_repo_load_fingerprints(repo) != EPKG_OK)
928 0 : return (EPKG_FATAL);
929 : }
930 :
931 : /* Map meta file for extracting pubkeys from it */
932 7 : if (stat(filepath, &st) == -1) {
933 0 : pkg_emit_errno("pkg_repo_fetch_meta", "cannot stat meta fetched");
934 0 : rc = EPKG_FATAL;
935 0 : goto cleanup;
936 : }
937 7 : if ((fd = open(filepath, O_RDONLY)) == -1) {
938 0 : pkg_emit_errno("pkg_repo_fetch_meta", "cannot open meta fetched");
939 0 : rc = EPKG_FATAL;
940 0 : goto cleanup;
941 : }
942 :
943 7 : map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
944 7 : close(fd);
945 7 : if (map == MAP_FAILED) {
946 0 : pkg_emit_errno("pkg_repo_fetch_meta", "cannot mmap meta fetched");
947 0 : rc = EPKG_FATAL;
948 0 : goto cleanup;
949 : }
950 :
951 7 : if (repo->signature_type == SIG_FINGERPRINT) {
952 0 : cbdata.len = st.st_size;
953 0 : cbdata.map = map;
954 0 : HASH_ITER(hh, sc, s, stmp) {
955 0 : if (s->siglen != 0 && s->certlen == 0) {
956 : /*
957 : * We need to load this pubkey from meta
958 : */
959 0 : cbdata.name = s->name;
960 0 : if (pkg_emit_sandbox_get_string(pkg_repo_meta_extract_pubkey, &cbdata,
961 : (char **)&s->cert, &s->certlen) != EPKG_OK) {
962 0 : rc = EPKG_FATAL;
963 0 : goto cleanup;
964 : }
965 0 : s->cert_allocated = true;
966 : }
967 : }
968 :
969 0 : if (!pkg_repo_check_fingerprint(repo, sc, true)) {
970 0 : rc = EPKG_FATAL;
971 0 : goto cleanup;
972 : }
973 :
974 0 : HASH_ITER(hh, sc, s, stmp) {
975 0 : ret = rsa_verify_cert(filepath, s->cert, s->certlen, s->sig, s->siglen,
976 : -1);
977 0 : if (ret == EPKG_OK && s->trusted)
978 0 : break;
979 :
980 0 : ret = EPKG_FATAL;
981 : }
982 0 : if (ret != EPKG_OK) {
983 0 : pkg_emit_error("No trusted certificate has been used "
984 : "to sign the repository");
985 0 : rc = EPKG_FATAL;
986 0 : goto cleanup;
987 : }
988 : }
989 :
990 : load_meta:
991 7 : if ((rc = pkg_repo_meta_load(filepath, &nmeta)) != EPKG_OK) {
992 0 : if (map != NULL)
993 0 : munmap(map, st.st_size);
994 :
995 0 : return (rc);
996 : }
997 :
998 7 : if (repo->meta != NULL)
999 7 : pkg_repo_meta_free(repo->meta);
1000 :
1001 7 : repo->meta = nmeta;
1002 :
1003 : cleanup:
1004 7 : if (map != NULL)
1005 7 : munmap(map, st.st_size);
1006 :
1007 7 : if (sc != NULL)
1008 0 : pkg_repo_signatures_free(sc);
1009 :
1010 7 : if (rc != EPKG_OK)
1011 0 : unlink(filepath);
1012 :
1013 7 : return (rc);
1014 : }
1015 :
1016 : static struct fingerprint *
1017 0 : pkg_repo_parse_fingerprint(ucl_object_t *obj)
1018 : {
1019 : const ucl_object_t *cur;
1020 0 : ucl_object_iter_t it = NULL;
1021 0 : const char *function = NULL, *fp = NULL;
1022 0 : hash_t fct = HASH_UNKNOWN;
1023 0 : struct fingerprint *f = NULL;
1024 : const char *key;
1025 :
1026 0 : while ((cur = ucl_iterate_object(obj, &it, true))) {
1027 0 : key = ucl_object_key(cur);
1028 0 : if (cur->type != UCL_STRING)
1029 0 : continue;
1030 :
1031 0 : if (strcasecmp(key, "function") == 0) {
1032 0 : function = ucl_object_tostring(cur);
1033 0 : continue;
1034 : }
1035 :
1036 0 : if (strcasecmp(key, "fingerprint") == 0) {
1037 0 : fp = ucl_object_tostring(cur);
1038 0 : continue;
1039 : }
1040 : }
1041 :
1042 0 : if (fp == NULL || function == NULL)
1043 0 : return (NULL);
1044 :
1045 0 : if (strcasecmp(function, "sha256") == 0)
1046 0 : fct = HASH_SHA256;
1047 :
1048 0 : if (fct == HASH_UNKNOWN) {
1049 0 : pkg_emit_error("Unsupported hashing function: %s", function);
1050 0 : return (NULL);
1051 : }
1052 :
1053 0 : f = calloc(1, sizeof(struct fingerprint));
1054 0 : f->type = fct;
1055 0 : strlcpy(f->hash, fp, sizeof(f->hash));
1056 :
1057 0 : return (f);
1058 : }
1059 :
1060 : static struct fingerprint *
1061 0 : pkg_repo_load_fingerprint(const char *dir, const char *filename)
1062 : {
1063 0 : ucl_object_t *obj = NULL;
1064 0 : struct ucl_parser *p = NULL;
1065 : char path[MAXPATHLEN];
1066 0 : struct fingerprint *f = NULL;
1067 :
1068 0 : snprintf(path, sizeof(path), "%s/%s", dir, filename);
1069 :
1070 0 : p = ucl_parser_new(0);
1071 :
1072 0 : if (!ucl_parser_add_file(p, path)) {
1073 0 : pkg_emit_error("%s", ucl_parser_get_error(p));
1074 0 : ucl_parser_free(p);
1075 0 : return (NULL);
1076 : }
1077 :
1078 0 : obj = ucl_parser_get_object(p);
1079 :
1080 0 : if (obj->type == UCL_OBJECT)
1081 0 : f = pkg_repo_parse_fingerprint(obj);
1082 :
1083 0 : ucl_object_unref(obj);
1084 0 : ucl_parser_free(p);
1085 :
1086 0 : return (f);
1087 : }
1088 :
1089 : static int
1090 0 : pkg_repo_load_fingerprints_from_path(const char *path, struct fingerprint **f)
1091 : {
1092 : DIR *d;
1093 : struct dirent *ent;
1094 0 : struct fingerprint *finger = NULL;
1095 :
1096 0 : *f = NULL;
1097 :
1098 0 : if ((d = opendir(path)) == NULL)
1099 0 : return (EPKG_FATAL);
1100 :
1101 0 : while ((ent = readdir(d))) {
1102 0 : if (strcmp(ent->d_name, ".") == 0 ||
1103 0 : strcmp(ent->d_name, "..") == 0)
1104 0 : continue;
1105 0 : finger = pkg_repo_load_fingerprint(path, ent->d_name);
1106 0 : if (finger != NULL)
1107 0 : HASH_ADD_STR(*f, hash, finger);
1108 : }
1109 :
1110 0 : closedir(d);
1111 :
1112 0 : return (EPKG_OK);
1113 : }
1114 :
1115 : int
1116 0 : pkg_repo_load_fingerprints(struct pkg_repo *repo)
1117 : {
1118 : char path[MAXPATHLEN];
1119 : struct stat st;
1120 :
1121 0 : snprintf(path, sizeof(path), "%s/trusted", pkg_repo_fingerprints(repo));
1122 0 : if ((pkg_repo_load_fingerprints_from_path(path, &repo->trusted_fp)) != EPKG_OK) {
1123 0 : pkg_emit_error("Error loading trusted certificates");
1124 0 : return (EPKG_FATAL);
1125 : }
1126 :
1127 0 : if (HASH_COUNT(repo->trusted_fp) == 0) {
1128 0 : pkg_emit_error("No trusted certificates");
1129 0 : return (EPKG_FATAL);
1130 : }
1131 :
1132 0 : snprintf(path, sizeof(path), "%s/revoked", pkg_repo_fingerprints(repo));
1133 : /* Absence of revoked certificates is not a fatal error */
1134 0 : if (stat(path, &st) != -1) {
1135 0 : if ((pkg_repo_load_fingerprints_from_path(path, &repo->revoked_fp)) != EPKG_OK) {
1136 0 : pkg_emit_error("Error loading revoked certificates");
1137 0 : return (EPKG_FATAL);
1138 : }
1139 : }
1140 :
1141 0 : return (EPKG_OK);
1142 : }
1143 :
1144 :
1145 :
1146 : int
1147 0 : pkg_repo_fetch_package(struct pkg *pkg)
1148 : {
1149 : struct pkg_repo *repo;
1150 :
1151 0 : if (pkg->repo == NULL) {
1152 0 : pkg_emit_error("Trying to fetch package without repository");
1153 0 : return (EPKG_FATAL);
1154 : }
1155 :
1156 0 : repo = pkg->repo;
1157 0 : if (repo->ops->fetch_pkg == NULL) {
1158 0 : pkg_emit_error("Repository %s does not support fetching", repo->name);
1159 0 : return (EPKG_FATAL);
1160 : }
1161 :
1162 0 : return (repo->ops->fetch_pkg(repo, pkg));
1163 : }
1164 :
1165 : int
1166 0 : pkg_repo_mirror_package(struct pkg *pkg, const char *destdir)
1167 : {
1168 : struct pkg_repo *repo;
1169 :
1170 0 : if (pkg->repo == NULL) {
1171 0 : pkg_emit_error("Trying to mirror package without repository");
1172 0 : return (EPKG_FATAL);
1173 : }
1174 :
1175 0 : repo = pkg->repo;
1176 0 : if (repo->ops->mirror_pkg == NULL) {
1177 0 : pkg_emit_error("Repository %s does not support mirroring", repo->name);
1178 0 : return (EPKG_FATAL);
1179 : }
1180 :
1181 0 : return (repo->ops->mirror_pkg(repo, pkg, destdir));
1182 : }
1183 :
1184 : int
1185 64 : pkg_repo_cached_name(struct pkg *pkg, char *dest, size_t destlen)
1186 : {
1187 : struct pkg_repo *repo;
1188 :
1189 64 : if (pkg->repo == NULL)
1190 0 : return (EPKG_FATAL);
1191 :
1192 64 : repo = pkg->repo;
1193 64 : if (repo->ops->get_cached_name == NULL)
1194 0 : return (EPKG_FATAL);
1195 :
1196 64 : return (repo->ops->get_cached_name(repo, pkg, dest, destlen));
1197 : }
|