Mon Mar 2 14:59:14 2009 UTC ()
pkg_install-20090301:
Plug a number of file descriptor leaks.


(joerg)
diff -r1.81 -r1.82 pkgsrc/pkgtools/pkg_install/files/add/perform.c
diff -r1.3 -r1.4 pkgsrc/pkgtools/pkg_install/files/lib/pkcs7.c
diff -r1.5 -r1.6 pkgsrc/pkgtools/pkg_install/files/lib/pkg_signature.c
diff -r1.115 -r1.116 pkgsrc/pkgtools/pkg_install/files/lib/version.h
diff -r1.4 -r1.5 pkgsrc/pkgtools/pkg_install/files/lib/vulnerabilities-file.c

cvs diff -r1.81 -r1.82 pkgsrc/pkgtools/pkg_install/files/add/perform.c (switch to unified diff)

--- pkgsrc/pkgtools/pkg_install/files/add/perform.c 2009/02/28 16:03:56 1.81
+++ pkgsrc/pkgtools/pkg_install/files/add/perform.c 2009/03/02 14:59:14 1.82
@@ -1,1441 +1,1445 @@ @@ -1,1441 +1,1445 @@
1/* $NetBSD: perform.c,v 1.81 2009/02/28 16:03:56 joerg Exp $ */ 1/* $NetBSD: perform.c,v 1.82 2009/03/02 14:59:14 joerg Exp $ */
2#if HAVE_CONFIG_H 2#if HAVE_CONFIG_H
3#include "config.h" 3#include "config.h"
4#endif 4#endif
5#include <nbcompat.h> 5#include <nbcompat.h>
6#if HAVE_SYS_CDEFS_H 6#if HAVE_SYS_CDEFS_H
7#include <sys/cdefs.h> 7#include <sys/cdefs.h>
8#endif 8#endif
9__RCSID("$NetBSD: perform.c,v 1.81 2009/02/28 16:03:56 joerg Exp $"); 9__RCSID("$NetBSD: perform.c,v 1.82 2009/03/02 14:59:14 joerg Exp $");
10 10
11/*- 11/*-
12 * Copyright (c) 2003 Grant Beattie <grant@NetBSD.org> 12 * Copyright (c) 2003 Grant Beattie <grant@NetBSD.org>
13 * Copyright (c) 2005 Dieter Baron <dillo@NetBSD.org> 13 * Copyright (c) 2005 Dieter Baron <dillo@NetBSD.org>
14 * Copyright (c) 2007 Roland Illig <rillig@NetBSD.org> 14 * Copyright (c) 2007 Roland Illig <rillig@NetBSD.org>
15 * Copyright (c) 2008, 2009 Joerg Sonnenberger <joerg@NetBSD.org> 15 * Copyright (c) 2008, 2009 Joerg Sonnenberger <joerg@NetBSD.org>
16 * All rights reserved. 16 * All rights reserved.
17 * 17 *
18 * Redistribution and use in source and binary forms, with or without 18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions 19 * modification, are permitted provided that the following conditions
20 * are met: 20 * are met:
21 * 21 *
22 * 1. Redistributions of source code must retain the above copyright 22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer. 23 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright 24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in 25 * notice, this list of conditions and the following disclaimer in
26 * the documentation and/or other materials provided with the 26 * the documentation and/or other materials provided with the
27 * distribution. 27 * distribution.
28 * 28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
32 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 32 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
33 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 33 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 34 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
35 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 35 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 36 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
37 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 37 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
38 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 38 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
39 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE. 40 * SUCH DAMAGE.
41 */ 41 */
42 42
43#include <sys/utsname.h> 43#include <sys/utsname.h>
44#if HAVE_ERR_H 44#if HAVE_ERR_H
45#include <err.h> 45#include <err.h>
46#endif 46#endif
47#include <errno.h> 47#include <errno.h>
48#if HAVE_FCNTL_H 48#if HAVE_FCNTL_H
49#include <fcntl.h> 49#include <fcntl.h>
50#endif 50#endif
51#include <stdlib.h> 51#include <stdlib.h>
52#include <string.h> 52#include <string.h>
53#include <unistd.h> 53#include <unistd.h>
54 54
55#include <archive.h> 55#include <archive.h>
56#include <archive_entry.h> 56#include <archive_entry.h>
57 57
58#include "lib.h" 58#include "lib.h"
59#include "add.h" 59#include "add.h"
60 60
61struct pkg_meta { 61struct pkg_meta {
62 char *meta_contents; 62 char *meta_contents;
63 char *meta_comment; 63 char *meta_comment;
64 char *meta_desc; 64 char *meta_desc;
65 char *meta_mtree; 65 char *meta_mtree;
66 char *meta_build_version; 66 char *meta_build_version;
67 char *meta_build_info; 67 char *meta_build_info;
68 char *meta_size_pkg; 68 char *meta_size_pkg;
69 char *meta_size_all; 69 char *meta_size_all;
70 char *meta_required_by; 70 char *meta_required_by;
71 char *meta_display; 71 char *meta_display;
72 char *meta_install; 72 char *meta_install;
73 char *meta_deinstall; 73 char *meta_deinstall;
74 char *meta_preserve; 74 char *meta_preserve;
75 char *meta_views; 75 char *meta_views;
76 char *meta_installed_info; 76 char *meta_installed_info;
77}; 77};
78 78
79struct pkg_task { 79struct pkg_task {
80 char *pkgname; 80 char *pkgname;
81 81
82 const char *prefix; 82 const char *prefix;
83 char *install_prefix; 83 char *install_prefix;
84 84
85 char *logdir; 85 char *logdir;
86 char *install_logdir; 86 char *install_logdir;
87 char *other_version; 87 char *other_version;
88 88
89 package_t plist; 89 package_t plist;
90 90
91 struct pkg_meta meta_data; 91 struct pkg_meta meta_data;
92 92
93 struct archive *archive; 93 struct archive *archive;
94 struct archive_entry *entry; 94 struct archive_entry *entry;
95 95
96 char *buildinfo[BI_ENUM_COUNT]; 96 char *buildinfo[BI_ENUM_COUNT];
97 97
98 size_t dep_length, dep_allocated; 98 size_t dep_length, dep_allocated;
99 char **dependencies; 99 char **dependencies;
100}; 100};
101 101
102static const struct pkg_meta_desc { 102static const struct pkg_meta_desc {
103 size_t entry_offset; 103 size_t entry_offset;
104 const char *entry_filename; 104 const char *entry_filename;
105 int required_file; 105 int required_file;
106 mode_t perm; 106 mode_t perm;
107} pkg_meta_descriptors[] = { 107} pkg_meta_descriptors[] = {
108 { offsetof(struct pkg_meta, meta_contents), CONTENTS_FNAME, 1, 0644 }, 108 { offsetof(struct pkg_meta, meta_contents), CONTENTS_FNAME, 1, 0644 },
109 { offsetof(struct pkg_meta, meta_comment), COMMENT_FNAME, 1, 0444}, 109 { offsetof(struct pkg_meta, meta_comment), COMMENT_FNAME, 1, 0444},
110 { offsetof(struct pkg_meta, meta_desc), DESC_FNAME, 1, 0444}, 110 { offsetof(struct pkg_meta, meta_desc), DESC_FNAME, 1, 0444},
111 { offsetof(struct pkg_meta, meta_install), INSTALL_FNAME, 0, 0555 }, 111 { offsetof(struct pkg_meta, meta_install), INSTALL_FNAME, 0, 0555 },
112 { offsetof(struct pkg_meta, meta_deinstall), DEINSTALL_FNAME, 0, 0555 }, 112 { offsetof(struct pkg_meta, meta_deinstall), DEINSTALL_FNAME, 0, 0555 },
113 { offsetof(struct pkg_meta, meta_display), DISPLAY_FNAME, 0, 0444 }, 113 { offsetof(struct pkg_meta, meta_display), DISPLAY_FNAME, 0, 0444 },
114 { offsetof(struct pkg_meta, meta_mtree), MTREE_FNAME, 0, 0444 }, 114 { offsetof(struct pkg_meta, meta_mtree), MTREE_FNAME, 0, 0444 },
115 { offsetof(struct pkg_meta, meta_build_version), BUILD_VERSION_FNAME, 0, 0444 }, 115 { offsetof(struct pkg_meta, meta_build_version), BUILD_VERSION_FNAME, 0, 0444 },
116 { offsetof(struct pkg_meta, meta_build_info), BUILD_INFO_FNAME, 0, 0444 }, 116 { offsetof(struct pkg_meta, meta_build_info), BUILD_INFO_FNAME, 0, 0444 },
117 { offsetof(struct pkg_meta, meta_size_pkg), SIZE_PKG_FNAME, 0, 0444 }, 117 { offsetof(struct pkg_meta, meta_size_pkg), SIZE_PKG_FNAME, 0, 0444 },
118 { offsetof(struct pkg_meta, meta_size_all), SIZE_ALL_FNAME, 0, 0444 }, 118 { offsetof(struct pkg_meta, meta_size_all), SIZE_ALL_FNAME, 0, 0444 },
119 { offsetof(struct pkg_meta, meta_preserve), PRESERVE_FNAME, 0, 0444 }, 119 { offsetof(struct pkg_meta, meta_preserve), PRESERVE_FNAME, 0, 0444 },
120 { offsetof(struct pkg_meta, meta_views), VIEWS_FNAME, 0, 0444 }, 120 { offsetof(struct pkg_meta, meta_views), VIEWS_FNAME, 0, 0444 },
121 { offsetof(struct pkg_meta, meta_required_by), REQUIRED_BY_FNAME, 0, 0644 }, 121 { offsetof(struct pkg_meta, meta_required_by), REQUIRED_BY_FNAME, 0, 0644 },
122 { offsetof(struct pkg_meta, meta_installed_info), INSTALLED_INFO_FNAME, 0, 0644 }, 122 { offsetof(struct pkg_meta, meta_installed_info), INSTALLED_INFO_FNAME, 0, 0644 },
123 { 0, NULL, 0 }, 123 { 0, NULL, 0 },
124}; 124};
125 125
126static int pkg_do(const char *, int, int); 126static int pkg_do(const char *, int, int);
127 127
128static int 128static int
129mkdir_p(const char *path) 129mkdir_p(const char *path)
130{ 130{
131 char *p, *cur_end; 131 char *p, *cur_end;
132 int done; 132 int done;
133 133
134 /* 134 /*
135 * Handle the easy case of direct success or 135 * Handle the easy case of direct success or
136 * pre-existing directory first. 136 * pre-existing directory first.
137 */ 137 */
138 if (mkdir(path, 0777) == 0 || errno == EEXIST) 138 if (mkdir(path, 0777) == 0 || errno == EEXIST)
139 return 0; 139 return 0;
140 if (errno != ENOENT) 140 if (errno != ENOENT)
141 return -1; 141 return -1;
142 142
143 cur_end = p = xstrdup(path); 143 cur_end = p = xstrdup(path);
144 144
145 for (;;) { 145 for (;;) {
146 /* 146 /*
147 * First skip leading slashes either from / or 147 * First skip leading slashes either from / or
148 * from the last iteration. 148 * from the last iteration.
149 */ 149 */
150 cur_end += strspn(cur_end, "/"); 150 cur_end += strspn(cur_end, "/");
151 /* Find end of actual directory name. */ 151 /* Find end of actual directory name. */
152 cur_end += strcspn(cur_end, "/"); 152 cur_end += strcspn(cur_end, "/");
153 153
154 /* 154 /*
155 * Remember if this is the last component and 155 * Remember if this is the last component and
156 * overwrite / if needed. 156 * overwrite / if needed.
157 */ 157 */
158 done = (*cur_end == '\0'); 158 done = (*cur_end == '\0');
159 *cur_end = '\0'; 159 *cur_end = '\0';
160 160
161 /* 161 /*
162 * ENOENT can only happen if something else races us, 162 * ENOENT can only happen if something else races us,
163 * in which case we should better give up. 163 * in which case we should better give up.
164 */ 164 */
165 if (mkdir(p, 0777) == -1 && errno != EEXIST) { 165 if (mkdir(p, 0777) == -1 && errno != EEXIST) {
166 free(p); 166 free(p);
167 return -1; 167 return -1;
168 } 168 }
169 if (done) 169 if (done)
170 break; 170 break;
171 *cur_end = '/'; 171 *cur_end = '/';
172 } 172 }
173 173
174 free(p); 174 free(p);
175 return 0;  175 return 0;
176} 176}
177 177
178/* 178/*
179 * Read meta data from archive. 179 * Read meta data from archive.
180 * Bail out if a required entry is missing or entries are in the wrong order. 180 * Bail out if a required entry is missing or entries are in the wrong order.
181 */ 181 */
182static int 182static int
183read_meta_data(struct pkg_task *pkg) 183read_meta_data(struct pkg_task *pkg)
184{ 184{
185 const struct pkg_meta_desc *descr, *last_descr; 185 const struct pkg_meta_desc *descr, *last_descr;
186 const char *fname; 186 const char *fname;
187 char **target; 187 char **target;
188 int64_t size; 188 int64_t size;
189 int r, found_required; 189 int r, found_required;
190 190
191 found_required = 0; 191 found_required = 0;
192 192
193 r = ARCHIVE_OK; 193 r = ARCHIVE_OK;
194 last_descr = 0; 194 last_descr = 0;
195 195
196 if (pkg->entry != NULL) 196 if (pkg->entry != NULL)
197 goto skip_header; 197 goto skip_header;
198 198
199 for (;;) { 199 for (;;) {
200 r = archive_read_next_header(pkg->archive, &pkg->entry); 200 r = archive_read_next_header(pkg->archive, &pkg->entry);
201 if (r != ARCHIVE_OK) 201 if (r != ARCHIVE_OK)
202 break; 202 break;
203skip_header: 203skip_header:
204 fname = archive_entry_pathname(pkg->entry); 204 fname = archive_entry_pathname(pkg->entry);
205 205
206 for (descr = pkg_meta_descriptors; descr->entry_filename; 206 for (descr = pkg_meta_descriptors; descr->entry_filename;
207 ++descr) { 207 ++descr) {
208 if (strcmp(descr->entry_filename, fname) == 0) 208 if (strcmp(descr->entry_filename, fname) == 0)
209 break; 209 break;
210 } 210 }
211 if (descr->entry_filename == NULL) 211 if (descr->entry_filename == NULL)
212 break; 212 break;
213 213
214 if (descr->required_file) 214 if (descr->required_file)
215 ++found_required; 215 ++found_required;
216 216
217 target = (char **)((char *)&pkg->meta_data + 217 target = (char **)((char *)&pkg->meta_data +
218 descr->entry_offset); 218 descr->entry_offset);
219 if (*target) { 219 if (*target) {
220 warnx("duplicate entry, package corrupt"); 220 warnx("duplicate entry, package corrupt");
221 return -1; 221 return -1;
222 } 222 }
223 if (descr < last_descr) { 223 if (descr < last_descr) {
224 warnx("misordered package"); 224 warnx("misordered package");
225 return -1; 225 return -1;
226 } 226 }
227 last_descr = descr; 227 last_descr = descr;
228 228
229 size = archive_entry_size(pkg->entry); 229 size = archive_entry_size(pkg->entry);
230 if (size > SSIZE_MAX - 1) { 230 if (size > SSIZE_MAX - 1) {
231 warnx("package meta data too large to process"); 231 warnx("package meta data too large to process");
232 return -1; 232 return -1;
233 } 233 }
234 *target = xmalloc(size + 1); 234 *target = xmalloc(size + 1);
235 if (archive_read_data(pkg->archive, *target, size) != size) { 235 if (archive_read_data(pkg->archive, *target, size) != size) {
236 warnx("cannot read package meta data"); 236 warnx("cannot read package meta data");
237 return -1; 237 return -1;
238 } 238 }
239 (*target)[size] = '\0'; 239 (*target)[size] = '\0';
240 } 240 }
241 241
242 if (r != ARCHIVE_OK) 242 if (r != ARCHIVE_OK)
243 pkg->entry = NULL; 243 pkg->entry = NULL;
244 if (r == ARCHIVE_EOF) 244 if (r == ARCHIVE_EOF)
245 r = ARCHIVE_OK; 245 r = ARCHIVE_OK;
246 246
247 for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { 247 for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) {
248 if (descr->required_file) 248 if (descr->required_file)
249 --found_required; 249 --found_required;
250 } 250 }
251 251
252 return !found_required && r == ARCHIVE_OK ? 0 : -1; 252 return !found_required && r == ARCHIVE_OK ? 0 : -1;
253} 253}
254 254
255/* 255/*
256 * Free meta data. 256 * Free meta data.
257 */ 257 */
258static void 258static void
259free_meta_data(struct pkg_task *pkg) 259free_meta_data(struct pkg_task *pkg)
260{ 260{
261 const struct pkg_meta_desc *descr; 261 const struct pkg_meta_desc *descr;
262 char **target; 262 char **target;
263 263
264 for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { 264 for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) {
265 target = (char **)((char *)&pkg->meta_data + 265 target = (char **)((char *)&pkg->meta_data +
266 descr->entry_offset); 266 descr->entry_offset);
267 free(*target); 267 free(*target);
268 *target = NULL; 268 *target = NULL;
269 } 269 }
270} 270}
271 271
272/* 272/*
273 * Parse PLIST and populate pkg. 273 * Parse PLIST and populate pkg.
274 */ 274 */
275static int 275static int
276pkg_parse_plist(struct pkg_task *pkg) 276pkg_parse_plist(struct pkg_task *pkg)
277{ 277{
278 plist_t *p; 278 plist_t *p;
279 279
280 parse_plist(&pkg->plist, pkg->meta_data.meta_contents); 280 parse_plist(&pkg->plist, pkg->meta_data.meta_contents);
281 if ((p = find_plist(&pkg->plist, PLIST_NAME)) == NULL) { 281 if ((p = find_plist(&pkg->plist, PLIST_NAME)) == NULL) {
282 warnx("Invalid PLIST: missing @name"); 282 warnx("Invalid PLIST: missing @name");
283 return -1; 283 return -1;
284 } 284 }
285 if (pkg->pkgname == NULL) 285 if (pkg->pkgname == NULL)
286 pkg->pkgname = xstrdup(p->name); 286 pkg->pkgname = xstrdup(p->name);
287 else if (strcmp(pkg->pkgname, p->name) != 0) { 287 else if (strcmp(pkg->pkgname, p->name) != 0) {
288 warnx("Signature and PLIST differ on package name"); 288 warnx("Signature and PLIST differ on package name");
289 return -1; 289 return -1;
290 } 290 }
291 if ((p = find_plist(&pkg->plist, PLIST_CWD)) == NULL) { 291 if ((p = find_plist(&pkg->plist, PLIST_CWD)) == NULL) {
292 warnx("Invalid PLIST: missing @cwd"); 292 warnx("Invalid PLIST: missing @cwd");
293 return -1; 293 return -1;
294 } 294 }
295 295
296 if (Prefix != NULL && 296 if (Prefix != NULL &&
297 strcmp(p->name, Prefix) != 0) { 297 strcmp(p->name, Prefix) != 0) {
298 size_t len; 298 size_t len;
299 299
300 delete_plist(&pkg->plist, FALSE, PLIST_CWD, NULL); 300 delete_plist(&pkg->plist, FALSE, PLIST_CWD, NULL);
301 add_plist_top(&pkg->plist, PLIST_CWD, Prefix); 301 add_plist_top(&pkg->plist, PLIST_CWD, Prefix);
302 free(pkg->meta_data.meta_contents); 302 free(pkg->meta_data.meta_contents);
303 stringify_plist(&pkg->plist, &pkg->meta_data.meta_contents, &len, 303 stringify_plist(&pkg->plist, &pkg->meta_data.meta_contents, &len,
304 Prefix); 304 Prefix);
305 pkg->prefix = Prefix; 305 pkg->prefix = Prefix;
306 } else 306 } else
307 pkg->prefix = p->name; 307 pkg->prefix = p->name;
308 308
309 if (Destdir != NULL) 309 if (Destdir != NULL)
310 pkg->install_prefix = xasprintf("%s/%s", Destdir, pkg->prefix); 310 pkg->install_prefix = xasprintf("%s/%s", Destdir, pkg->prefix);
311 else 311 else
312 pkg->install_prefix = xstrdup(pkg->prefix); 312 pkg->install_prefix = xstrdup(pkg->prefix);
313 313
314 return 0; 314 return 0;
315} 315}
316 316
317/* 317/*
318 * Helper function to extract value from a string of the 318 * Helper function to extract value from a string of the
319 * form key=value ending at eol. 319 * form key=value ending at eol.
320 */ 320 */
321static char * 321static char *
322dup_value(const char *line, const char *eol) 322dup_value(const char *line, const char *eol)
323{ 323{
324 const char *key; 324 const char *key;
325 char *val; 325 char *val;
326 326
327 key = strchr(line, '='); 327 key = strchr(line, '=');
328 val = xmalloc(eol - key); 328 val = xmalloc(eol - key);
329 memcpy(val, key + 1, eol - key - 1); 329 memcpy(val, key + 1, eol - key - 1);
330 val[eol - key - 1] = '\0'; 330 val[eol - key - 1] = '\0';
331 return val; 331 return val;
332} 332}
333 333
334static int 334static int
335check_already_installed(struct pkg_task *pkg) 335check_already_installed(struct pkg_task *pkg)
336{ 336{
337 char *filename; 337 char *filename;
338 int fd; 338 int fd;
339 339
340 if (Force) 340 if (Force)
341 return -1; 341 return -1;
342 342
343 filename = pkgdb_pkg_file(pkg->pkgname, CONTENTS_FNAME); 343 filename = pkgdb_pkg_file(pkg->pkgname, CONTENTS_FNAME);
344 fd = open(filename, O_RDONLY); 344 fd = open(filename, O_RDONLY);
345 free(filename); 345 free(filename);
346 if (fd == -1) 346 if (fd == -1)
347 return -1; 347 return -1;
348 348
349 /* We can only arrive here for explicitly requested packages. */ 349 /* We can only arrive here for explicitly requested packages. */
350 if (!Automatic && is_automatic_installed(pkg->pkgname)) { 350 if (!Automatic && is_automatic_installed(pkg->pkgname)) {
351 if (Fake || 351 if (Fake ||
352 mark_as_automatic_installed(pkg->pkgname, 0) == 0) 352 mark_as_automatic_installed(pkg->pkgname, 0) == 0)
353 warnx("package `%s' was already installed as " 353 warnx("package `%s' was already installed as "
354 "dependency, now marked as installed " 354 "dependency, now marked as installed "
355 "manually", pkg->pkgname); 355 "manually", pkg->pkgname);
356 } else { 356 } else {
357 warnx("package `%s' already recorded as installed", 357 warnx("package `%s' already recorded as installed",
358 pkg->pkgname); 358 pkg->pkgname);
359 } 359 }
 360 close(fd);
360 return 0; 361 return 0;
361 362
362} 363}
363 364
364static int 365static int
365check_other_installed(struct pkg_task *pkg) 366check_other_installed(struct pkg_task *pkg)
366{ 367{
367 FILE *f, *f_pkg; 368 FILE *f, *f_pkg;
368 size_t len; 369 size_t len;
369 char *pkgbase, *iter, *filename; 370 char *pkgbase, *iter, *filename;
370 package_t plist; 371 package_t plist;
371 plist_t *p; 372 plist_t *p;
372 int status; 373 int status;
373 374
374 pkgbase = xstrdup(pkg->pkgname); 375 pkgbase = xstrdup(pkg->pkgname);
375 376
376 if ((iter = strrchr(pkgbase, '-')) == NULL) { 377 if ((iter = strrchr(pkgbase, '-')) == NULL) {
377 free(pkgbase); 378 free(pkgbase);
378 warnx("Invalid package name %s", pkg->pkgname); 379 warnx("Invalid package name %s", pkg->pkgname);
379 return -1; 380 return -1;
380 } 381 }
381 *iter = '\0'; 382 *iter = '\0';
382 pkg->other_version = find_best_matching_installed_pkg(pkgbase); 383 pkg->other_version = find_best_matching_installed_pkg(pkgbase);
383 free(pkgbase); 384 free(pkgbase);
384 if (pkg->other_version == NULL) 385 if (pkg->other_version == NULL)
385 return 0; 386 return 0;
386 387
387 if (!Replace) { 388 if (!Replace) {
388 /* XXX This is redundant to the implicit conflict check. */ 389 /* XXX This is redundant to the implicit conflict check. */
389 warnx("A different version of %s is already installed: %s", 390 warnx("A different version of %s is already installed: %s",
390 pkg->pkgname, pkg->other_version); 391 pkg->pkgname, pkg->other_version);
391 return -1; 392 return -1;
392 } 393 }
393 394
394 filename = pkgdb_pkg_file(pkg->other_version, REQUIRED_BY_FNAME); 395 filename = pkgdb_pkg_file(pkg->other_version, REQUIRED_BY_FNAME);
395 errno = 0; 396 errno = 0;
396 f = fopen(filename, "r"); 397 f = fopen(filename, "r");
397 free(filename); 398 free(filename);
398 if (f == NULL) { 399 if (f == NULL) {
399 if (errno == ENOENT) { 400 if (errno == ENOENT) {
400 /* No packages depend on this, so everything is well. */ 401 /* No packages depend on this, so everything is well. */
401 return 0;  402 return 0;
402 } 403 }
403 warnx("Can't open +REQUIRED_BY of %s", pkg->other_version); 404 warnx("Can't open +REQUIRED_BY of %s", pkg->other_version);
404 return -1; 405 return -1;
405 } 406 }
406 407
407 status = 0; 408 status = 0;
408 409
409 while ((iter = fgetln(f, &len)) != NULL) { 410 while ((iter = fgetln(f, &len)) != NULL) {
410 if (iter[len - 1] == '\n') 411 if (iter[len - 1] == '\n')
411 iter[len - 1] = '\0'; 412 iter[len - 1] = '\0';
412 filename = pkgdb_pkg_file(iter, CONTENTS_FNAME); 413 filename = pkgdb_pkg_file(iter, CONTENTS_FNAME);
413 if ((f_pkg = fopen(filename, "r")) == NULL) { 414 if ((f_pkg = fopen(filename, "r")) == NULL) {
414 warnx("Can't open +CONTENTS of depending package %s", 415 warnx("Can't open +CONTENTS of depending package %s",
415 iter); 416 iter);
416 fclose(f); 417 fclose(f);
417 return -1; 418 return -1;
418 } 419 }
419 read_plist(&plist, f_pkg); 420 read_plist(&plist, f_pkg);
420 fclose(f_pkg); 421 fclose(f_pkg);
421 for (p = plist.head; p != NULL; p = p->next) { 422 for (p = plist.head; p != NULL; p = p->next) {
422 if (p->type == PLIST_IGNORE) { 423 if (p->type == PLIST_IGNORE) {
423 p = p->next; 424 p = p->next;
424 continue; 425 continue;
425 } else if (p->type != PLIST_PKGDEP) 426 } else if (p->type != PLIST_PKGDEP)
426 continue; 427 continue;
427 /* 428 /*
428 * XXX This is stricter than necessary. 429 * XXX This is stricter than necessary.
429 * XXX One pattern might be fulfilled by 430 * XXX One pattern might be fulfilled by
430 * XXX a different package and still need this 431 * XXX a different package and still need this
431 * XXX one for a different pattern. 432 * XXX one for a different pattern.
432 */ 433 */
433 if (pkg_match(p->name, pkg->other_version) == 0) 434 if (pkg_match(p->name, pkg->other_version) == 0)
434 continue; 435 continue;
435 if (pkg_match(p->name, pkg->pkgname) == 1) 436 if (pkg_match(p->name, pkg->pkgname) == 1)
436 continue; /* Both match, ok. */ 437 continue; /* Both match, ok. */
437 warnx("Dependency of %s fulfilled by %s, but not by %s", 438 warnx("Dependency of %s fulfilled by %s, but not by %s",
438 iter, pkg->other_version, pkg->pkgname); 439 iter, pkg->other_version, pkg->pkgname);
439 if (!Force) 440 if (!Force)
440 status = -1; 441 status = -1;
441 break; 442 break;
442 } 443 }
443 free_plist(&plist);  444 free_plist(&plist);
444 } 445 }
445 446
446 fclose(f); 447 fclose(f);
447 448
448 return status; 449 return status;
449} 450}
450 451
451/* 452/*
452 * Read package build information from meta data. 453 * Read package build information from meta data.
453 */ 454 */
454static int 455static int
455read_buildinfo(struct pkg_task *pkg) 456read_buildinfo(struct pkg_task *pkg)
456{ 457{
457 const char *data, *eol, *next_line; 458 const char *data, *eol, *next_line;
458 459
459 data = pkg->meta_data.meta_build_info; 460 data = pkg->meta_data.meta_build_info;
460 461
461 for (; data != NULL && *data != '\0'; data = next_line) { 462 for (; data != NULL && *data != '\0'; data = next_line) {
462 if ((eol = strchr(data, '\n')) == NULL) { 463 if ((eol = strchr(data, '\n')) == NULL) {
463 eol = data + strlen(data); 464 eol = data + strlen(data);
464 next_line = eol; 465 next_line = eol;
465 } else 466 } else
466 next_line = eol + 1; 467 next_line = eol + 1;
467 468
468 if (strncmp(data, "OPSYS=", 6) == 0) 469 if (strncmp(data, "OPSYS=", 6) == 0)
469 pkg->buildinfo[BI_OPSYS] = dup_value(data, eol); 470 pkg->buildinfo[BI_OPSYS] = dup_value(data, eol);
470 else if (strncmp(data, "OS_VERSION=", 11) == 0) 471 else if (strncmp(data, "OS_VERSION=", 11) == 0)
471 pkg->buildinfo[BI_OS_VERSION] = dup_value(data, eol); 472 pkg->buildinfo[BI_OS_VERSION] = dup_value(data, eol);
472 else if (strncmp(data, "MACHINE_ARCH=", 13) == 0) 473 else if (strncmp(data, "MACHINE_ARCH=", 13) == 0)
473 pkg->buildinfo[BI_MACHINE_ARCH] = dup_value(data, eol); 474 pkg->buildinfo[BI_MACHINE_ARCH] = dup_value(data, eol);
474 else if (strncmp(data, "IGNORE_RECOMMENDED=", 19) == 0) 475 else if (strncmp(data, "IGNORE_RECOMMENDED=", 19) == 0)
475 pkg->buildinfo[BI_IGNORE_RECOMMENDED] = dup_value(data, 476 pkg->buildinfo[BI_IGNORE_RECOMMENDED] = dup_value(data,
476 eol); 477 eol);
477 else if (strncmp(data, "USE_ABI_DEPENDS=", 16) == 0) 478 else if (strncmp(data, "USE_ABI_DEPENDS=", 16) == 0)
478 pkg->buildinfo[BI_USE_ABI_DEPENDS] = dup_value(data, 479 pkg->buildinfo[BI_USE_ABI_DEPENDS] = dup_value(data,
479 eol); 480 eol);
480 } 481 }
481 if (pkg->buildinfo[BI_OPSYS] == NULL || 482 if (pkg->buildinfo[BI_OPSYS] == NULL ||
482 pkg->buildinfo[BI_OS_VERSION] == NULL || 483 pkg->buildinfo[BI_OS_VERSION] == NULL ||
483 pkg->buildinfo[BI_MACHINE_ARCH] == NULL) { 484 pkg->buildinfo[BI_MACHINE_ARCH] == NULL) {
484 warnx("Not all required build information are present."); 485 warnx("Not all required build information are present.");
485 return -1; 486 return -1;
486 } 487 }
487 488
488 if ((pkg->buildinfo[BI_USE_ABI_DEPENDS] != NULL && 489 if ((pkg->buildinfo[BI_USE_ABI_DEPENDS] != NULL &&
489 strcasecmp(pkg->buildinfo[BI_USE_ABI_DEPENDS], "YES") != 0) || 490 strcasecmp(pkg->buildinfo[BI_USE_ABI_DEPENDS], "YES") != 0) ||
490 (pkg->buildinfo[BI_IGNORE_RECOMMENDED] != NULL && 491 (pkg->buildinfo[BI_IGNORE_RECOMMENDED] != NULL &&
491 strcasecmp(pkg->buildinfo[BI_IGNORE_RECOMMENDED], "NO") != 0)) { 492 strcasecmp(pkg->buildinfo[BI_IGNORE_RECOMMENDED], "NO") != 0)) {
492 warnx("%s was built to ignore ABI dependencies", pkg->pkgname); 493 warnx("%s was built to ignore ABI dependencies", pkg->pkgname);
493 } 494 }
494 495
495 return 0; 496 return 0;
496} 497}
497 498
498/* 499/*
499 * Free buildinfo. 500 * Free buildinfo.
500 */ 501 */
501static void 502static void
502free_buildinfo(struct pkg_task *pkg) 503free_buildinfo(struct pkg_task *pkg)
503{ 504{
504 size_t i; 505 size_t i;
505 506
506 for (i = 0; i < BI_ENUM_COUNT; ++i) { 507 for (i = 0; i < BI_ENUM_COUNT; ++i) {
507 free(pkg->buildinfo[i]); 508 free(pkg->buildinfo[i]);
508 pkg->buildinfo[i] = NULL; 509 pkg->buildinfo[i] = NULL;
509 } 510 }
510} 511}
511 512
512/* 513/*
513 * Write meta data files to pkgdb after creating the directory. 514 * Write meta data files to pkgdb after creating the directory.
514 */ 515 */
515static int 516static int
516write_meta_data(struct pkg_task *pkg) 517write_meta_data(struct pkg_task *pkg)
517{ 518{
518 const struct pkg_meta_desc *descr; 519 const struct pkg_meta_desc *descr;
519 char *filename, **target; 520 char *filename, **target;
520 size_t len; 521 size_t len;
521 ssize_t ret; 522 ssize_t ret;
522 int fd; 523 int fd;
523 524
524 if (Fake) 525 if (Fake)
525 return 0; 526 return 0;
526 527
527 if (mkdir_p(pkg->install_logdir)) { 528 if (mkdir_p(pkg->install_logdir)) {
528 warn("Can't create pkgdb entry: %s", pkg->install_logdir); 529 warn("Can't create pkgdb entry: %s", pkg->install_logdir);
529 return -1; 530 return -1;
530 } 531 }
531 532
532 for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { 533 for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) {
533 target = (char **)((char *)&pkg->meta_data + 534 target = (char **)((char *)&pkg->meta_data +
534 descr->entry_offset); 535 descr->entry_offset);
535 if (*target == NULL) 536 if (*target == NULL)
536 continue; 537 continue;
537 filename = xasprintf("%s/%s", pkg->install_logdir, 538 filename = xasprintf("%s/%s", pkg->install_logdir,
538 descr->entry_filename); 539 descr->entry_filename);
539 (void)unlink(filename); 540 (void)unlink(filename);
540 fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, descr->perm); 541 fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, descr->perm);
541 if (fd == -1) { 542 if (fd == -1) {
542 warn("Can't open meta data file: %s", filename); 543 warn("Can't open meta data file: %s", filename);
543 return -1; 544 return -1;
544 } 545 }
545 len = strlen(*target); 546 len = strlen(*target);
546 do { 547 do {
547 ret = write(fd, *target, len); 548 ret = write(fd, *target, len);
548 if (ret == -1) { 549 if (ret == -1) {
549 warn("Can't write meta data file: %s", 550 warn("Can't write meta data file: %s",
550 filename); 551 filename);
551 free(filename); 552 free(filename);
 553 close(fd);
552 return -1; 554 return -1;
553 } 555 }
554 len -= ret; 556 len -= ret;
555 } while (ret > 0); 557 } while (ret > 0);
556 if (close(fd) == -1) { 558 if (close(fd) == -1) {
557 warn("Can't close meta data file: %s", filename); 559 warn("Can't close meta data file: %s", filename);
558 free(filename); 560 free(filename);
559 return -1; 561 return -1;
560 } 562 }
561 free(filename); 563 free(filename);
562 } 564 }
563 565
564 return 0; 566 return 0;
565} 567}
566 568
567/* 569/*
568 * Helper function for extract_files. 570 * Helper function for extract_files.
569 */ 571 */
570static int 572static int
571copy_data_to_disk(struct archive *reader, struct archive *writer, 573copy_data_to_disk(struct archive *reader, struct archive *writer,
572 const char *filename) 574 const char *filename)
573{ 575{
574 int r; 576 int r;
575 const void *buff; 577 const void *buff;
576 size_t size; 578 size_t size;
577 off_t offset; 579 off_t offset;
578 580
579 for (;;) { 581 for (;;) {
580 r = archive_read_data_block(reader, &buff, &size, &offset); 582 r = archive_read_data_block(reader, &buff, &size, &offset);
581 if (r == ARCHIVE_EOF) 583 if (r == ARCHIVE_EOF)
582 return 0; 584 return 0;
583 if (r != ARCHIVE_OK) { 585 if (r != ARCHIVE_OK) {
584 warnx("Read error for %s: %s", filename, 586 warnx("Read error for %s: %s", filename,
585 archive_error_string(reader)); 587 archive_error_string(reader));
586 return -1; 588 return -1;
587 } 589 }
588 r = archive_write_data_block(writer, buff, size, offset); 590 r = archive_write_data_block(writer, buff, size, offset);
589 if (r != ARCHIVE_OK) { 591 if (r != ARCHIVE_OK) {
590 warnx("Write error for %s: %s", filename, 592 warnx("Write error for %s: %s", filename,
591 archive_error_string(writer)); 593 archive_error_string(writer));
592 return -1; 594 return -1;
593 } 595 }
594 } 596 }
595} 597}
596 598
597/* 599/*
598 * Extract package. 600 * Extract package.
599 * Any misordered, missing or unlisted file in the package is an error. 601 * Any misordered, missing or unlisted file in the package is an error.
600 */ 602 */
601 603
602static const int extract_flags = /* ARCHIVE_EXTRACT_OWNER | */ 604static const int extract_flags = /* ARCHIVE_EXTRACT_OWNER | */
603 ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_UNLINK | 605 ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_UNLINK |
604 ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR; 606 ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR;
605 607
606static int 608static int
607extract_files(struct pkg_task *pkg) 609extract_files(struct pkg_task *pkg)
608{ 610{
609 char cmd[MaxPathSize]; 611 char cmd[MaxPathSize];
610 const char *owner, *group, *permissions; 612 const char *owner, *group, *permissions;
611 struct archive *writer; 613 struct archive *writer;
612 int r; 614 int r;
613 plist_t *p; 615 plist_t *p;
614 const char *last_file; 616 const char *last_file;
615 char *fullpath; 617 char *fullpath;
616 618
617 if (Fake) 619 if (Fake)
618 return 0; 620 return 0;
619 621
620 if (mkdir_p(pkg->install_prefix)) { 622 if (mkdir_p(pkg->install_prefix)) {
621 warn("Can't create prefix: %s", pkg->install_prefix); 623 warn("Can't create prefix: %s", pkg->install_prefix);
622 return -1; 624 return -1;
623 } 625 }
624 626
625 if (!NoRecord && !pkgdb_open(ReadWrite)) { 627 if (!NoRecord && !pkgdb_open(ReadWrite)) {
626 warn("Can't open pkgdb for writing"); 628 warn("Can't open pkgdb for writing");
627 return -1; 629 return -1;
628 } 630 }
629 631
630 if (chdir(pkg->install_prefix) == -1) { 632 if (chdir(pkg->install_prefix) == -1) {
631 warn("Can't change into prefix: %s", pkg->install_prefix); 633 warn("Can't change into prefix: %s", pkg->install_prefix);
632 return -1; 634 return -1;
633 } 635 }
634 636
635 writer = archive_write_disk_new(); 637 writer = archive_write_disk_new();
636 archive_write_disk_set_options(writer, extract_flags); 638 archive_write_disk_set_options(writer, extract_flags);
637 archive_write_disk_set_standard_lookup(writer); 639 archive_write_disk_set_standard_lookup(writer);
638 640
639 owner = NULL; 641 owner = NULL;
640 group = NULL; 642 group = NULL;
641 permissions = NULL; 643 permissions = NULL;
642 last_file = NULL; 644 last_file = NULL;
643 645
644 r = -1; 646 r = -1;
645 647
646 for (p = pkg->plist.head; p != NULL; p = p->next) { 648 for (p = pkg->plist.head; p != NULL; p = p->next) {
647 switch (p->type) { 649 switch (p->type) {
648 case PLIST_FILE: 650 case PLIST_FILE:
649 last_file = p->name; 651 last_file = p->name;
650 if (pkg->entry == NULL) { 652 if (pkg->entry == NULL) {
651 warnx("PLIST entry not in package (%s)", 653 warnx("PLIST entry not in package (%s)",
652 archive_entry_pathname(pkg->entry)); 654 archive_entry_pathname(pkg->entry));
653 goto out; 655 goto out;
654 } 656 }
655 if (strcmp(p->name, archive_entry_pathname(pkg->entry))) { 657 if (strcmp(p->name, archive_entry_pathname(pkg->entry))) {
656 warnx("PLIST entry and package don't match (%s vs %s)", 658 warnx("PLIST entry and package don't match (%s vs %s)",
657 p->name, archive_entry_pathname(pkg->entry)); 659 p->name, archive_entry_pathname(pkg->entry));
658 goto out; 660 goto out;
659 } 661 }
660 fullpath = xasprintf("%s/%s", pkg->prefix, p->name); 662 fullpath = xasprintf("%s/%s", pkg->prefix, p->name);
661 pkgdb_store(fullpath, pkg->pkgname); 663 pkgdb_store(fullpath, pkg->pkgname);
662 free(fullpath); 664 free(fullpath);
663 if (Verbose) 665 if (Verbose)
664 printf("%s", p->name); 666 printf("%s", p->name);
665 break; 667 break;
666 668
667 case PLIST_CMD: 669 case PLIST_CMD:
668 if (format_cmd(cmd, sizeof(cmd), p->name, pkg->prefix, last_file)) 670 if (format_cmd(cmd, sizeof(cmd), p->name, pkg->prefix, last_file))
669 return -1; 671 return -1;
670 printf("Executing '%s'\n", cmd); 672 printf("Executing '%s'\n", cmd);
671 if (!Fake && system(cmd)) 673 if (!Fake && system(cmd))
672 warnx("command '%s' failed", cmd); /* XXX bail out? */ 674 warnx("command '%s' failed", cmd); /* XXX bail out? */
673 continue; 675 continue;
674 676
675 case PLIST_CHMOD: 677 case PLIST_CHMOD:
676 permissions = p->name; 678 permissions = p->name;
677 continue; 679 continue;
678 680
679 case PLIST_CHOWN: 681 case PLIST_CHOWN:
680 owner = p->name; 682 owner = p->name;
681 continue; 683 continue;
682 684
683 case PLIST_CHGRP: 685 case PLIST_CHGRP:
684 group = p->name; 686 group = p->name;
685 continue; 687 continue;
686 688
687 case PLIST_IGNORE: 689 case PLIST_IGNORE:
688 p = p->next; 690 p = p->next;
689 continue; 691 continue;
690 692
691 default: 693 default:
692 continue; 694 continue;
693 } 695 }
694 696
695 r = archive_write_header(writer, pkg->entry); 697 r = archive_write_header(writer, pkg->entry);
696 if (r != ARCHIVE_OK) { 698 if (r != ARCHIVE_OK) {
697 warnx("Failed to write %s: %s", 699 warnx("Failed to write %s: %s",
698 archive_entry_pathname(pkg->entry), 700 archive_entry_pathname(pkg->entry),
699 archive_error_string(writer)); 701 archive_error_string(writer));
700 goto out; 702 goto out;
701 } 703 }
702 704
703 if (owner != NULL) 705 if (owner != NULL)
704 archive_entry_set_uname(pkg->entry, owner); 706 archive_entry_set_uname(pkg->entry, owner);
705 if (group != NULL) 707 if (group != NULL)
706 archive_entry_set_uname(pkg->entry, group); 708 archive_entry_set_uname(pkg->entry, group);
707 if (permissions != NULL) { 709 if (permissions != NULL) {
708 mode_t mode; 710 mode_t mode;
709 711
710 mode = archive_entry_mode(pkg->entry); 712 mode = archive_entry_mode(pkg->entry);
711 mode = getmode(setmode(permissions), mode); 713 mode = getmode(setmode(permissions), mode);
712 archive_entry_set_mode(pkg->entry, mode); 714 archive_entry_set_mode(pkg->entry, mode);
713 } 715 }
714 716
715 r = copy_data_to_disk(pkg->archive, writer, 717 r = copy_data_to_disk(pkg->archive, writer,
716 archive_entry_pathname(pkg->entry)); 718 archive_entry_pathname(pkg->entry));
717 if (r) 719 if (r)
718 goto out; 720 goto out;
719 if (Verbose) 721 if (Verbose)
720 printf("\n"); 722 printf("\n");
721 723
722 r = archive_read_next_header(pkg->archive, &pkg->entry); 724 r = archive_read_next_header(pkg->archive, &pkg->entry);
723 if (r == ARCHIVE_EOF) { 725 if (r == ARCHIVE_EOF) {
724 pkg->entry = NULL; 726 pkg->entry = NULL;
725 continue; 727 continue;
726 } 728 }
727 if (r != ARCHIVE_OK) { 729 if (r != ARCHIVE_OK) {
728 warnx("Failed to read from archive: %s", 730 warnx("Failed to read from archive: %s",
729 archive_error_string(pkg->archive)); 731 archive_error_string(pkg->archive));
730 goto out; 732 goto out;
731 } 733 }
732 } 734 }
733 735
734 if (pkg->entry != NULL) { 736 if (pkg->entry != NULL) {
735 warnx("Package contains entries not in PLIST: %s", 737 warnx("Package contains entries not in PLIST: %s",
736 archive_entry_pathname(pkg->entry)); 738 archive_entry_pathname(pkg->entry));
737 goto out; 739 goto out;
738 } 740 }
739 741
740 r = 0; 742 r = 0;
741 743
742out: 744out:
743 if (!NoRecord) 745 if (!NoRecord)
744 pkgdb_close(); 746 pkgdb_close();
745 archive_write_close(writer); 747 archive_write_close(writer);
746 archive_write_finish(writer); 748 archive_write_finish(writer);
747 749
748 return r; 750 return r;
749} 751}
750 752
751/* 753/*
752 * Register dependencies after sucessfully installing the package. 754 * Register dependencies after sucessfully installing the package.
753 */ 755 */
754static void 756static void
755pkg_register_depends(struct pkg_task *pkg) 757pkg_register_depends(struct pkg_task *pkg)
756{ 758{
757 int fd; 759 int fd;
758 size_t text_len, i; 760 size_t text_len, i;
759 char *required_by, *text; 761 char *required_by, *text;
760 762
761 if (Fake) 763 if (Fake)
762 return; 764 return;
763 765
764 if (pkg->other_version != NULL) 766 if (pkg->other_version != NULL)
765 return; /* XXX It's using the old dependencies. */ 767 return; /* XXX It's using the old dependencies. */
766 768
767 text = xasprintf("%s\n", pkg->pkgname); 769 text = xasprintf("%s\n", pkg->pkgname);
768 text_len = strlen(text); 770 text_len = strlen(text);
769 771
770 for (i = 0; i < pkg->dep_length; ++i) { 772 for (i = 0; i < pkg->dep_length; ++i) {
771 required_by = pkgdb_pkg_file(pkg->dependencies[i], REQUIRED_BY_FNAME); 773 required_by = pkgdb_pkg_file(pkg->dependencies[i], REQUIRED_BY_FNAME);
772 774
773 fd = open(required_by, O_WRONLY | O_APPEND | O_CREAT, 0644); 775 fd = open(required_by, O_WRONLY | O_APPEND | O_CREAT, 0644);
774 if (fd == -1) 776 if (fd == -1) {
775 warn("can't open dependency file '%s'," 777 warn("can't open dependency file '%s',"
776 "registration is incomplete!", required_by); 778 "registration is incomplete!", required_by);
777 else if (write(fd, text, text_len) != text_len) 779 close(fd);
 780 } else if (write(fd, text, text_len) != text_len) {
778 warn("can't write to dependency file `%s'", required_by); 781 warn("can't write to dependency file `%s'", required_by);
779 else if (close(fd) == -1) 782 close(fd);
 783 } else if (close(fd) == -1)
780 warn("cannot close file %s", required_by); 784 warn("cannot close file %s", required_by);
781 785
782 free(required_by); 786 free(required_by);
783 } 787 }
784 788
785 free(text); 789 free(text);
786} 790}
787 791
788/* 792/*
789 * Reduce the result from uname(3) to a canonical form. 793 * Reduce the result from uname(3) to a canonical form.
790 */ 794 */
791static void 795static void
792normalise_platform(struct utsname *host_name) 796normalise_platform(struct utsname *host_name)
793{ 797{
794#ifdef NUMERIC_VERSION_ONLY 798#ifdef NUMERIC_VERSION_ONLY
795 size_t span; 799 size_t span;
796 800
797 span = strspn(host_name->release, "0123456789."); 801 span = strspn(host_name->release, "0123456789.");
798 host_name->release[span] = '\0'; 802 host_name->release[span] = '\0';
799#endif 803#endif
800} 804}
801 805
802/* 806/*
803 * Check build platform of the package against local host. 807 * Check build platform of the package against local host.
804 */ 808 */
805static int 809static int
806check_platform(struct pkg_task *pkg) 810check_platform(struct pkg_task *pkg)
807{ 811{
808 struct utsname host_uname; 812 struct utsname host_uname;
809 const char *effective_arch; 813 const char *effective_arch;
810 int fatal; 814 int fatal;
811 815
812 if (uname(&host_uname) < 0) { 816 if (uname(&host_uname) < 0) {
813 if (Force) { 817 if (Force) {
814 warnx("uname() failed, continuing."); 818 warnx("uname() failed, continuing.");
815 return 0; 819 return 0;
816 } else { 820 } else {
817 warnx("uname() failed, aborting."); 821 warnx("uname() failed, aborting.");
818 return -1; 822 return -1;
819 } 823 }
820 } 824 }
821 825
822 normalise_platform(&host_uname); 826 normalise_platform(&host_uname);
823 827
824 if (OverrideMachine != NULL) 828 if (OverrideMachine != NULL)
825 effective_arch = OverrideMachine; 829 effective_arch = OverrideMachine;
826 else 830 else
827 effective_arch = MACHINE_ARCH; 831 effective_arch = MACHINE_ARCH;
828 832
829 /* If either the OS or arch are different, bomb */ 833 /* If either the OS or arch are different, bomb */
830 if (strcmp(OPSYS_NAME, pkg->buildinfo[BI_OPSYS]) || 834 if (strcmp(OPSYS_NAME, pkg->buildinfo[BI_OPSYS]) ||
831 strcmp(effective_arch, pkg->buildinfo[BI_MACHINE_ARCH]) != 0) 835 strcmp(effective_arch, pkg->buildinfo[BI_MACHINE_ARCH]) != 0)
832 fatal = 1; 836 fatal = 1;
833 else 837 else
834 fatal = 0; 838 fatal = 0;
835 839
836 if (fatal || 840 if (fatal ||
837 strcmp(host_uname.release, pkg->buildinfo[BI_OS_VERSION]) != 0) { 841 strcmp(host_uname.release, pkg->buildinfo[BI_OS_VERSION]) != 0) {
838 warnx("Warning: package `%s' was built for a platform:", 842 warnx("Warning: package `%s' was built for a platform:",
839 pkg->pkgname); 843 pkg->pkgname);
840 warnx("%s/%s %s (pkg) vs. %s/%s %s (this host)", 844 warnx("%s/%s %s (pkg) vs. %s/%s %s (this host)",
841 pkg->buildinfo[BI_OPSYS], 845 pkg->buildinfo[BI_OPSYS],
842 pkg->buildinfo[BI_MACHINE_ARCH], 846 pkg->buildinfo[BI_MACHINE_ARCH],
843 pkg->buildinfo[BI_OS_VERSION], 847 pkg->buildinfo[BI_OS_VERSION],
844 OPSYS_NAME, 848 OPSYS_NAME,
845 effective_arch, 849 effective_arch,
846 host_uname.release); 850 host_uname.release);
847 if (!Force && fatal) 851 if (!Force && fatal)
848 return -1; 852 return -1;
849 } 853 }
850 return 0; 854 return 0;
851} 855}
852 856
853/* 857/*
854 * Run the install script. 858 * Run the install script.
855 */ 859 */
856static int 860static int
857run_install_script(struct pkg_task *pkg, const char *argument) 861run_install_script(struct pkg_task *pkg, const char *argument)
858{ 862{
859 int ret; 863 int ret;
860 char *filename; 864 char *filename;
861 865
862 if (pkg->meta_data.meta_install == NULL || NoInstall) 866 if (pkg->meta_data.meta_install == NULL || NoInstall)
863 return 0; 867 return 0;
864 868
865 if (Destdir != NULL) 869 if (Destdir != NULL)
866 setenv(PKG_DESTDIR_VNAME, Destdir, 1); 870 setenv(PKG_DESTDIR_VNAME, Destdir, 1);
867 setenv(PKG_PREFIX_VNAME, pkg->prefix, 1); 871 setenv(PKG_PREFIX_VNAME, pkg->prefix, 1);
868 setenv(PKG_METADATA_DIR_VNAME, pkg->logdir, 1); 872 setenv(PKG_METADATA_DIR_VNAME, pkg->logdir, 1);
869 setenv(PKG_REFCOUNT_DBDIR_VNAME, pkgdb_refcount_dir(), 1); 873 setenv(PKG_REFCOUNT_DBDIR_VNAME, pkgdb_refcount_dir(), 1);
870 874
871 if (Verbose) 875 if (Verbose)
872 printf("Running install with PRE-INSTALL for %s.\n", pkg->pkgname); 876 printf("Running install with PRE-INSTALL for %s.\n", pkg->pkgname);
873 if (Fake) 877 if (Fake)
874 return 0; 878 return 0;
875 879
876 filename = pkgdb_pkg_file(pkg->pkgname, INSTALL_FNAME); 880 filename = pkgdb_pkg_file(pkg->pkgname, INSTALL_FNAME);
877 881
878 ret = 0; 882 ret = 0;
879 errno = 0; 883 errno = 0;
880 if (fcexec(pkg->install_logdir, filename, pkg->pkgname, argument, 884 if (fcexec(pkg->install_logdir, filename, pkg->pkgname, argument,
881 (void *)NULL)) { 885 (void *)NULL)) {
882 if (errno != 0) 886 if (errno != 0)
883 warn("exec of install script failed"); 887 warn("exec of install script failed");
884 else 888 else
885 warnx("install script returned error status"); 889 warnx("install script returned error status");
886 ret = -1; 890 ret = -1;
887 } 891 }
888 free(filename); 892 free(filename);
889 893
890 return ret; 894 return ret;
891} 895}
892 896
893struct find_conflict_data { 897struct find_conflict_data {
894 const char *pkg; 898 const char *pkg;
895 const char *old_pkg; 899 const char *old_pkg;
896 const char *pattern; 900 const char *pattern;
897}; 901};
898 902
899static int 903static int
900check_explicit_conflict_iter(const char *cur_pkg, void *cookie) 904check_explicit_conflict_iter(const char *cur_pkg, void *cookie)
901{ 905{
902 struct find_conflict_data *data = cookie; 906 struct find_conflict_data *data = cookie;
903 907
904 if (data->old_pkg && strcmp(data->old_pkg, cur_pkg) == 0) 908 if (data->old_pkg && strcmp(data->old_pkg, cur_pkg) == 0)
905 return 0; 909 return 0;
906 910
907 warnx("Package `%s' conflicts with `%s', and `%s' is installed.", 911 warnx("Package `%s' conflicts with `%s', and `%s' is installed.",
908 data->pkg, data->pattern, cur_pkg); 912 data->pkg, data->pattern, cur_pkg);
909 913
910 return 1; 914 return 1;
911} 915}
912 916
913static int 917static int
914check_explicit_conflict(struct pkg_task *pkg) 918check_explicit_conflict(struct pkg_task *pkg)
915{ 919{
916 struct find_conflict_data data; 920 struct find_conflict_data data;
917 char *installed, *installed_pattern; 921 char *installed, *installed_pattern;
918 plist_t *p; 922 plist_t *p;
919 int status; 923 int status;
920 924
921 status = 0; 925 status = 0;
922 926
923 for (p = pkg->plist.head; p != NULL; p = p->next) { 927 for (p = pkg->plist.head; p != NULL; p = p->next) {
924 if (p->type == PLIST_IGNORE) { 928 if (p->type == PLIST_IGNORE) {
925 p = p->next; 929 p = p->next;
926 continue; 930 continue;
927 } 931 }
928 if (p->type != PLIST_PKGCFL) 932 if (p->type != PLIST_PKGCFL)
929 continue; 933 continue;
930 data.pkg = pkg->pkgname; 934 data.pkg = pkg->pkgname;
931 data.old_pkg = pkg->other_version; 935 data.old_pkg = pkg->other_version;
932 data.pattern = p->name; 936 data.pattern = p->name;
933 status |= match_installed_pkgs(p->name, 937 status |= match_installed_pkgs(p->name,
934 check_explicit_conflict_iter, &data); 938 check_explicit_conflict_iter, &data);
935 } 939 }
936 940
937 if (some_installed_package_conflicts_with(pkg->pkgname, 941 if (some_installed_package_conflicts_with(pkg->pkgname,
938 pkg->other_version, &installed, &installed_pattern)) { 942 pkg->other_version, &installed, &installed_pattern)) {
939 warnx("Installed package `%s' conflicts with `%s' when trying to install `%s'.", 943 warnx("Installed package `%s' conflicts with `%s' when trying to install `%s'.",
940 installed, installed_pattern, pkg->pkgname); 944 installed, installed_pattern, pkg->pkgname);
941 free(installed); 945 free(installed);
942 free(installed_pattern); 946 free(installed_pattern);
943 status |= -1; 947 status |= -1;
944 } 948 }
945 949
946 return status; 950 return status;
947} 951}
948 952
949static int 953static int
950check_implicit_conflict(struct pkg_task *pkg) 954check_implicit_conflict(struct pkg_task *pkg)
951{ 955{
952 plist_t *p; 956 plist_t *p;
953 char *fullpath, *existing; 957 char *fullpath, *existing;
954 int status; 958 int status;
955 959
956 if (!pkgdb_open(ReadOnly)) { 960 if (!pkgdb_open(ReadOnly)) {
957#if notyet /* XXX empty pkgdb without database? */ 961#if notyet /* XXX empty pkgdb without database? */
958 warn("Can't open pkgdb for reading"); 962 warn("Can't open pkgdb for reading");
959 return -1; 963 return -1;
960#else 964#else
961 return 0; 965 return 0;
962#endif 966#endif
963 } 967 }
964 968
965 status = 0; 969 status = 0;
966 970
967 for (p = pkg->plist.head; p != NULL; p = p->next) { 971 for (p = pkg->plist.head; p != NULL; p = p->next) {
968 if (p->type == PLIST_IGNORE) { 972 if (p->type == PLIST_IGNORE) {
969 p = p->next; 973 p = p->next;
970 continue; 974 continue;
971 } else if (p->type != PLIST_FILE) 975 } else if (p->type != PLIST_FILE)
972 continue; 976 continue;
973 977
974 fullpath = xasprintf("%s/%s", pkg->prefix, p->name); 978 fullpath = xasprintf("%s/%s", pkg->prefix, p->name);
975 existing = pkgdb_retrieve(fullpath); 979 existing = pkgdb_retrieve(fullpath);
976 free(fullpath); 980 free(fullpath);
977 if (existing == NULL) 981 if (existing == NULL)
978 continue; 982 continue;
979 if (pkg->other_version != NULL && 983 if (pkg->other_version != NULL &&
980 strcmp(pkg->other_version, existing) == 0) 984 strcmp(pkg->other_version, existing) == 0)
981 continue; 985 continue;
982 986
983 warnx("Conflicting PLIST with %s: %s", existing, p->name); 987 warnx("Conflicting PLIST with %s: %s", existing, p->name);
984 if (!Force) { 988 if (!Force) {
985 status = -1; 989 status = -1;
986 if (!Verbose) 990 if (!Verbose)
987 break; 991 break;
988 } 992 }
989 } 993 }
990 994
991 pkgdb_close(); 995 pkgdb_close();
992 return status; 996 return status;
993} 997}
994 998
995static int 999static int
996check_dependencies(struct pkg_task *pkg) 1000check_dependencies(struct pkg_task *pkg)
997{ 1001{
998 plist_t *p; 1002 plist_t *p;
999 char *best_installed; 1003 char *best_installed;
1000 int status; 1004 int status;
1001 size_t i; 1005 size_t i;
1002 1006
1003 status = 0; 1007 status = 0;
1004 1008
1005 for (p = pkg->plist.head; p != NULL; p = p->next) { 1009 for (p = pkg->plist.head; p != NULL; p = p->next) {
1006 if (p->type == PLIST_IGNORE) { 1010 if (p->type == PLIST_IGNORE) {
1007 p = p->next; 1011 p = p->next;
1008 continue; 1012 continue;
1009 } else if (p->type != PLIST_PKGDEP) 1013 } else if (p->type != PLIST_PKGDEP)
1010 continue; 1014 continue;
1011 1015
1012 best_installed = find_best_matching_installed_pkg(p->name); 1016 best_installed = find_best_matching_installed_pkg(p->name);
1013 1017
1014 if (best_installed == NULL) { 1018 if (best_installed == NULL) {
1015 /* XXX check cyclic dependencies? */ 1019 /* XXX check cyclic dependencies? */
1016 if (Fake || NoRecord) { 1020 if (Fake || NoRecord) {
1017 if (!Force) { 1021 if (!Force) {
1018 warnx("Missing dependency %s\n", 1022 warnx("Missing dependency %s\n",
1019 p->name); 1023 p->name);
1020 status = -1; 1024 status = -1;
1021 break; 1025 break;
1022 } 1026 }
1023 warnx("Missing dependency %s, continuing", 1027 warnx("Missing dependency %s, continuing",
1024 p->name); 1028 p->name);
1025 continue; 1029 continue;
1026 } 1030 }
1027 if (pkg_do(p->name, 1, 0)) { 1031 if (pkg_do(p->name, 1, 0)) {
1028 warnx("Can't install dependency %s", p->name); 1032 warnx("Can't install dependency %s", p->name);
1029 status = -1; 1033 status = -1;
1030 break; 1034 break;
1031 } 1035 }
1032 best_installed = find_best_matching_installed_pkg(p->name); 1036 best_installed = find_best_matching_installed_pkg(p->name);
1033 if (best_installed == NULL && Force) { 1037 if (best_installed == NULL && Force) {
1034 warnx("Missing dependency %s ignored", p->name); 1038 warnx("Missing dependency %s ignored", p->name);
1035 continue; 1039 continue;
1036 } else if (best_installed == NULL) { 1040 } else if (best_installed == NULL) {
1037 warnx("Just installed dependency %s disappeared", p->name); 1041 warnx("Just installed dependency %s disappeared", p->name);
1038 status = -1; 1042 status = -1;
1039 break; 1043 break;
1040 } 1044 }
1041 } 1045 }
1042 for (i = 0; i < pkg->dep_length; ++i) { 1046 for (i = 0; i < pkg->dep_length; ++i) {
1043 if (strcmp(best_installed, pkg->dependencies[i]) == 0) 1047 if (strcmp(best_installed, pkg->dependencies[i]) == 0)
1044 break; 1048 break;
1045 } 1049 }
1046 if (i < pkg->dep_length) { 1050 if (i < pkg->dep_length) {
1047 /* Already used as dependency, so skip it. */ 1051 /* Already used as dependency, so skip it. */
1048 free(best_installed); 1052 free(best_installed);
1049 continue; 1053 continue;
1050 } 1054 }
1051 if (pkg->dep_length + 1 >= pkg->dep_allocated) { 1055 if (pkg->dep_length + 1 >= pkg->dep_allocated) {
1052 char **tmp; 1056 char **tmp;
1053 pkg->dep_allocated = 2 * pkg->dep_allocated + 1; 1057 pkg->dep_allocated = 2 * pkg->dep_allocated + 1;
1054 pkg->dependencies = xrealloc(pkg->dependencies, 1058 pkg->dependencies = xrealloc(pkg->dependencies,
1055 pkg->dep_allocated * sizeof(*tmp)); 1059 pkg->dep_allocated * sizeof(*tmp));
1056 } 1060 }
1057 pkg->dependencies[pkg->dep_length++] = best_installed; 1061 pkg->dependencies[pkg->dep_length++] = best_installed;
1058 } 1062 }
1059 1063
1060 return status; 1064 return status;
1061} 1065}
1062 1066
1063/* 1067/*
1064 * If this package uses pkg_views, register it in the default view. 1068 * If this package uses pkg_views, register it in the default view.
1065 */ 1069 */
1066static void 1070static void
1067pkg_register_views(struct pkg_task *pkg) 1071pkg_register_views(struct pkg_task *pkg)
1068{ 1072{
1069 if (Fake || NoView || pkg->meta_data.meta_views == NULL) 1073 if (Fake || NoView || pkg->meta_data.meta_views == NULL)
1070 return; 1074 return;
1071 1075
1072 if (Verbose) { 1076 if (Verbose) {
1073 printf("%s/pkg_view -d %s %s%s %s%s %sadd %s\n", 1077 printf("%s/pkg_view -d %s %s%s %s%s %sadd %s\n",
1074 BINDIR, _pkgdb_getPKGDB_DIR(), 1078 BINDIR, _pkgdb_getPKGDB_DIR(),
1075 View ? "-w " : "", View ? View : "", 1079 View ? "-w " : "", View ? View : "",
1076 Viewbase ? "-W " : "", Viewbase ? Viewbase : "", 1080 Viewbase ? "-W " : "", Viewbase ? Viewbase : "",
1077 Verbose ? "-v " : "", pkg->pkgname); 1081 Verbose ? "-v " : "", pkg->pkgname);
1078 } 1082 }
1079 1083
1080 fexec_skipempty(BINDIR "/pkg_view", "-d", _pkgdb_getPKGDB_DIR(), 1084 fexec_skipempty(BINDIR "/pkg_view", "-d", _pkgdb_getPKGDB_DIR(),
1081 View ? "-w " : "", View ? View : "", 1085 View ? "-w " : "", View ? View : "",
1082 Viewbase ? "-W " : "", Viewbase ? Viewbase : "", 1086 Viewbase ? "-W " : "", Viewbase ? Viewbase : "",
1083 Verbose ? "-v " : "", "add", pkg->pkgname, 1087 Verbose ? "-v " : "", "add", pkg->pkgname,
1084 (void *)NULL); 1088 (void *)NULL);
1085} 1089}
1086 1090
1087static int 1091static int
1088preserve_meta_data_file(struct pkg_task *pkg, const char *name) 1092preserve_meta_data_file(struct pkg_task *pkg, const char *name)
1089{ 1093{
1090 char *old_file, *new_file; 1094 char *old_file, *new_file;
1091 int rv; 1095 int rv;
1092 1096
1093 if (Fake) 1097 if (Fake)
1094 return 0; 1098 return 0;
1095 1099
1096 old_file = pkgdb_pkg_file(pkg->other_version, name); 1100 old_file = pkgdb_pkg_file(pkg->other_version, name);
1097 new_file = pkgdb_pkg_file(pkg->pkgname, name); 1101 new_file = pkgdb_pkg_file(pkg->pkgname, name);
1098 rv = 0; 1102 rv = 0;
1099 if (rename(old_file, new_file) == -1 && errno != ENOENT) { 1103 if (rename(old_file, new_file) == -1 && errno != ENOENT) {
1100 warn("Can't move %s from %s to %s", name, old_file, new_file); 1104 warn("Can't move %s from %s to %s", name, old_file, new_file);
1101 rv = -1;  1105 rv = -1;
1102 } 1106 }
1103 free(old_file); 1107 free(old_file);
1104 free(new_file); 1108 free(new_file);
1105 return rv; 1109 return rv;
1106} 1110}
1107 1111
1108static int 1112static int
1109start_replacing(struct pkg_task *pkg) 1113start_replacing(struct pkg_task *pkg)
1110{ 1114{
1111 if (preserve_meta_data_file(pkg, REQUIRED_BY_FNAME)) 1115 if (preserve_meta_data_file(pkg, REQUIRED_BY_FNAME))
1112 return -1; 1116 return -1;
1113 1117
1114 if (preserve_meta_data_file(pkg, PRESERVE_FNAME)) 1118 if (preserve_meta_data_file(pkg, PRESERVE_FNAME))
1115 return -1; 1119 return -1;
1116 1120
1117 if (pkg->meta_data.meta_installed_info == NULL && 1121 if (pkg->meta_data.meta_installed_info == NULL &&
1118 preserve_meta_data_file(pkg, INSTALLED_INFO_FNAME)) 1122 preserve_meta_data_file(pkg, INSTALLED_INFO_FNAME))
1119 return -1; 1123 return -1;
1120 1124
1121 if (Verbose || Fake) { 1125 if (Verbose || Fake) {
1122 printf("%s/pkg_delete -K %s -p %s%s%s '%s'\n", 1126 printf("%s/pkg_delete -K %s -p %s%s%s '%s'\n",
1123 BINDIR, _pkgdb_getPKGDB_DIR(), pkg->prefix, 1127 BINDIR, _pkgdb_getPKGDB_DIR(), pkg->prefix,
1124 Destdir ? " -P ": "", Destdir ? Destdir : "", 1128 Destdir ? " -P ": "", Destdir ? Destdir : "",
1125 pkg->other_version); 1129 pkg->other_version);
1126 } 1130 }
1127 if (!Fake) 1131 if (!Fake)
1128 fexec_skipempty(BINDIR "/pkg_delete", "-K", _pkgdb_getPKGDB_DIR(), 1132 fexec_skipempty(BINDIR "/pkg_delete", "-K", _pkgdb_getPKGDB_DIR(),
1129 "-p", pkg->prefix, 1133 "-p", pkg->prefix,
1130 Destdir ? "-P": "", Destdir ? Destdir : "", 1134 Destdir ? "-P": "", Destdir ? Destdir : "",
1131 pkg->other_version, NULL); 1135 pkg->other_version, NULL);
1132 1136
1133 /* XXX Check return value and do what? */ 1137 /* XXX Check return value and do what? */
1134 return 0; 1138 return 0;
1135} 1139}
1136 1140
1137static int check_input(const char *line, size_t len) 1141static int check_input(const char *line, size_t len)
1138{ 1142{
1139 if (line == NULL || len == 0) 1143 if (line == NULL || len == 0)
1140 return 1; 1144 return 1;
1141 switch (*line) { 1145 switch (*line) {
1142 case 'Y': 1146 case 'Y':
1143 case 'y': 1147 case 'y':
1144 case 'T': 1148 case 'T':
1145 case 't': 1149 case 't':
1146 case '1': 1150 case '1':
1147 return 0; 1151 return 0;
1148 default: 1152 default:
1149 return 1; 1153 return 1;
1150 } 1154 }
1151} 1155}
1152 1156
1153static int 1157static int
1154check_signature(struct pkg_task *pkg, void *signature_cookie, int invalid_sig) 1158check_signature(struct pkg_task *pkg, void *signature_cookie, int invalid_sig)
1155{ 1159{
1156 char *line; 1160 char *line;
1157 size_t len; 1161 size_t len;
1158 1162
1159 if (strcasecmp(verified_installation, "never") == 0) 1163 if (strcasecmp(verified_installation, "never") == 0)
1160 return 0; 1164 return 0;
1161 if (strcasecmp(verified_installation, "always") == 0) { 1165 if (strcasecmp(verified_installation, "always") == 0) {
1162 if (invalid_sig) 1166 if (invalid_sig)
1163 warnx("No valid signature found, rejected"); 1167 warnx("No valid signature found, rejected");
1164 return invalid_sig; 1168 return invalid_sig;
1165 } 1169 }
1166 if (strcasecmp(verified_installation, "trusted") == 0) { 1170 if (strcasecmp(verified_installation, "trusted") == 0) {
1167 if (!invalid_sig) 1171 if (!invalid_sig)
1168 return 0; 1172 return 0;
1169 fprintf(stderr, "No valid signature found for %s.\n", 1173 fprintf(stderr, "No valid signature found for %s.\n",
1170 pkg->pkgname); 1174 pkg->pkgname);
1171 fprintf(stderr, 1175 fprintf(stderr,
1172 "Do you want to proceed with the installation [y/n]?\n"); 1176 "Do you want to proceed with the installation [y/n]?\n");
1173 line = fgetln(stdin, &len); 1177 line = fgetln(stdin, &len);
1174 if (check_input(line, len)) { 1178 if (check_input(line, len)) {
1175 fprintf(stderr, "Cancelling installation\n"); 1179 fprintf(stderr, "Cancelling installation\n");
1176 return 1; 1180 return 1;
1177 } 1181 }
1178 return 0; 1182 return 0;
1179 } 1183 }
1180 if (strcasecmp(verified_installation, "interactive") == 0) { 1184 if (strcasecmp(verified_installation, "interactive") == 0) {
1181 fprintf(stderr, "Do you want to proceed with " 1185 fprintf(stderr, "Do you want to proceed with "
1182 "the installation of %s [y/n]?\n", pkg->pkgname); 1186 "the installation of %s [y/n]?\n", pkg->pkgname);
1183 line = fgetln(stdin, &len); 1187 line = fgetln(stdin, &len);
1184 if (check_input(line, len)) { 1188 if (check_input(line, len)) {
1185 fprintf(stderr, "Cancelling installation\n"); 1189 fprintf(stderr, "Cancelling installation\n");
1186 return 1; 1190 return 1;
1187 } 1191 }
1188 return 0; 1192 return 0;
1189 } 1193 }
1190 warnx("Unknown value of configuration variable VERIFIED_INSTALLATION"); 1194 warnx("Unknown value of configuration variable VERIFIED_INSTALLATION");
1191 return 1; 1195 return 1;
1192} 1196}
1193 1197
1194static int 1198static int
1195check_vulnerable(struct pkg_task *pkg) 1199check_vulnerable(struct pkg_task *pkg)
1196{ 1200{
1197 static struct pkg_vulnerabilities *pv; 1201 static struct pkg_vulnerabilities *pv;
1198 int require_check; 1202 int require_check;
1199 char *line; 1203 char *line;
1200 size_t len; 1204 size_t len;
1201 1205
1202 if (strcasecmp(check_vulnerabilities, "never") == 0) 1206 if (strcasecmp(check_vulnerabilities, "never") == 0)
1203 return 0; 1207 return 0;
1204 else if (strcasecmp(check_vulnerabilities, "always")) 1208 else if (strcasecmp(check_vulnerabilities, "always"))
1205 require_check = 1; 1209 require_check = 1;
1206 else if (strcasecmp(check_vulnerabilities, "interactive")) 1210 else if (strcasecmp(check_vulnerabilities, "interactive"))
1207 require_check = 0; 1211 require_check = 0;
1208 else { 1212 else {
1209 warnx("Unknown value of the configuration variable" 1213 warnx("Unknown value of the configuration variable"
1210 "CHECK_VULNERABILITIES"); 1214 "CHECK_VULNERABILITIES");
1211 return 1; 1215 return 1;
1212 } 1216 }
1213 1217
1214 if (pv == NULL) { 1218 if (pv == NULL) {
1215 pv = read_pkg_vulnerabilities(pkg_vulnerabilities_file, 1219 pv = read_pkg_vulnerabilities(pkg_vulnerabilities_file,
1216 require_check, 0); 1220 require_check, 0);
1217 if (pv == NULL) 1221 if (pv == NULL)
1218 return require_check; 1222 return require_check;
1219 } 1223 }
1220 1224
1221 if (!audit_package(pv, pkg->pkgname, NULL, 0, 2)) 1225 if (!audit_package(pv, pkg->pkgname, NULL, 0, 2))
1222 return 0; 1226 return 0;
1223 1227
1224 if (require_check) 1228 if (require_check)
1225 return 1; 1229 return 1;
1226 1230
1227 fprintf(stderr, "Do you want to proceed with the installation of %s" 1231 fprintf(stderr, "Do you want to proceed with the installation of %s"
1228 " [y/n]?\n", pkg->pkgname); 1232 " [y/n]?\n", pkg->pkgname);
1229 line = fgetln(stdin, &len); 1233 line = fgetln(stdin, &len);
1230 if (check_input(line, len)) { 1234 if (check_input(line, len)) {
1231 fprintf(stderr, "Cancelling installation\n"); 1235 fprintf(stderr, "Cancelling installation\n");
1232 return 1; 1236 return 1;
1233 } 1237 }
1234 return 0; 1238 return 0;
1235} 1239}
1236 1240
1237/* 1241/*
1238 * Install a single package. 1242 * Install a single package.
1239 */ 1243 */
1240static int 1244static int
1241pkg_do(const char *pkgpath, int mark_automatic, int top_level) 1245pkg_do(const char *pkgpath, int mark_automatic, int top_level)
1242{ 1246{
1243 int status, invalid_sig; 1247 int status, invalid_sig;
1244 void *archive_cookie; 1248 void *archive_cookie;
1245 void *signature_cookie; 1249 void *signature_cookie;
1246 struct pkg_task *pkg; 1250 struct pkg_task *pkg;
1247 1251
1248 pkg = xcalloc(1, sizeof(*pkg)); 1252 pkg = xcalloc(1, sizeof(*pkg));
1249 1253
1250 status = -1; 1254 status = -1;
1251 1255
1252 pkg->archive = find_archive(pkgpath, &archive_cookie, top_level); 1256 pkg->archive = find_archive(pkgpath, &archive_cookie, top_level);
1253 if (pkg->archive == NULL) { 1257 if (pkg->archive == NULL) {
1254 warnx("no pkg found for '%s', sorry.", pkgpath); 1258 warnx("no pkg found for '%s', sorry.", pkgpath);
1255 goto clean_find_archive; 1259 goto clean_find_archive;
1256 } 1260 }
1257 1261
1258 invalid_sig = pkg_verify_signature(&pkg->archive, &pkg->entry, 1262 invalid_sig = pkg_verify_signature(&pkg->archive, &pkg->entry,
1259 &pkg->pkgname, &signature_cookie); 1263 &pkg->pkgname, &signature_cookie);
1260 1264
1261 if (pkg->archive == NULL) 1265 if (pkg->archive == NULL)
1262 goto clean_memory; 1266 goto clean_memory;
1263 1267
1264 if (read_meta_data(pkg)) 1268 if (read_meta_data(pkg))
1265 goto clean_memory; 1269 goto clean_memory;
1266 1270
1267 /* Parse PLIST early, so that messages can use real package name. */ 1271 /* Parse PLIST early, so that messages can use real package name. */
1268 if (pkg_parse_plist(pkg)) 1272 if (pkg_parse_plist(pkg))
1269 goto clean_memory; 1273 goto clean_memory;
1270 1274
1271 if (check_signature(pkg, &signature_cookie, invalid_sig)) 1275 if (check_signature(pkg, &signature_cookie, invalid_sig))
1272 goto clean_memory; 1276 goto clean_memory;
1273 1277
1274 if (check_vulnerable(pkg)) 1278 if (check_vulnerable(pkg))
1275 goto clean_memory; 1279 goto clean_memory;
1276 1280
1277 if (pkg->meta_data.meta_mtree != NULL) 1281 if (pkg->meta_data.meta_mtree != NULL)
1278 warnx("mtree specification in pkg `%s' ignored", pkg->pkgname); 1282 warnx("mtree specification in pkg `%s' ignored", pkg->pkgname);
1279 1283
1280 if (pkg->meta_data.meta_views != NULL) { 1284 if (pkg->meta_data.meta_views != NULL) {
1281 pkg->logdir = xstrdup(pkg->prefix); 1285 pkg->logdir = xstrdup(pkg->prefix);
1282 _pkgdb_setPKGDB_DIR(dirname_of(pkg->logdir)); 1286 _pkgdb_setPKGDB_DIR(dirname_of(pkg->logdir));
1283 } else { 1287 } else {
1284 pkg->logdir = xasprintf("%s/%s", _pkgdb_getPKGDB_DIR(), 1288 pkg->logdir = xasprintf("%s/%s", _pkgdb_getPKGDB_DIR(),
1285 pkg->pkgname); 1289 pkg->pkgname);
1286 } 1290 }
1287 1291
1288 if (Destdir != NULL) { 1292 if (Destdir != NULL) {
1289 pkg->install_logdir = xasprintf("%s/%s", Destdir, pkg->logdir); 1293 pkg->install_logdir = xasprintf("%s/%s", Destdir, pkg->logdir);
1290 _pkgdb_setPKGDB_DIR(dirname_of(pkg->install_logdir)); 1294 _pkgdb_setPKGDB_DIR(dirname_of(pkg->install_logdir));
1291 } else 1295 } else
1292 pkg->install_logdir = xstrdup(pkg->logdir); 1296 pkg->install_logdir = xstrdup(pkg->logdir);
1293 1297
1294 if (NoRecord && !Fake) { 1298 if (NoRecord && !Fake) {
1295 const char *tmpdir; 1299 const char *tmpdir;
1296 1300
1297 tmpdir = getenv("TMPDIR"); 1301 tmpdir = getenv("TMPDIR");
1298 if (tmpdir == NULL) 1302 if (tmpdir == NULL)
1299 tmpdir = "/tmp"; 1303 tmpdir = "/tmp";
1300 1304
1301 free(pkg->install_logdir); 1305 free(pkg->install_logdir);
1302 pkg->install_logdir = xasprintf("%s/pkg_install.XXXXXX", tmpdir); 1306 pkg->install_logdir = xasprintf("%s/pkg_install.XXXXXX", tmpdir);
1303 /* XXX pkg_add -u... */ 1307 /* XXX pkg_add -u... */
1304 if (mkdtemp(pkg->install_logdir) == NULL) { 1308 if (mkdtemp(pkg->install_logdir) == NULL) {
1305 warn("mkdtemp failed"); 1309 warn("mkdtemp failed");
1306 goto clean_memory; 1310 goto clean_memory;
1307 } 1311 }
1308 } 1312 }
1309 1313
1310 if (check_already_installed(pkg) == 0) { 1314 if (check_already_installed(pkg) == 0) {
1311 status = 0; 1315 status = 0;
1312 goto clean_memory; 1316 goto clean_memory;
1313 } 1317 }
1314 1318
1315 if (read_buildinfo(pkg)) 1319 if (read_buildinfo(pkg))
1316 goto clean_memory; 1320 goto clean_memory;
1317 1321
1318 if (check_platform(pkg)) 1322 if (check_platform(pkg))
1319 goto clean_memory; 1323 goto clean_memory;
1320 1324
1321 if (check_other_installed(pkg)) 1325 if (check_other_installed(pkg))
1322 goto clean_memory;  1326 goto clean_memory;
1323 1327
1324 if (check_explicit_conflict(pkg)) 1328 if (check_explicit_conflict(pkg))
1325 goto clean_memory; 1329 goto clean_memory;
1326 1330
1327 if (check_implicit_conflict(pkg)) 1331 if (check_implicit_conflict(pkg))
1328 goto clean_memory; 1332 goto clean_memory;
1329 1333
1330 if (pkg->other_version != NULL) { 1334 if (pkg->other_version != NULL) {
1331 /* 1335 /*
1332 * Replacing an existing package. 1336 * Replacing an existing package.
1333 * Write meta-data, get rid of the old version, 1337 * Write meta-data, get rid of the old version,
1334 * install/update dependencies and finally extract. 1338 * install/update dependencies and finally extract.
1335 */ 1339 */
1336 if (write_meta_data(pkg)) 1340 if (write_meta_data(pkg))
1337 goto nuke_pkgdb; 1341 goto nuke_pkgdb;
1338 1342
1339 if (start_replacing(pkg)) 1343 if (start_replacing(pkg))
1340 goto nuke_pkgdb; 1344 goto nuke_pkgdb;
1341 1345
1342 if (check_dependencies(pkg)) 1346 if (check_dependencies(pkg))
1343 goto nuke_pkgdb; 1347 goto nuke_pkgdb;
1344 } else { 1348 } else {
1345 /* 1349 /*
1346 * Normal installation. 1350 * Normal installation.
1347 * Install/update dependencies first and 1351 * Install/update dependencies first and
1348 * write the current package to disk afterwards. 1352 * write the current package to disk afterwards.
1349 */  1353 */
1350 if (check_dependencies(pkg)) 1354 if (check_dependencies(pkg))
1351 goto clean_memory; 1355 goto clean_memory;
1352 1356
1353 if (write_meta_data(pkg)) 1357 if (write_meta_data(pkg))
1354 goto nuke_pkgdb; 1358 goto nuke_pkgdb;
1355 } 1359 }
1356 1360
1357 if (run_install_script(pkg, "PRE-INSTALL")) 1361 if (run_install_script(pkg, "PRE-INSTALL"))
1358 goto nuke_pkgdb; 1362 goto nuke_pkgdb;
1359 1363
1360 if (extract_files(pkg)) 1364 if (extract_files(pkg))
1361 goto nuke_pkg; 1365 goto nuke_pkg;
1362 1366
1363 if (run_install_script(pkg, "POST-INSTALL")) 1367 if (run_install_script(pkg, "POST-INSTALL"))
1364 goto nuke_pkgdb; 1368 goto nuke_pkgdb;
1365 1369
1366 /* XXX keep +INSTALL_INFO for updates? */ 1370 /* XXX keep +INSTALL_INFO for updates? */
1367 /* XXX keep +PRESERVE for updates? */ 1371 /* XXX keep +PRESERVE for updates? */
1368 if (mark_automatic) 1372 if (mark_automatic)
1369 mark_as_automatic_installed(pkg->pkgname, 1); 1373 mark_as_automatic_installed(pkg->pkgname, 1);
1370 1374
1371 pkg_register_depends(pkg); 1375 pkg_register_depends(pkg);
1372 1376
1373 if (Verbose) 1377 if (Verbose)
1374 printf("Package %s registered in %s\n", pkg->pkgname, pkg->install_logdir); 1378 printf("Package %s registered in %s\n", pkg->pkgname, pkg->install_logdir);
1375 1379
1376 if (pkg->meta_data.meta_display != NULL) 1380 if (pkg->meta_data.meta_display != NULL)
1377 fputs(pkg->meta_data.meta_display, stdout); 1381 fputs(pkg->meta_data.meta_display, stdout);
1378 1382
1379 pkg_register_views(pkg); 1383 pkg_register_views(pkg);
1380 1384
1381 status = 0; 1385 status = 0;
1382 goto clean_memory; 1386 goto clean_memory;
1383 1387
1384nuke_pkg: 1388nuke_pkg:
1385 if (!Fake) { 1389 if (!Fake) {
1386 if (pkg->other_version) { 1390 if (pkg->other_version) {
1387 warnx("Updating of %s to %s failed.", 1391 warnx("Updating of %s to %s failed.",
1388 pkg->other_version, pkg->pkgname); 1392 pkg->other_version, pkg->pkgname);
1389 warnx("Remember to run pkg_admin rebuild-tree after fixing this."); 1393 warnx("Remember to run pkg_admin rebuild-tree after fixing this.");
1390 } 1394 }
1391 delete_package(FALSE, FALSE, &pkg->plist, FALSE, Destdir); 1395 delete_package(FALSE, FALSE, &pkg->plist, FALSE, Destdir);
1392 } 1396 }
1393 1397
1394nuke_pkgdb: 1398nuke_pkgdb:
1395 if (!Fake) { 1399 if (!Fake) {
1396 if (recursive_remove(pkg->install_logdir, 1)) 1400 if (recursive_remove(pkg->install_logdir, 1))
1397 warn("Couldn't remove %s", pkg->install_logdir); 1401 warn("Couldn't remove %s", pkg->install_logdir);
1398 free(pkg->install_logdir); 1402 free(pkg->install_logdir);
1399 free(pkg->logdir); 1403 free(pkg->logdir);
1400 pkg->install_logdir = NULL; 1404 pkg->install_logdir = NULL;
1401 pkg->logdir = NULL; 1405 pkg->logdir = NULL;
1402 } 1406 }
1403 1407
1404clean_memory: 1408clean_memory:
1405 if (pkg->logdir != NULL && NoRecord && !Fake) { 1409 if (pkg->logdir != NULL && NoRecord && !Fake) {
1406 if (recursive_remove(pkg->install_logdir, 1)) 1410 if (recursive_remove(pkg->install_logdir, 1))
1407 warn("Couldn't remove %s", pkg->install_logdir); 1411 warn("Couldn't remove %s", pkg->install_logdir);
1408 } 1412 }
1409 free(pkg->install_prefix); 1413 free(pkg->install_prefix);
1410 free(pkg->install_logdir); 1414 free(pkg->install_logdir);
1411 free(pkg->logdir); 1415 free(pkg->logdir);
1412 free_buildinfo(pkg); 1416 free_buildinfo(pkg);
1413 free_plist(&pkg->plist); 1417 free_plist(&pkg->plist);
1414 free_meta_data(pkg); 1418 free_meta_data(pkg);
1415 if (pkg->archive) { 1419 if (pkg->archive) {
1416 archive_read_close(pkg->archive); 1420 archive_read_close(pkg->archive);
1417 close_archive(archive_cookie); 1421 close_archive(archive_cookie);
1418 } 1422 }
1419 free(pkg->other_version); 1423 free(pkg->other_version);
1420 free(pkg->pkgname); 1424 free(pkg->pkgname);
1421 pkg_free_signature(signature_cookie); 1425 pkg_free_signature(signature_cookie);
1422clean_find_archive: 1426clean_find_archive:
1423 free(pkg); 1427 free(pkg);
1424 return status; 1428 return status;
1425} 1429}
1426 1430
1427int 1431int
1428pkg_perform(lpkg_head_t *pkgs) 1432pkg_perform(lpkg_head_t *pkgs)
1429{ 1433{
1430 int errors = 0; 1434 int errors = 0;
1431 lpkg_t *lpp; 1435 lpkg_t *lpp;
1432 1436
1433 while ((lpp = TAILQ_FIRST(pkgs)) != NULL) { 1437 while ((lpp = TAILQ_FIRST(pkgs)) != NULL) {
1434 if (pkg_do(lpp->lp_name, Automatic, 1)) 1438 if (pkg_do(lpp->lp_name, Automatic, 1))
1435 ++errors; 1439 ++errors;
1436 TAILQ_REMOVE(pkgs, lpp, lp_link); 1440 TAILQ_REMOVE(pkgs, lpp, lp_link);
1437 free_lpkg(lpp); 1441 free_lpkg(lpp);
1438 } 1442 }
1439 1443
1440 return errors; 1444 return errors;
1441} 1445}

cvs diff -r1.3 -r1.4 pkgsrc/pkgtools/pkg_install/files/lib/pkcs7.c (switch to unified diff)

--- pkgsrc/pkgtools/pkg_install/files/lib/pkcs7.c 2009/02/16 20:59:11 1.3
+++ pkgsrc/pkgtools/pkg_install/files/lib/pkcs7.c 2009/03/02 14:59:14 1.4
@@ -1,335 +1,336 @@ @@ -1,335 +1,336 @@
1/* $NetBSD: pkcs7.c,v 1.3 2009/02/16 20:59:11 joerg Exp $ */ 1/* $NetBSD: pkcs7.c,v 1.4 2009/03/02 14:59:14 joerg Exp $ */
2#if HAVE_CONFIG_H 2#if HAVE_CONFIG_H
3#include "config.h" 3#include "config.h"
4#endif 4#endif
5#include <nbcompat.h> 5#include <nbcompat.h>
6#if HAVE_SYS_CDEFS_H 6#if HAVE_SYS_CDEFS_H
7#include <sys/cdefs.h> 7#include <sys/cdefs.h>
8#endif 8#endif
9 9
10__RCSID("$NetBSD: pkcs7.c,v 1.3 2009/02/16 20:59:11 joerg Exp $"); 10__RCSID("$NetBSD: pkcs7.c,v 1.4 2009/03/02 14:59:14 joerg Exp $");
11 11
12/*- 12/*-
13 * Copyright (c) 2004, 2008 The NetBSD Foundation, Inc. 13 * Copyright (c) 2004, 2008 The NetBSD Foundation, Inc.
14 * All rights reserved. 14 * All rights reserved.
15 * 15 *
16 * This code is derived from software contributed to The NetBSD Foundation 16 * This code is derived from software contributed to The NetBSD Foundation
17 * by Love Hörnquist Åstrand <lha@it.su.se> 17 * by Love Hörnquist Åstrand <lha@it.su.se>
18 * 18 *
19 * Redistribution and use in source and binary forms, with or without 19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions 20 * modification, are permitted provided that the following conditions
21 * are met: 21 * are met:
22 * 1. Redistributions of source code must retain the above copyright 22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer. 23 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright 24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the 25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution. 26 * documentation and/or other materials provided with the distribution.
27 * 27 *
28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE. 38 * POSSIBILITY OF SUCH DAMAGE.
39 */ 39 */
40 40
41#if HAVE_ERR_H 41#if HAVE_ERR_H
42#include <err.h> 42#include <err.h>
43#endif 43#endif
44 44
45#include <openssl/pkcs7.h> 45#include <openssl/pkcs7.h>
46#include <openssl/evp.h> 46#include <openssl/evp.h>
47#include <openssl/x509.h> 47#include <openssl/x509.h>
48#include <openssl/x509v3.h> 48#include <openssl/x509v3.h>
49#include <openssl/pem.h> 49#include <openssl/pem.h>
50#include <openssl/err.h> 50#include <openssl/err.h>
51 51
52#include "lib.h" 52#include "lib.h"
53 53
54#ifndef __UNCONST 54#ifndef __UNCONST
55#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a)) 55#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a))
56#endif 56#endif
57 57
58#ifndef NS_ANY_CA 58#ifndef NS_ANY_CA
59#define NS_ANY_CA (NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA) 59#define NS_ANY_CA (NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA)
60#endif 60#endif
61 61
62static const int pkg_key_usage = XKU_CODE_SIGN | XKU_SMIME; 62static const int pkg_key_usage = XKU_CODE_SIGN | XKU_SMIME;
63 63
64static int 64static int
65check_ca(X509 *cert) 65check_ca(X509 *cert)
66{ 66{
67 if ((cert->ex_flags & EXFLAG_KUSAGE) != 0 && 67 if ((cert->ex_flags & EXFLAG_KUSAGE) != 0 &&
68 (cert->ex_kusage & KU_KEY_CERT_SIGN) != KU_KEY_CERT_SIGN) 68 (cert->ex_kusage & KU_KEY_CERT_SIGN) != KU_KEY_CERT_SIGN)
69 return 0; 69 return 0;
70 if ((cert->ex_flags & EXFLAG_BCONS) != 0) 70 if ((cert->ex_flags & EXFLAG_BCONS) != 0)
71 return (cert->ex_flags & EXFLAG_CA) == EXFLAG_CA; 71 return (cert->ex_flags & EXFLAG_CA) == EXFLAG_CA;
72 if ((cert->ex_flags & (EXFLAG_V1|EXFLAG_SS)) == (EXFLAG_V1|EXFLAG_SS)) 72 if ((cert->ex_flags & (EXFLAG_V1|EXFLAG_SS)) == (EXFLAG_V1|EXFLAG_SS))
73 return 1; 73 return 1;
74 if ((cert->ex_flags & EXFLAG_KUSAGE) != 0) 74 if ((cert->ex_flags & EXFLAG_KUSAGE) != 0)
75 return 1; 75 return 1;
76 if ((cert->ex_flags & EXFLAG_NSCERT) != 0 && 76 if ((cert->ex_flags & EXFLAG_NSCERT) != 0 &&
77 (cert->ex_nscert & NS_ANY_CA) != 0) 77 (cert->ex_nscert & NS_ANY_CA) != 0)
78 return 1; 78 return 1;
79 return 0; 79 return 0;
80} 80}
81 81
82static STACK_OF(X509) * 82static STACK_OF(X509) *
83file_to_certs(const char *file) 83file_to_certs(const char *file)
84{ 84{
85 unsigned long ret; 85 unsigned long ret;
86 STACK_OF(X509) *certs; 86 STACK_OF(X509) *certs;
87 FILE *f; 87 FILE *f;
88 88
89 if ((f = fopen(file, "r")) == NULL) { 89 if ((f = fopen(file, "r")) == NULL) {
90 warn("open failed %s", file); 90 warn("open failed %s", file);
91 return NULL; 91 return NULL;
92 } 92 }
93 93
94 certs = sk_X509_new_null(); 94 certs = sk_X509_new_null();
95 for (;;) { 95 for (;;) {
96 X509 *cert; 96 X509 *cert;
97 97
98 cert = PEM_read_X509(f, NULL, NULL, NULL); 98 cert = PEM_read_X509(f, NULL, NULL, NULL);
99 if (cert == NULL) { 99 if (cert == NULL) {
100 ret = ERR_GET_REASON(ERR_peek_error()); 100 ret = ERR_GET_REASON(ERR_peek_error());
101 if (ret == PEM_R_NO_START_LINE) { 101 if (ret == PEM_R_NO_START_LINE) {
102 /* End of file reached. no error */ 102 /* End of file reached. no error */
103 ERR_clear_error(); 103 ERR_clear_error();
104 break; 104 break;
105 } 105 }
106 sk_X509_free(certs); 106 sk_X509_free(certs);
107 warnx("Can't read certificate in file: %s", file); 107 warnx("Can't read certificate in file: %s", file);
 108 fclose(f);
108 return NULL; 109 return NULL;
109 } 110 }
110 sk_X509_insert(certs, cert, sk_X509_num(certs)); 111 sk_X509_insert(certs, cert, sk_X509_num(certs));
111 } 112 }
112 113
113 fclose(f); 114 fclose(f);
114 115
115 if (sk_X509_num(certs) == 0) { 116 if (sk_X509_num(certs) == 0) {
116 sk_X509_free(certs); 117 sk_X509_free(certs);
117 certs = NULL; 118 certs = NULL;
118 warnx("No certificate found in file %s", file); 119 warnx("No certificate found in file %s", file);
119 } 120 }
120 121
121 return certs; 122 return certs;
122} 123}
123 124
124int 125int
125easy_pkcs7_verify(const char *content, size_t len, 126easy_pkcs7_verify(const char *content, size_t len,
126 const char *signature, size_t signature_len, 127 const char *signature, size_t signature_len,
127 const char *anchor, int is_pkg) 128 const char *anchor, int is_pkg)
128{ 129{
129 STACK_OF(X509) *cert_chain, *signers; 130 STACK_OF(X509) *cert_chain, *signers;
130 X509_STORE *store; 131 X509_STORE *store;
131 BIO *sig, *in; 132 BIO *sig, *in;
132 PKCS7 *p7; 133 PKCS7 *p7;
133 int i, status; 134 int i, status;
134 X509_NAME *name; 135 X509_NAME *name;
135 char *subject; 136 char *subject;
136 137
137 OpenSSL_add_all_algorithms(); 138 OpenSSL_add_all_algorithms();
138 ERR_load_crypto_strings(); 139 ERR_load_crypto_strings();
139 140
140 status = -1; 141 status = -1;
141 142
142 if (cert_chain_file) 143 if (cert_chain_file)
143 cert_chain = file_to_certs(cert_chain_file); 144 cert_chain = file_to_certs(cert_chain_file);
144 else 145 else
145 cert_chain = NULL; 146 cert_chain = NULL;
146 147
147 store = X509_STORE_new(); 148 store = X509_STORE_new();
148 if (store == NULL) { 149 if (store == NULL) {
149 sk_X509_free(cert_chain); 150 sk_X509_free(cert_chain);
150 warnx("Failed to create certificate store"); 151 warnx("Failed to create certificate store");
151 return -1; 152 return -1;
152 } 153 }
153 154
154 X509_STORE_load_locations(store, anchor, NULL); 155 X509_STORE_load_locations(store, anchor, NULL);
155 156
156 in = BIO_new_mem_buf(__UNCONST(content), len); 157 in = BIO_new_mem_buf(__UNCONST(content), len);
157 sig = BIO_new_mem_buf(__UNCONST(signature), signature_len); 158 sig = BIO_new_mem_buf(__UNCONST(signature), signature_len);
158 signers = NULL; 159 signers = NULL;
159 160
160 p7 = PEM_read_bio_PKCS7(sig, NULL, NULL, NULL); 161 p7 = PEM_read_bio_PKCS7(sig, NULL, NULL, NULL);
161 if (p7 == NULL) { 162 if (p7 == NULL) {
162 warnx("Failed to parse the signature"); 163 warnx("Failed to parse the signature");
163 goto cleanup; 164 goto cleanup;
164 } 165 }
165 166
166 if (PKCS7_verify(p7, cert_chain, store, in, NULL, 0) != 1) { 167 if (PKCS7_verify(p7, cert_chain, store, in, NULL, 0) != 1) {
167 warnx("Failed to verify signature"); 168 warnx("Failed to verify signature");
168 goto cleanup; 169 goto cleanup;
169 } 170 }
170 171
171 signers = PKCS7_get0_signers(p7, NULL, 0); 172 signers = PKCS7_get0_signers(p7, NULL, 0);
172 if (signers == NULL) { 173 if (signers == NULL) {
173 warnx("Failed to get signers"); 174 warnx("Failed to get signers");
174 goto cleanup; 175 goto cleanup;
175 } 176 }
176  177
177 if (sk_X509_num(signers) == 0) { 178 if (sk_X509_num(signers) == 0) {
178 warnx("No signers found"); 179 warnx("No signers found");
179 goto cleanup; 180 goto cleanup;
180 } 181 }
181 182
182 for (i = 0; i < sk_X509_num(signers); i++) { 183 for (i = 0; i < sk_X509_num(signers); i++) {
183 /* Compute ex_xkusage */ 184 /* Compute ex_xkusage */
184 X509_check_purpose(sk_X509_value(signers, i), -1, -1); 185 X509_check_purpose(sk_X509_value(signers, i), -1, -1);
185 186
186 if (check_ca(sk_X509_value(signers, i))) { 187 if (check_ca(sk_X509_value(signers, i))) {
187 warnx("CA keys are not valid for signatures"); 188 warnx("CA keys are not valid for signatures");
188 goto cleanup; 189 goto cleanup;
189 } 190 }
190 if (is_pkg) { 191 if (is_pkg) {
191 if (sk_X509_value(signers, i)->ex_xkusage != pkg_key_usage) { 192 if (sk_X509_value(signers, i)->ex_xkusage != pkg_key_usage) {
192 warnx("Certificate must have CODE SIGNING " 193 warnx("Certificate must have CODE SIGNING "
193 "and EMAIL PROTECTION property"); 194 "and EMAIL PROTECTION property");
194 goto cleanup; 195 goto cleanup;
195 } 196 }
196 } else { 197 } else {
197 if (sk_X509_value(signers, i)->ex_xkusage != 0) { 198 if (sk_X509_value(signers, i)->ex_xkusage != 0) {
198 warnx("Certificate must not have any property"); 199 warnx("Certificate must not have any property");
199 goto cleanup; 200 goto cleanup;
200 } 201 }
201 } 202 }
202 } 203 }
203 204
204 printf("Sigature ok, signed by:\n"); 205 printf("Sigature ok, signed by:\n");
205 206
206 for (i = 0; i < sk_X509_num(signers); i++) { 207 for (i = 0; i < sk_X509_num(signers); i++) {
207 name = X509_get_subject_name(sk_X509_value(signers, i)); 208 name = X509_get_subject_name(sk_X509_value(signers, i));
208 subject = X509_NAME_oneline(name, NULL, 0); 209 subject = X509_NAME_oneline(name, NULL, 0);
209 210
210 printf("\t%s\n", subject); 211 printf("\t%s\n", subject);
211 212
212 OPENSSL_free(subject); 213 OPENSSL_free(subject);
213 } 214 }
214 215
215 status = 0; 216 status = 0;
216 217
217cleanup: 218cleanup:
218 sk_X509_free(cert_chain); 219 sk_X509_free(cert_chain);
219 sk_X509_free(signers); 220 sk_X509_free(signers);
220 X509_STORE_free(store); 221 X509_STORE_free(store);
221 222
222 PKCS7_free(p7); 223 PKCS7_free(p7);
223 BIO_free(in); 224 BIO_free(in);
224 BIO_free(sig); 225 BIO_free(sig);
225 226
226 return status; 227 return status;
227} 228}
228 229
229static int 230static int
230ssl_pass_cb(char *buf, int size, int rwflag, void *u) 231ssl_pass_cb(char *buf, int size, int rwflag, void *u)
231{ 232{
232 233
233 if (EVP_read_pw_string(buf, size, "Passphrase :", 0)) { 234 if (EVP_read_pw_string(buf, size, "Passphrase :", 0)) {
234#if OPENSSL_VERSION >= 0x0090608fL 235#if OPENSSL_VERSION >= 0x0090608fL
235 OPENSSL_cleanse(buf, size); 236 OPENSSL_cleanse(buf, size);
236#else 237#else
237 memset(buf, 0, size); 238 memset(buf, 0, size);
238#endif 239#endif
239 return 0; 240 return 0;
240 } 241 }
241 return strlen(buf); 242 return strlen(buf);
242} 243}
243 244
244int 245int
245easy_pkcs7_sign(const char *content, size_t len, 246easy_pkcs7_sign(const char *content, size_t len,
246 char **signature, size_t *signature_len, 247 char **signature, size_t *signature_len,
247 const char *key_file, const char *cert_file) 248 const char *key_file, const char *cert_file)
248{ 249{
249 FILE *f; 250 FILE *f;
250 X509 *certificate; 251 X509 *certificate;
251 STACK_OF(X509) *c, *cert_chain; 252 STACK_OF(X509) *c, *cert_chain;
252 EVP_PKEY *private_key; 253 EVP_PKEY *private_key;
253 char *tmp_sig; 254 char *tmp_sig;
254 BIO *out, *in; 255 BIO *out, *in;
255 PKCS7 *p7; 256 PKCS7 *p7;
256 int status; 257 int status;
257 258
258 OpenSSL_add_all_algorithms(); 259 OpenSSL_add_all_algorithms();
259 ERR_load_crypto_strings(); 260 ERR_load_crypto_strings();
260 261
261 status = -1; 262 status = -1;
262 private_key = NULL; 263 private_key = NULL;
263 cert_chain = NULL; 264 cert_chain = NULL;
264 in = NULL; 265 in = NULL;
265 266
266 c = file_to_certs(cert_file); 267 c = file_to_certs(cert_file);
267 268
268 if (sk_X509_num(c) != 1) { 269 if (sk_X509_num(c) != 1) {
269 warnx("More then one certificate in the certificate file"); 270 warnx("More then one certificate in the certificate file");
270 goto cleanup; 271 goto cleanup;
271 } 272 }
272 certificate = sk_X509_value(c, 0); 273 certificate = sk_X509_value(c, 0);
273 274
274 /* Compute ex_kusage */ 275 /* Compute ex_kusage */
275 X509_check_purpose(certificate, -1, 0); 276 X509_check_purpose(certificate, -1, 0);
276 277
277 if (check_ca(certificate)) { 278 if (check_ca(certificate)) {
278 warnx("CA keys are not valid for signatures"); 279 warnx("CA keys are not valid for signatures");
279 goto cleanup; 280 goto cleanup;
280 } 281 }
281 282
282 if (certificate->ex_xkusage != pkg_key_usage) { 283 if (certificate->ex_xkusage != pkg_key_usage) {
283 warnx("Certificate must have CODE SIGNING " 284 warnx("Certificate must have CODE SIGNING "
284 "and EMAIL PROTECTION property"); 285 "and EMAIL PROTECTION property");
285 goto cleanup; 286 goto cleanup;
286 } 287 }
287 288
288 if (cert_chain_file) 289 if (cert_chain_file)
289 cert_chain = file_to_certs(cert_chain_file); 290 cert_chain = file_to_certs(cert_chain_file);
290 291
291 if ((f = fopen(key_file, "r")) == NULL) { 292 if ((f = fopen(key_file, "r")) == NULL) {
292 warn("Failed to open private key file %s", key_file); 293 warn("Failed to open private key file %s", key_file);
293 goto cleanup; 294 goto cleanup;
294 } 295 }
295 private_key = PEM_read_PrivateKey(f, NULL, ssl_pass_cb, NULL); 296 private_key = PEM_read_PrivateKey(f, NULL, ssl_pass_cb, NULL);
296 fclose(f); 297 fclose(f);
297 if (private_key == NULL) { 298 if (private_key == NULL) {
298 warnx("Can't read private key: %s", key_file); 299 warnx("Can't read private key: %s", key_file);
299 goto cleanup; 300 goto cleanup;
300 } 301 }
301 302
302 if (X509_check_private_key(certificate, private_key) != 1) { 303 if (X509_check_private_key(certificate, private_key) != 1) {
303 warnx("The private key %s doesn't match the certificate %s", 304 warnx("The private key %s doesn't match the certificate %s",
304 key_file, cert_file); 305 key_file, cert_file);
305 goto cleanup; 306 goto cleanup;
306 } 307 }
307 308
308 in = BIO_new_mem_buf(__UNCONST(content), len); 309 in = BIO_new_mem_buf(__UNCONST(content), len);
309 310
310 p7 = PKCS7_sign(certificate, private_key, cert_chain, in,  311 p7 = PKCS7_sign(certificate, private_key, cert_chain, in,
311 PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY); 312 PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY);
312 if (p7 == NULL) { 313 if (p7 == NULL) {
313 warnx("Failed to create signature structure"); 314 warnx("Failed to create signature structure");
314 goto cleanup; 315 goto cleanup;
315 } 316 }
316 317
317 out = BIO_new(BIO_s_mem()); 318 out = BIO_new(BIO_s_mem());
318 PEM_write_bio_PKCS7(out, p7); 319 PEM_write_bio_PKCS7(out, p7);
319 *signature_len = BIO_get_mem_data(out, &tmp_sig); 320 *signature_len = BIO_get_mem_data(out, &tmp_sig);
320 *signature = xmalloc(*signature_len); 321 *signature = xmalloc(*signature_len);
321 memcpy(*signature, tmp_sig, *signature_len); 322 memcpy(*signature, tmp_sig, *signature_len);
322 BIO_free_all(out); 323 BIO_free_all(out);
323 324
324 PKCS7_free(p7); 325 PKCS7_free(p7);
325 326
326 status = 0; 327 status = 0;
327 328
328cleanup: 329cleanup:
329 sk_X509_free(c); 330 sk_X509_free(c);
330 sk_X509_free(cert_chain); 331 sk_X509_free(cert_chain);
331 EVP_PKEY_free(private_key); 332 EVP_PKEY_free(private_key);
332 BIO_free(in); 333 BIO_free(in);
333 334
334 return status; 335 return status;
335} 336}

cvs diff -r1.5 -r1.6 pkgsrc/pkgtools/pkg_install/files/lib/pkg_signature.c (switch to unified diff)

--- pkgsrc/pkgtools/pkg_install/files/lib/pkg_signature.c 2009/02/13 13:17:41 1.5
+++ pkgsrc/pkgtools/pkg_install/files/lib/pkg_signature.c 2009/03/02 14:59:14 1.6
@@ -1,710 +1,714 @@ @@ -1,710 +1,714 @@
1/* $NetBSD: pkg_signature.c,v 1.5 2009/02/13 13:17:41 joerg Exp $ */ 1/* $NetBSD: pkg_signature.c,v 1.6 2009/03/02 14:59:14 joerg Exp $ */
2 2
3#if HAVE_CONFIG_H 3#if HAVE_CONFIG_H
4#include "config.h" 4#include "config.h"
5#endif 5#endif
6#include <nbcompat.h> 6#include <nbcompat.h>
7#if HAVE_SYS_CDEFS_H 7#if HAVE_SYS_CDEFS_H
8#include <sys/cdefs.h> 8#include <sys/cdefs.h>
9#endif 9#endif
10__RCSID("$NetBSD: pkg_signature.c,v 1.5 2009/02/13 13:17:41 joerg Exp $"); 10__RCSID("$NetBSD: pkg_signature.c,v 1.6 2009/03/02 14:59:14 joerg Exp $");
11 11
12/*- 12/*-
13 * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>. 13 * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
14 * All rights reserved. 14 * All rights reserved.
15 * 15 *
16 * Redistribution and use in source and binary forms, with or without 16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions 17 * modification, are permitted provided that the following conditions
18 * are met: 18 * are met:
19 * 19 *
20 * 1. Redistributions of source code must retain the above copyright 20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer. 21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright 22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in 23 * notice, this list of conditions and the following disclaimer in
24 * the documentation and/or other materials provided with the 24 * the documentation and/or other materials provided with the
25 * distribution. 25 * distribution.
26 * 26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
30 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 30 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
31 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 31 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 32 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
33 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 33 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 34 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
35 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 35 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 36 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
37 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE. 38 * SUCH DAMAGE.
39 */ 39 */
40 40
41#if HAVE_SYS_WAIT_H 41#if HAVE_SYS_WAIT_H
42#include <sys/wait.h> 42#include <sys/wait.h>
43#endif 43#endif
44#include <ctype.h> 44#include <ctype.h>
45#if HAVE_ERR_H 45#if HAVE_ERR_H
46#include <err.h> 46#include <err.h>
47#endif 47#endif
48#include <errno.h> 48#include <errno.h>
49#include <fcntl.h> 49#include <fcntl.h>
50#include <stdlib.h> 50#include <stdlib.h>
51#ifndef NETBSD 51#ifndef NETBSD
52#include <nbcompat/sha2.h> 52#include <nbcompat/sha2.h>
53#else 53#else
54#include <sha2.h> 54#include <sha2.h>
55#endif 55#endif
56#include <signal.h> 56#include <signal.h>
57#ifdef NETBSD 57#ifdef NETBSD
58#include <unistd.h> 58#include <unistd.h>
59#else 59#else
60#include <nbcompat/unistd.h> 60#include <nbcompat/unistd.h>
61#endif 61#endif
62 62
63#include <archive.h> 63#include <archive.h>
64#include <archive_entry.h> 64#include <archive_entry.h>
65 65
66#include "lib.h" 66#include "lib.h"
67 67
68#define HASH_FNAME "+PKG_HASH" 68#define HASH_FNAME "+PKG_HASH"
69#define SIGNATURE_FNAME "+PKG_SIGNATURE" 69#define SIGNATURE_FNAME "+PKG_SIGNATURE"
70#define GPG_SIGNATURE_FNAME "+PKG_GPG_SIGNATURE" 70#define GPG_SIGNATURE_FNAME "+PKG_GPG_SIGNATURE"
71 71
72struct signature_archive { 72struct signature_archive {
73 struct archive *archive; 73 struct archive *archive;
74 off_t pkg_size; 74 off_t pkg_size;
75 size_t sign_block_len, sign_block_number, sign_cur_block; 75 size_t sign_block_len, sign_block_number, sign_cur_block;
76 char **sign_blocks; 76 char **sign_blocks;
77 unsigned char *sign_buf; 77 unsigned char *sign_buf;
78}; 78};
79 79
80static void 80static void
81hash_block(unsigned char *buf, size_t buf_len, 81hash_block(unsigned char *buf, size_t buf_len,
82 char hash[SHA512_DIGEST_STRING_LENGTH]) 82 char hash[SHA512_DIGEST_STRING_LENGTH])
83{ 83{
84 unsigned char digest[SHA512_DIGEST_LENGTH]; 84 unsigned char digest[SHA512_DIGEST_LENGTH];
85 SHA512_CTX hash_ctx; 85 SHA512_CTX hash_ctx;
86 int i; 86 int i;
87 87
88 SHA512_Init(&hash_ctx); 88 SHA512_Init(&hash_ctx);
89 SHA512_Update(&hash_ctx, buf, buf_len); 89 SHA512_Update(&hash_ctx, buf, buf_len);
90 SHA512_Final(digest, &hash_ctx); 90 SHA512_Final(digest, &hash_ctx);
91 for (i = 0; i < SHA512_DIGEST_LENGTH; ++i) { 91 for (i = 0; i < SHA512_DIGEST_LENGTH; ++i) {
92 unsigned char c; 92 unsigned char c;
93 93
94 c = digest[i] / 16; 94 c = digest[i] / 16;
95 if (c < 10) 95 if (c < 10)
96 hash[2 * i] = '0' + c; 96 hash[2 * i] = '0' + c;
97 else 97 else
98 hash[2 * i] = 'a' - 10 + c; 98 hash[2 * i] = 'a' - 10 + c;
99 99
100 c = digest[i] % 16; 100 c = digest[i] % 16;
101 if (c < 10) 101 if (c < 10)
102 hash[2 * i + 1] = '0' + c; 102 hash[2 * i + 1] = '0' + c;
103 else 103 else
104 hash[2 * i + 1] = 'a' - 10 + c; 104 hash[2 * i + 1] = 'a' - 10 + c;
105 } 105 }
106 hash[2 * i] = '\0'; 106 hash[2 * i] = '\0';
107} 107}
108 108
109static ssize_t 109static ssize_t
110verify_signature_read_cb(struct archive *archive, void *cookie, const void **buf) 110verify_signature_read_cb(struct archive *archive, void *cookie, const void **buf)
111{ 111{
112 struct signature_archive *state = cookie; 112 struct signature_archive *state = cookie;
113 char hash[SHA512_DIGEST_STRING_LENGTH]; 113 char hash[SHA512_DIGEST_STRING_LENGTH];
114 ssize_t len, expected; 114 ssize_t len, expected;
115 115
116 if (state->sign_cur_block >= state->sign_block_number) 116 if (state->sign_cur_block >= state->sign_block_number)
117 return 0; 117 return 0;
118 118
119 /* The following works for sign_block_len > 1 */ 119 /* The following works for sign_block_len > 1 */
120 if (state->sign_cur_block + 1 == state->sign_block_number) 120 if (state->sign_cur_block + 1 == state->sign_block_number)
121 expected = state->pkg_size % state->sign_block_len; 121 expected = state->pkg_size % state->sign_block_len;
122 else 122 else
123 expected = state->sign_block_len; 123 expected = state->sign_block_len;
124 124
125 len = archive_read_data(state->archive, state->sign_buf, expected); 125 len = archive_read_data(state->archive, state->sign_buf, expected);
126 if (len != expected) { 126 if (len != expected) {
127 warnx("Short read from package"); 127 warnx("Short read from package");
128 return -1; 128 return -1;
129 } 129 }
130 130
131 hash_block(state->sign_buf, len, hash); 131 hash_block(state->sign_buf, len, hash);
132 132
133 if (strcmp(hash, state->sign_blocks[state->sign_cur_block]) != 0) { 133 if (strcmp(hash, state->sign_blocks[state->sign_cur_block]) != 0) {
134 warnx("Invalid signature of block %llu", 134 warnx("Invalid signature of block %llu",
135 (unsigned long long)state->sign_cur_block); 135 (unsigned long long)state->sign_cur_block);
136 return -1; 136 return -1;
137 } 137 }
138 ++state->sign_cur_block; 138 ++state->sign_cur_block;
139 *buf = state->sign_buf; 139 *buf = state->sign_buf;
140 return len; 140 return len;
141} 141}
142 142
143static void 143static void
144free_signature_int(struct signature_archive *state) 144free_signature_int(struct signature_archive *state)
145{ 145{
146 size_t i; 146 size_t i;
147 147
148 if (state->sign_blocks != NULL) { 148 if (state->sign_blocks != NULL) {
149 for (i = 0; i < state->sign_block_number; ++i) 149 for (i = 0; i < state->sign_block_number; ++i)
150 free(state->sign_blocks[i]); 150 free(state->sign_blocks[i]);
151 } 151 }
152 free(state->sign_blocks); 152 free(state->sign_blocks);
153 free(state->sign_buf); 153 free(state->sign_buf);
154 free(state); 154 free(state);
155} 155}
156 156
157void 157void
158pkg_free_signature(void *cookie) 158pkg_free_signature(void *cookie)
159{ 159{
160 struct signature_archive *state = cookie; 160 struct signature_archive *state = cookie;
161 161
162 if (state == NULL) 162 if (state == NULL)
163 return; 163 return;
164 164
165 archive_read_finish(state->archive); 165 archive_read_finish(state->archive);
166 free_signature_int(state); 166 free_signature_int(state);
167} 167}
168 168
169static int 169static int
170read_file_from_archive(struct archive *archive, struct archive_entry **entry, 170read_file_from_archive(struct archive *archive, struct archive_entry **entry,
171 const char *fname, char **content, size_t *len) 171 const char *fname, char **content, size_t *len)
172{ 172{
173 int r; 173 int r;
174 174
175 *content = NULL; 175 *content = NULL;
176 *len = 0; 176 *len = 0;
177 177
178retry: 178retry:
179 if (*entry == NULL && 179 if (*entry == NULL &&
180 (r = archive_read_next_header(archive, entry)) != ARCHIVE_OK) { 180 (r = archive_read_next_header(archive, entry)) != ARCHIVE_OK) {
181 if (r == ARCHIVE_FATAL) { 181 if (r == ARCHIVE_FATAL) {
182 warnx("Cannot read from archive: %s", 182 warnx("Cannot read from archive: %s",
183 archive_error_string(archive)); 183 archive_error_string(archive));
184 return -1; 184 return -1;
185 } 185 }
186 return 1; 186 return 1;
187 } 187 }
188 if (strcmp(archive_entry_pathname(*entry), "//") == 0) { 188 if (strcmp(archive_entry_pathname(*entry), "//") == 0) {
189 archive_read_data_skip(archive); 189 archive_read_data_skip(archive);
190 *entry = NULL; 190 *entry = NULL;
191 goto retry; 191 goto retry;
192 } 192 }
193 193
194 if (strcmp(fname, archive_entry_pathname(*entry)) != 0) 194 if (strcmp(fname, archive_entry_pathname(*entry)) != 0)
195 return 1; 195 return 1;
196 196
197 if (archive_entry_size(*entry) > SSIZE_MAX - 1) { 197 if (archive_entry_size(*entry) > SSIZE_MAX - 1) {
198 warnx("signature too large to process"); 198 warnx("signature too large to process");
199 return 1; 199 return 1;
200 } 200 }
201 *len = archive_entry_size(*entry); 201 *len = archive_entry_size(*entry);
202 *content = xmalloc(*len + 1); 202 *content = xmalloc(*len + 1);
203 203
204 if (archive_read_data(archive, *content, *len) != *len) { 204 if (archive_read_data(archive, *content, *len) != *len) {
205 warnx("cannot read complete %s from archive", fname); 205 warnx("cannot read complete %s from archive", fname);
206 free(*content); 206 free(*content);
207 *len = 0; 207 *len = 0;
208 *content = NULL; 208 *content = NULL;
209 return 1; 209 return 1;
210 } 210 }
211 (*content)[*len] = '\0'; 211 (*content)[*len] = '\0';
212 *entry = NULL; 212 *entry = NULL;
213 213
214 return 0; 214 return 0;
215} 215}
216 216
217static int 217static int
218parse_hash_file(const char *hash_file, char **pkgname, 218parse_hash_file(const char *hash_file, char **pkgname,
219 struct signature_archive *state) 219 struct signature_archive *state)
220{ 220{
221 static const char block1[] = "pkgsrc signature\n\nversion: 1\npkgname: "; 221 static const char block1[] = "pkgsrc signature\n\nversion: 1\npkgname: ";
222 static const char block2[] = "algorithm: SHA512\nblock size: "; 222 static const char block2[] = "algorithm: SHA512\nblock size: ";
223 static const char block3[] = "file size: "; 223 static const char block3[] = "file size: ";
224 static const char block4[] = "end pkgsrc signature\n"; 224 static const char block4[] = "end pkgsrc signature\n";
225 char *next; 225 char *next;
226 size_t i, len; 226 size_t i, len;
227 227
228 *pkgname = NULL; 228 *pkgname = NULL;
229 229
230 if (strncmp(hash_file, block1, strlen(block1)) != 0) 230 if (strncmp(hash_file, block1, strlen(block1)) != 0)
231 goto cleanup; 231 goto cleanup;
232 hash_file += strlen(block1); 232 hash_file += strlen(block1);
233 233
234 len = strcspn(hash_file, "\n"); 234 len = strcspn(hash_file, "\n");
235 *pkgname = xmalloc(len + 1); 235 *pkgname = xmalloc(len + 1);
236 memcpy(*pkgname, hash_file, len); 236 memcpy(*pkgname, hash_file, len);
237 (*pkgname)[len] = '\0'; 237 (*pkgname)[len] = '\0';
238 for (i = 0; i < len; ++i) { 238 for (i = 0; i < len; ++i) {
239 if (!isgraph((unsigned char)(*pkgname)[i])) 239 if (!isgraph((unsigned char)(*pkgname)[i]))
240 goto cleanup; 240 goto cleanup;
241 } 241 }
242 hash_file += len + 1; 242 hash_file += len + 1;
243 243
244 if (strncmp(hash_file, block2, strlen(block2)) != 0) 244 if (strncmp(hash_file, block2, strlen(block2)) != 0)
245 goto cleanup; 245 goto cleanup;
246 hash_file += strlen(block2); 246 hash_file += strlen(block2);
247 247
248 errno = 0; 248 errno = 0;
249 if (!isdigit((unsigned char)*hash_file)) 249 if (!isdigit((unsigned char)*hash_file))
250 goto cleanup; 250 goto cleanup;
251 state->sign_block_len = strtoul(hash_file, &next, 10); 251 state->sign_block_len = strtoul(hash_file, &next, 10);
252 hash_file = next; 252 hash_file = next;
253 253
254 /* Assert sane minimum block size of 1KB */ 254 /* Assert sane minimum block size of 1KB */
255 if (*hash_file++ != '\n' || errno == ERANGE || state->sign_block_len < 1024) 255 if (*hash_file++ != '\n' || errno == ERANGE || state->sign_block_len < 1024)
256 goto cleanup; 256 goto cleanup;
257 257
258 if (strncmp(hash_file, block3, strlen(block3)) != 0) 258 if (strncmp(hash_file, block3, strlen(block3)) != 0)
259 goto cleanup; 259 goto cleanup;
260 hash_file += strlen(block3); 260 hash_file += strlen(block3);
261 261
262 errno = 0; 262 errno = 0;
263 if (!isdigit((unsigned char)*hash_file)) 263 if (!isdigit((unsigned char)*hash_file))
264 goto cleanup; 264 goto cleanup;
265 if (sizeof(off_t) >= sizeof(long long)) 265 if (sizeof(off_t) >= sizeof(long long))
266 state->pkg_size = strtoll(hash_file, &next, 10); 266 state->pkg_size = strtoll(hash_file, &next, 10);
267 else 267 else
268 state->pkg_size = strtol(hash_file, &next, 10); 268 state->pkg_size = strtol(hash_file, &next, 10);
269 hash_file = next; 269 hash_file = next;
270 if (*hash_file++ != '\n' || errno == ERANGE || state->pkg_size < 1) 270 if (*hash_file++ != '\n' || errno == ERANGE || state->pkg_size < 1)
271 goto cleanup; 271 goto cleanup;
272 272
273 if (*hash_file++ != '\n') 273 if (*hash_file++ != '\n')
274 goto cleanup; 274 goto cleanup;
275 275
276 if (state->pkg_size / state->sign_block_len > SSIZE_MAX) 276 if (state->pkg_size / state->sign_block_len > SSIZE_MAX)
277 goto cleanup; 277 goto cleanup;
278 state->sign_block_number = (state->pkg_size + 278 state->sign_block_number = (state->pkg_size +
279 state->sign_block_len - 1) / state->sign_block_len; 279 state->sign_block_len - 1) / state->sign_block_len;
280 280
281 state->sign_buf = xmalloc(state->sign_block_len); 281 state->sign_buf = xmalloc(state->sign_block_len);
282 state->sign_blocks = xcalloc(state->sign_block_number, sizeof(char *)); 282 state->sign_blocks = xcalloc(state->sign_block_number, sizeof(char *));
283 283
284 for (i = 0; i < state->sign_block_number; ++i) { 284 for (i = 0; i < state->sign_block_number; ++i) {
285 len = strspn(hash_file, "01234567889abcdef"); 285 len = strspn(hash_file, "01234567889abcdef");
286 if (len != SHA512_DIGEST_LENGTH * 2 || hash_file[len] != '\n') 286 if (len != SHA512_DIGEST_LENGTH * 2 || hash_file[len] != '\n')
287 goto cleanup_hashes; 287 goto cleanup_hashes;
288 state->sign_blocks[i] = xmalloc(len + 1); 288 state->sign_blocks[i] = xmalloc(len + 1);
289 memcpy(state->sign_blocks[i], hash_file, len); 289 memcpy(state->sign_blocks[i], hash_file, len);
290 state->sign_blocks[i][len] = '\0'; 290 state->sign_blocks[i][len] = '\0';
291 hash_file += len + 1; 291 hash_file += len + 1;
292 } 292 }
293 293
294 if (strcmp(hash_file, block4) != 0) 294 if (strcmp(hash_file, block4) != 0)
295 goto cleanup_hashes; 295 goto cleanup_hashes;
296 296
297 return 0; 297 return 0;
298 298
299cleanup_hashes: 299cleanup_hashes:
300 for (i = 0; i < state->sign_block_number; ++i) 300 for (i = 0; i < state->sign_block_number; ++i)
301 free(state->sign_blocks[i]); 301 free(state->sign_blocks[i]);
302 free(state->sign_blocks); 302 free(state->sign_blocks);
303 state->sign_blocks = NULL; 303 state->sign_blocks = NULL;
304 304
305cleanup: 305cleanup:
306 warnx("Unknown format of hash file"); 306 warnx("Unknown format of hash file");
307 free(*pkgname); 307 free(*pkgname);
308 *pkgname = NULL; 308 *pkgname = NULL;
309 return -1; 309 return -1;
310} 310}
311 311
312int 312int
313pkg_verify_signature(struct archive **archive, struct archive_entry **entry, 313pkg_verify_signature(struct archive **archive, struct archive_entry **entry,
314 char **pkgname, void **cookie) 314 char **pkgname, void **cookie)
315{ 315{
316 struct signature_archive *state; 316 struct signature_archive *state;
317 struct archive_entry *my_entry; 317 struct archive_entry *my_entry;
318 struct archive *a; 318 struct archive *a;
319 char *hash_file, *signature_file; 319 char *hash_file, *signature_file;
320 size_t hash_len, signature_len; 320 size_t hash_len, signature_len;
321 int r, has_sig; 321 int r, has_sig;
322 322
323 *pkgname = NULL; 323 *pkgname = NULL;
324 *cookie = NULL; 324 *cookie = NULL;
325 325
326 state = xmalloc(sizeof(*state)); 326 state = xmalloc(sizeof(*state));
327 state->sign_blocks = NULL; 327 state->sign_blocks = NULL;
328 state->sign_buf = NULL; 328 state->sign_buf = NULL;
329 state->archive = NULL; 329 state->archive = NULL;
330 330
331 r = read_file_from_archive(*archive, entry, HASH_FNAME, 331 r = read_file_from_archive(*archive, entry, HASH_FNAME,
332 &hash_file, &hash_len); 332 &hash_file, &hash_len);
333 if (r == -1) { 333 if (r == -1) {
334 archive_read_finish(*archive); 334 archive_read_finish(*archive);
335 *archive = NULL; 335 *archive = NULL;
336 free(state); 336 free(state);
337 goto no_valid_signature; 337 goto no_valid_signature;
338 } else if (r == 1) { 338 } else if (r == 1) {
339 free(state); 339 free(state);
340 goto no_valid_signature; 340 goto no_valid_signature;
341 } 341 }
342 342
343 if (parse_hash_file(hash_file, pkgname, state)) 343 if (parse_hash_file(hash_file, pkgname, state))
344 goto no_valid_signature; 344 goto no_valid_signature;
345 345
346 r = read_file_from_archive(*archive, entry, SIGNATURE_FNAME, 346 r = read_file_from_archive(*archive, entry, SIGNATURE_FNAME,
347 &signature_file, &signature_len); 347 &signature_file, &signature_len);
348 if (r == -1) { 348 if (r == -1) {
349 archive_read_finish(*archive); 349 archive_read_finish(*archive);
350 *archive = NULL; 350 *archive = NULL;
351 free(state); 351 free(state);
352 free(hash_file); 352 free(hash_file);
353 goto no_valid_signature; 353 goto no_valid_signature;
354 } else if (r != 0) { 354 } else if (r != 0) {
355 if (*entry != NULL) 355 if (*entry != NULL)
356 r = read_file_from_archive(*archive, entry, 356 r = read_file_from_archive(*archive, entry,
357 GPG_SIGNATURE_FNAME, 357 GPG_SIGNATURE_FNAME,
358 &signature_file, &signature_len); 358 &signature_file, &signature_len);
359 if (r == -1) { 359 if (r == -1) {
360 archive_read_finish(*archive); 360 archive_read_finish(*archive);
361 *archive = NULL; 361 *archive = NULL;
362 free(state); 362 free(state);
363 free(hash_file); 363 free(hash_file);
364 goto no_valid_signature; 364 goto no_valid_signature;
365 } else if (r != 0) { 365 } else if (r != 0) {
366 free(hash_file); 366 free(hash_file);
367 free(state); 367 free(state);
368 goto no_valid_signature; 368 goto no_valid_signature;
369 } 369 }
370 has_sig = !detached_gpg_verify(hash_file, hash_len, 370 has_sig = !detached_gpg_verify(hash_file, hash_len,
371 signature_file, signature_len, gpg_keyring_verify); 371 signature_file, signature_len, gpg_keyring_verify);
372 372
373 free(signature_file); 373 free(signature_file);
374 } else { 374 } else {
375#ifdef HAVE_SSL 375#ifdef HAVE_SSL
376 has_sig = !easy_pkcs7_verify(hash_file, hash_len, signature_file, 376 has_sig = !easy_pkcs7_verify(hash_file, hash_len, signature_file,
377 signature_len, certs_packages, 1); 377 signature_len, certs_packages, 1);
378 378
379 free(signature_file); 379 free(signature_file);
380#else 380#else
381 warnx("No OpenSSL support compiled in, skipping signature"); 381 warnx("No OpenSSL support compiled in, skipping signature");
382 has_sig = 0; 382 has_sig = 0;
383 free(signature_file); 383 free(signature_file);
384#endif 384#endif
385 } 385 }
386 386
387 r = archive_read_next_header(*archive, &my_entry); 387 r = archive_read_next_header(*archive, &my_entry);
388 if (r != ARCHIVE_OK) { 388 if (r != ARCHIVE_OK) {
389 warnx("Cannot read inner package: %s", 389 warnx("Cannot read inner package: %s",
390 archive_error_string(*archive)); 390 archive_error_string(*archive));
391 free_signature_int(state); 391 free_signature_int(state);
392 goto no_valid_signature; 392 goto no_valid_signature;
393 } 393 }
394 394
395 if (archive_entry_size(my_entry) != state->pkg_size) { 395 if (archive_entry_size(my_entry) != state->pkg_size) {
396 warnx("Package size doesn't match signature"); 396 warnx("Package size doesn't match signature");
397 free_signature_int(state); 397 free_signature_int(state);
398 goto no_valid_signature; 398 goto no_valid_signature;
399 } 399 }
400 400
401 state->archive = *archive; 401 state->archive = *archive;
402 402
403 a = archive_read_new(); 403 a = archive_read_new();
404 archive_read_support_compression_all(a); 404 archive_read_support_compression_all(a);
405 archive_read_support_format_all(a); 405 archive_read_support_format_all(a);
406 if (archive_read_open(a, state, NULL, verify_signature_read_cb, NULL)) { 406 if (archive_read_open(a, state, NULL, verify_signature_read_cb, NULL)) {
407 warnx("Can't open signed package file"); 407 warnx("Can't open signed package file");
408 archive_read_finish(a); 408 archive_read_finish(a);
409 free_signature_int(state); 409 free_signature_int(state);
410 goto no_valid_signature; 410 goto no_valid_signature;
411 } 411 }
412 *archive = a; 412 *archive = a;
413 *entry = NULL; 413 *entry = NULL;
414 *cookie = state; 414 *cookie = state;
415 415
416 return has_sig ? 0 : -1; 416 return has_sig ? 0 : -1;
417 417
418no_valid_signature: 418no_valid_signature:
419 return -1; 419 return -1;
420} 420}
421 421
422int 422int
423pkg_full_signature_check(struct archive **archive) 423pkg_full_signature_check(struct archive **archive)
424{ 424{
425 struct archive_entry *entry = NULL; 425 struct archive_entry *entry = NULL;
426 char *pkgname; 426 char *pkgname;
427 void *cookie; 427 void *cookie;
428 int r; 428 int r;
429 429
430 if (pkg_verify_signature(archive, &entry, &pkgname, &cookie)) 430 if (pkg_verify_signature(archive, &entry, &pkgname, &cookie))
431 return -1; 431 return -1;
432 if (pkgname == NULL) 432 if (pkgname == NULL)
433 return 0; 433 return 0;
434 434
435 /* XXX read PLIST and compare pkgname */ 435 /* XXX read PLIST and compare pkgname */
436 while ((r = archive_read_next_header(*archive, &entry)) == ARCHIVE_OK) 436 while ((r = archive_read_next_header(*archive, &entry)) == ARCHIVE_OK)
437 archive_read_data_skip(*archive); 437 archive_read_data_skip(*archive);
438 438
439 pkg_free_signature(cookie); 439 pkg_free_signature(cookie);
440 free(pkgname); 440 free(pkgname);
441 return r == ARCHIVE_EOF ? 0 : -1; 441 return r == ARCHIVE_EOF ? 0 : -1;
442} 442}
443 443
444static char * 444static char *
445extract_pkgname(int fd) 445extract_pkgname(int fd)
446{ 446{
447 package_t plist; 447 package_t plist;
448 plist_t *p; 448 plist_t *p;
449 struct archive *a; 449 struct archive *a;
450 struct archive_entry *entry; 450 struct archive_entry *entry;
451 char *buf; 451 char *buf;
452 ssize_t len; 452 ssize_t len;
453 int r; 453 int r;
454 454
455 a = archive_read_new(); 455 a = archive_read_new();
456 archive_read_support_compression_all(a); 456 archive_read_support_compression_all(a);
457 archive_read_support_format_all(a); 457 archive_read_support_format_all(a);
458 if (archive_read_open_fd(a, fd, 1024)) { 458 if (archive_read_open_fd(a, fd, 1024)) {
459 warnx("Cannot open binary package: %s", 459 warnx("Cannot open binary package: %s",
460 archive_error_string(a)); 460 archive_error_string(a));
461 archive_read_finish(a); 461 archive_read_finish(a);
462 return NULL; 462 return NULL;
463 } 463 }
464 464
465 r = archive_read_next_header(a, &entry); 465 r = archive_read_next_header(a, &entry);
466 if (r != ARCHIVE_OK) { 466 if (r != ARCHIVE_OK) {
467 warnx("Cannot extract package name: %s", 467 warnx("Cannot extract package name: %s",
468 r == ARCHIVE_EOF ? "EOF" : archive_error_string(a)); 468 r == ARCHIVE_EOF ? "EOF" : archive_error_string(a));
469 archive_read_finish(a); 469 archive_read_finish(a);
470 return NULL; 470 return NULL;
471 } 471 }
472 if (strcmp(archive_entry_pathname(entry), "+CONTENTS") != 0) { 472 if (strcmp(archive_entry_pathname(entry), "+CONTENTS") != 0) {
473 warnx("Invalid binary package, doesn't start with +CONTENTS"); 473 warnx("Invalid binary package, doesn't start with +CONTENTS");
474 archive_read_finish(a); 474 archive_read_finish(a);
475 return NULL; 475 return NULL;
476 } 476 }
477 if (archive_entry_size(entry) > SSIZE_MAX - 1) { 477 if (archive_entry_size(entry) > SSIZE_MAX - 1) {
478 warnx("+CONTENTS too large to process"); 478 warnx("+CONTENTS too large to process");
479 archive_read_finish(a); 479 archive_read_finish(a);
480 return NULL; 480 return NULL;
481 } 481 }
482 482
483 len = archive_entry_size(entry); 483 len = archive_entry_size(entry);
484 buf = xmalloc(len + 1); 484 buf = xmalloc(len + 1);
485 485
486 if (archive_read_data(a, buf, len) != len) { 486 if (archive_read_data(a, buf, len) != len) {
487 warnx("Short read when extracing +CONTENTS"); 487 warnx("Short read when extracing +CONTENTS");
488 free(buf); 488 free(buf);
489 archive_read_finish(a); 489 archive_read_finish(a);
490 return NULL; 490 return NULL;
491 } 491 }
492 buf[len] = '\0'; 492 buf[len] = '\0';
493 493
494 archive_read_finish(a); 494 archive_read_finish(a);
495 495
496 parse_plist(&plist, buf); 496 parse_plist(&plist, buf);
497 free(buf); 497 free(buf);
498 p = find_plist(&plist, PLIST_NAME);  498 p = find_plist(&plist, PLIST_NAME);
499 if (p != NULL) { 499 if (p != NULL) {
500 buf = xstrdup(p->name); 500 buf = xstrdup(p->name);
501 } else { 501 } else {
502 warnx("Invalid PLIST: missing @name"); 502 warnx("Invalid PLIST: missing @name");
503 buf = NULL; 503 buf = NULL;
504 } 504 }
505 free_plist(&plist); 505 free_plist(&plist);
506 506
507 if (lseek(fd, 0, SEEK_SET) != 0) { 507 if (lseek(fd, 0, SEEK_SET) != 0) {
508 warn("Cannot seek in archive"); 508 warn("Cannot seek in archive");
509 free(buf); 509 free(buf);
510 return NULL; 510 return NULL;
511 } 511 }
512 512
513 return buf; 513 return buf;
514} 514}
515 515
516static const char hash_template[] = 516static const char hash_template[] =
517"pkgsrc signature\n" 517"pkgsrc signature\n"
518"\n" 518"\n"
519"version: 1\n" 519"version: 1\n"
520"pkgname: %s\n" 520"pkgname: %s\n"
521"algorithm: SHA512\n" 521"algorithm: SHA512\n"
522"block size: 65536\n" 522"block size: 65536\n"
523"file size: %lld\n" 523"file size: %lld\n"
524"\n"; 524"\n";
525 525
526static const char hash_trailer[] = "end pkgsrc signature\n"; 526static const char hash_trailer[] = "end pkgsrc signature\n";
527 527
528#ifdef HAVE_SSL 528#ifdef HAVE_SSL
529void 529void
530pkg_sign_x509(const char *name, const char *output, const char *key_file, const char *cert_file) 530pkg_sign_x509(const char *name, const char *output, const char *key_file, const char *cert_file)
531{ 531{
532 struct archive *pkg; 532 struct archive *pkg;
533 struct archive_entry *entry, *hash_entry, *sign_entry; 533 struct archive_entry *entry, *hash_entry, *sign_entry;
534 int fd; 534 int fd;
535 struct stat sb; 535 struct stat sb;
536 char *hash_file, *signature_file, *tmp, *pkgname, hash[SHA512_DIGEST_STRING_LENGTH]; 536 char *hash_file, *signature_file, *tmp, *pkgname, hash[SHA512_DIGEST_STRING_LENGTH];
537 unsigned char block[65536]; 537 unsigned char block[65536];
538 off_t i, size; 538 off_t i, size;
539 size_t block_len, signature_len; 539 size_t block_len, signature_len;
540 540
541 if ((fd = open(name, O_RDONLY)) == -1) 541 if ((fd = open(name, O_RDONLY)) == -1)
542 err(EXIT_FAILURE, "Cannot open binary package %s", name); 542 err(EXIT_FAILURE, "Cannot open binary package %s", name);
543 if (fstat(fd, &sb) == -1) 543 if (fstat(fd, &sb) == -1)
544 err(EXIT_FAILURE, "Cannot stat %s", name); 544 err(EXIT_FAILURE, "Cannot stat %s", name);
545 545
546 entry = archive_entry_new(); 546 entry = archive_entry_new();
547 archive_entry_copy_stat(entry, &sb); 547 archive_entry_copy_stat(entry, &sb);
548 548
549 pkgname = extract_pkgname(fd); 549 pkgname = extract_pkgname(fd);
550 hash_file = xasprintf(hash_template, pkgname, 550 hash_file = xasprintf(hash_template, pkgname,
551 (long long)archive_entry_size(entry)); 551 (long long)archive_entry_size(entry));
552 free(pkgname); 552 free(pkgname);
553 553
554 for (i = 0; i < archive_entry_size(entry); i += block_len) { 554 for (i = 0; i < archive_entry_size(entry); i += block_len) {
555 if (i + sizeof(block) < archive_entry_size(entry)) 555 if (i + sizeof(block) < archive_entry_size(entry))
556 block_len = sizeof(block); 556 block_len = sizeof(block);
557 else 557 else
558 block_len = archive_entry_size(entry) % sizeof(block); 558 block_len = archive_entry_size(entry) % sizeof(block);
559 if (read(fd, block, block_len) != block_len) 559 if (read(fd, block, block_len) != block_len)
560 err(2, "short read"); 560 err(2, "short read");
561 hash_block(block, block_len, hash); 561 hash_block(block, block_len, hash);
562 tmp = xasprintf("%s%s\n", hash_file, hash); 562 tmp = xasprintf("%s%s\n", hash_file, hash);
563 free(hash_file); 563 free(hash_file);
564 hash_file = tmp; 564 hash_file = tmp;
565 } 565 }
566 tmp = xasprintf("%s%s", hash_file, hash_trailer); 566 tmp = xasprintf("%s%s", hash_file, hash_trailer);
567 free(hash_file); 567 free(hash_file);
568 hash_file = tmp; 568 hash_file = tmp;
569 569
570 if (easy_pkcs7_sign(hash_file, strlen(hash_file), &signature_file, 570 if (easy_pkcs7_sign(hash_file, strlen(hash_file), &signature_file,
571 &signature_len, key_file, cert_file)) 571 &signature_len, key_file, cert_file))
572 err(EXIT_FAILURE, "Cannot sign hash file"); 572 err(EXIT_FAILURE, "Cannot sign hash file");
573 573
574 lseek(fd, 0, SEEK_SET); 574 lseek(fd, 0, SEEK_SET);
575 575
576 sign_entry = archive_entry_clone(entry); 576 sign_entry = archive_entry_clone(entry);
577 hash_entry = archive_entry_clone(entry); 577 hash_entry = archive_entry_clone(entry);
578 pkgname = strrchr(name, '/'); 578 pkgname = strrchr(name, '/');
579 archive_entry_set_pathname(entry, pkgname != NULL ? pkgname + 1 : name); 579 archive_entry_set_pathname(entry, pkgname != NULL ? pkgname + 1 : name);
580 archive_entry_set_pathname(hash_entry, HASH_FNAME); 580 archive_entry_set_pathname(hash_entry, HASH_FNAME);
581 archive_entry_set_pathname(sign_entry, SIGNATURE_FNAME); 581 archive_entry_set_pathname(sign_entry, SIGNATURE_FNAME);
582 archive_entry_set_size(hash_entry, strlen(hash_file)); 582 archive_entry_set_size(hash_entry, strlen(hash_file));
583 archive_entry_set_size(sign_entry, signature_len); 583 archive_entry_set_size(sign_entry, signature_len);
584 584
585 pkg = archive_write_new(); 585 pkg = archive_write_new();
586 archive_write_set_compression_none(pkg); 586 archive_write_set_compression_none(pkg);
587 archive_write_set_format_ar_bsd(pkg); 587 archive_write_set_format_ar_bsd(pkg);
588 archive_write_open_filename(pkg, output); 588 archive_write_open_filename(pkg, output);
589 589
590 archive_write_header(pkg, hash_entry); 590 archive_write_header(pkg, hash_entry);
591 archive_write_data(pkg, hash_file, strlen(hash_file)); 591 archive_write_data(pkg, hash_file, strlen(hash_file));
592 archive_write_finish_entry(pkg); 592 archive_write_finish_entry(pkg);
593 archive_entry_free(hash_entry); 593 archive_entry_free(hash_entry);
594 594
595 archive_write_header(pkg, sign_entry); 595 archive_write_header(pkg, sign_entry);
596 archive_write_data(pkg, signature_file, signature_len); 596 archive_write_data(pkg, signature_file, signature_len);
597 archive_write_finish_entry(pkg); 597 archive_write_finish_entry(pkg);
598 archive_entry_free(sign_entry); 598 archive_entry_free(sign_entry);
599 599
600 size = archive_entry_size(entry); 600 size = archive_entry_size(entry);
601 archive_write_header(pkg, entry); 601 archive_write_header(pkg, entry);
602 602
603 for (i = 0; i < size; i += block_len) { 603 for (i = 0; i < size; i += block_len) {
604 if (i + sizeof(block) < size) 604 if (i + sizeof(block) < size)
605 block_len = sizeof(block); 605 block_len = sizeof(block);
606 else 606 else
607 block_len = size % sizeof(block); 607 block_len = size % sizeof(block);
608 if (read(fd, block, block_len) != block_len) 608 if (read(fd, block, block_len) != block_len)
609 err(2, "short read"); 609 err(2, "short read");
610 archive_write_data(pkg, block, block_len); 610 archive_write_data(pkg, block, block_len);
611 } 611 }
612 archive_write_finish_entry(pkg); 612 archive_write_finish_entry(pkg);
613 archive_entry_free(entry); 613 archive_entry_free(entry);
614 614
615 archive_write_finish(pkg); 615 archive_write_finish(pkg);
616 616
 617 close(fd);
 618
617 exit(0); 619 exit(0);
618} 620}
619#endif 621#endif
620 622
621void 623void
622pkg_sign_gpg(const char *name, const char *output) 624pkg_sign_gpg(const char *name, const char *output)
623{ 625{
624 struct archive *pkg; 626 struct archive *pkg;
625 struct archive_entry *entry, *hash_entry, *sign_entry; 627 struct archive_entry *entry, *hash_entry, *sign_entry;
626 int fd; 628 int fd;
627 struct stat sb; 629 struct stat sb;
628 char *hash_file, *signature_file, *tmp, *pkgname, hash[SHA512_DIGEST_STRING_LENGTH]; 630 char *hash_file, *signature_file, *tmp, *pkgname, hash[SHA512_DIGEST_STRING_LENGTH];
629 unsigned char block[65536]; 631 unsigned char block[65536];
630 off_t i, size; 632 off_t i, size;
631 size_t block_len, signature_len; 633 size_t block_len, signature_len;
632 634
633 if ((fd = open(name, O_RDONLY)) == -1) 635 if ((fd = open(name, O_RDONLY)) == -1)
634 err(EXIT_FAILURE, "Cannot open binary package %s", name); 636 err(EXIT_FAILURE, "Cannot open binary package %s", name);
635 if (fstat(fd, &sb) == -1) 637 if (fstat(fd, &sb) == -1)
636 err(EXIT_FAILURE, "Cannot stat %s", name); 638 err(EXIT_FAILURE, "Cannot stat %s", name);
637 639
638 entry = archive_entry_new(); 640 entry = archive_entry_new();
639 archive_entry_copy_stat(entry, &sb); 641 archive_entry_copy_stat(entry, &sb);
640 642
641 pkgname = extract_pkgname(fd); 643 pkgname = extract_pkgname(fd);
642 hash_file = xasprintf(hash_template, pkgname, 644 hash_file = xasprintf(hash_template, pkgname,
643 (long long)archive_entry_size(entry)); 645 (long long)archive_entry_size(entry));
644 free(pkgname); 646 free(pkgname);
645 647
646 for (i = 0; i < archive_entry_size(entry); i += block_len) { 648 for (i = 0; i < archive_entry_size(entry); i += block_len) {
647 if (i + sizeof(block) < archive_entry_size(entry)) 649 if (i + sizeof(block) < archive_entry_size(entry))
648 block_len = sizeof(block); 650 block_len = sizeof(block);
649 else 651 else
650 block_len = archive_entry_size(entry) % sizeof(block); 652 block_len = archive_entry_size(entry) % sizeof(block);
651 if (read(fd, block, block_len) != block_len) 653 if (read(fd, block, block_len) != block_len)
652 err(2, "short read"); 654 err(2, "short read");
653 hash_block(block, block_len, hash); 655 hash_block(block, block_len, hash);
654 tmp = xasprintf("%s%s\n", hash_file, hash); 656 tmp = xasprintf("%s%s\n", hash_file, hash);
655 free(hash_file); 657 free(hash_file);
656 hash_file = tmp; 658 hash_file = tmp;
657 } 659 }
658 tmp = xasprintf("%s%s", hash_file, hash_trailer); 660 tmp = xasprintf("%s%s", hash_file, hash_trailer);
659 free(hash_file); 661 free(hash_file);
660 hash_file = tmp; 662 hash_file = tmp;
661 663
662 if (detached_gpg_sign(hash_file, strlen(hash_file), &signature_file, 664 if (detached_gpg_sign(hash_file, strlen(hash_file), &signature_file,
663 &signature_len, gpg_keyring_sign, gpg_sign_as)) 665 &signature_len, gpg_keyring_sign, gpg_sign_as))
664 err(EXIT_FAILURE, "Cannot sign hash file"); 666 err(EXIT_FAILURE, "Cannot sign hash file");
665 667
666 lseek(fd, 0, SEEK_SET); 668 lseek(fd, 0, SEEK_SET);
667 669
668 sign_entry = archive_entry_clone(entry); 670 sign_entry = archive_entry_clone(entry);
669 hash_entry = archive_entry_clone(entry); 671 hash_entry = archive_entry_clone(entry);
670 pkgname = strrchr(name, '/'); 672 pkgname = strrchr(name, '/');
671 archive_entry_set_pathname(entry, pkgname != NULL ? pkgname + 1 : name); 673 archive_entry_set_pathname(entry, pkgname != NULL ? pkgname + 1 : name);
672 archive_entry_set_pathname(hash_entry, HASH_FNAME); 674 archive_entry_set_pathname(hash_entry, HASH_FNAME);
673 archive_entry_set_pathname(sign_entry, GPG_SIGNATURE_FNAME); 675 archive_entry_set_pathname(sign_entry, GPG_SIGNATURE_FNAME);
674 archive_entry_set_size(hash_entry, strlen(hash_file)); 676 archive_entry_set_size(hash_entry, strlen(hash_file));
675 archive_entry_set_size(sign_entry, signature_len); 677 archive_entry_set_size(sign_entry, signature_len);
676 678
677 pkg = archive_write_new(); 679 pkg = archive_write_new();
678 archive_write_set_compression_none(pkg); 680 archive_write_set_compression_none(pkg);
679 archive_write_set_format_ar_bsd(pkg); 681 archive_write_set_format_ar_bsd(pkg);
680 archive_write_open_filename(pkg, output); 682 archive_write_open_filename(pkg, output);
681 683
682 archive_write_header(pkg, hash_entry); 684 archive_write_header(pkg, hash_entry);
683 archive_write_data(pkg, hash_file, strlen(hash_file)); 685 archive_write_data(pkg, hash_file, strlen(hash_file));
684 archive_write_finish_entry(pkg); 686 archive_write_finish_entry(pkg);
685 archive_entry_free(hash_entry); 687 archive_entry_free(hash_entry);
686 688
687 archive_write_header(pkg, sign_entry); 689 archive_write_header(pkg, sign_entry);
688 archive_write_data(pkg, signature_file, signature_len); 690 archive_write_data(pkg, signature_file, signature_len);
689 archive_write_finish_entry(pkg); 691 archive_write_finish_entry(pkg);
690 archive_entry_free(sign_entry); 692 archive_entry_free(sign_entry);
691 693
692 size = archive_entry_size(entry); 694 size = archive_entry_size(entry);
693 archive_write_header(pkg, entry); 695 archive_write_header(pkg, entry);
694 696
695 for (i = 0; i < size; i += block_len) { 697 for (i = 0; i < size; i += block_len) {
696 if (i + sizeof(block) < size) 698 if (i + sizeof(block) < size)
697 block_len = sizeof(block); 699 block_len = sizeof(block);
698 else 700 else
699 block_len = size % sizeof(block); 701 block_len = size % sizeof(block);
700 if (read(fd, block, block_len) != block_len) 702 if (read(fd, block, block_len) != block_len)
701 err(2, "short read"); 703 err(2, "short read");
702 archive_write_data(pkg, block, block_len); 704 archive_write_data(pkg, block, block_len);
703 } 705 }
704 archive_write_finish_entry(pkg); 706 archive_write_finish_entry(pkg);
705 archive_entry_free(entry); 707 archive_entry_free(entry);
706 708
707 archive_write_finish(pkg); 709 archive_write_finish(pkg);
708 710
 711 close(fd);
 712
709 exit(0); 713 exit(0);
710} 714}

cvs diff -r1.115 -r1.116 pkgsrc/pkgtools/pkg_install/files/lib/version.h (switch to unified diff)

--- pkgsrc/pkgtools/pkg_install/files/lib/version.h 2009/02/28 16:03:56 1.115
+++ pkgsrc/pkgtools/pkg_install/files/lib/version.h 2009/03/02 14:59:14 1.116
@@ -1,32 +1,32 @@ @@ -1,32 +1,32 @@
1/* $NetBSD: version.h,v 1.115 2009/02/28 16:03:56 joerg Exp $ */ 1/* $NetBSD: version.h,v 1.116 2009/03/02 14:59:14 joerg Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001 Thomas Klausner. All rights reserved. 4 * Copyright (c) 2001 Thomas Klausner. All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */ 25 */
26 26
27#ifndef _INST_LIB_VERSION_H_ 27#ifndef _INST_LIB_VERSION_H_
28#define _INST_LIB_VERSION_H_ 28#define _INST_LIB_VERSION_H_
29 29
30#define PKGTOOLS_VERSION "20090228" 30#define PKGTOOLS_VERSION "20090301"
31 31
32#endif /* _INST_LIB_VERSION_H_ */ 32#endif /* _INST_LIB_VERSION_H_ */

cvs diff -r1.4 -r1.5 pkgsrc/pkgtools/pkg_install/files/lib/vulnerabilities-file.c (switch to unified diff)

--- pkgsrc/pkgtools/pkg_install/files/lib/vulnerabilities-file.c 2009/02/02 12:35:01 1.4
+++ pkgsrc/pkgtools/pkg_install/files/lib/vulnerabilities-file.c 2009/03/02 14:59:14 1.5
@@ -1,588 +1,590 @@ @@ -1,588 +1,590 @@
1/* $NetBSD: vulnerabilities-file.c,v 1.4 2009/02/02 12:35:01 joerg Exp $ */ 1/* $NetBSD: vulnerabilities-file.c,v 1.5 2009/03/02 14:59:14 joerg Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>. 4 * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 10 *
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in 14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the 15 * the documentation and/or other materials provided with the
16 * distribution. 16 * distribution.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32#if HAVE_CONFIG_H 32#if HAVE_CONFIG_H
33#include "config.h" 33#include "config.h"
34#endif 34#endif
35 35
36#include <nbcompat.h> 36#include <nbcompat.h>
37 37
38#if HAVE_SYS_CDEFS_H 38#if HAVE_SYS_CDEFS_H
39#include <sys/cdefs.h> 39#include <sys/cdefs.h>
40#endif 40#endif
41__RCSID("$NetBSD: vulnerabilities-file.c,v 1.4 2009/02/02 12:35:01 joerg Exp $"); 41__RCSID("$NetBSD: vulnerabilities-file.c,v 1.5 2009/03/02 14:59:14 joerg Exp $");
42 42
43#if HAVE_SYS_STAT_H 43#if HAVE_SYS_STAT_H
44#include <sys/stat.h> 44#include <sys/stat.h>
45#endif 45#endif
46#if HAVE_SYS_WAIT_H 46#if HAVE_SYS_WAIT_H
47#include <sys/wait.h> 47#include <sys/wait.h>
48#endif 48#endif
49#include <ctype.h> 49#include <ctype.h>
50#if HAVE_ERR_H 50#if HAVE_ERR_H
51#include <err.h> 51#include <err.h>
52#endif 52#endif
53#include <errno.h> 53#include <errno.h>
54#include <fcntl.h> 54#include <fcntl.h>
55#include <limits.h> 55#include <limits.h>
56#include <stdlib.h> 56#include <stdlib.h>
57#include <string.h> 57#include <string.h>
58#ifndef NETBSD 58#ifndef NETBSD
59#include <nbcompat/sha1.h> 59#include <nbcompat/sha1.h>
60#include <nbcompat/sha2.h> 60#include <nbcompat/sha2.h>
61#else 61#else
62#include <sha1.h> 62#include <sha1.h>
63#include <sha2.h> 63#include <sha2.h>
64#endif 64#endif
65#include <unistd.h> 65#include <unistd.h>
66 66
67#include "lib.h" 67#include "lib.h"
68 68
69static const char pgp_msg_start[] = "-----BEGIN PGP SIGNED MESSAGE-----\n"; 69static const char pgp_msg_start[] = "-----BEGIN PGP SIGNED MESSAGE-----\n";
70static const char pgp_msg_end[] = "-----BEGIN PGP SIGNATURE-----\n"; 70static const char pgp_msg_end[] = "-----BEGIN PGP SIGNATURE-----\n";
71static const char pkcs7_begin[] = "-----BEGIN PKCS7-----\n"; 71static const char pkcs7_begin[] = "-----BEGIN PKCS7-----\n";
72static const char pkcs7_end[] = "-----END PKCS7-----\n"; 72static const char pkcs7_end[] = "-----END PKCS7-----\n";
73 73
74static void 74static void
75verify_signature_pkcs7(const char *input) 75verify_signature_pkcs7(const char *input)
76{ 76{
77#ifdef HAVE_SSL 77#ifdef HAVE_SSL
78 const char *begin_pkgvul, *end_pkgvul, *begin_sig, *end_sig; 78 const char *begin_pkgvul, *end_pkgvul, *begin_sig, *end_sig;
79 79
80 if (strncmp(input, pgp_msg_start, strlen(pgp_msg_start)) == 0) { 80 if (strncmp(input, pgp_msg_start, strlen(pgp_msg_start)) == 0) {
81 begin_pkgvul = input + strlen(pgp_msg_start); 81 begin_pkgvul = input + strlen(pgp_msg_start);
82 if ((end_pkgvul = strstr(begin_pkgvul, pgp_msg_end)) == NULL) 82 if ((end_pkgvul = strstr(begin_pkgvul, pgp_msg_end)) == NULL)
83 errx(EXIT_FAILURE, "Invalid PGP signature"); 83 errx(EXIT_FAILURE, "Invalid PGP signature");
84 if ((begin_sig = strstr(end_pkgvul, pkcs7_begin)) == NULL) 84 if ((begin_sig = strstr(end_pkgvul, pkcs7_begin)) == NULL)
85 errx(EXIT_FAILURE, "No PKCS7 signature"); 85 errx(EXIT_FAILURE, "No PKCS7 signature");
86 } else { 86 } else {
87 begin_pkgvul = input; 87 begin_pkgvul = input;
88 if ((begin_sig = strstr(begin_pkgvul, pkcs7_begin)) == NULL) 88 if ((begin_sig = strstr(begin_pkgvul, pkcs7_begin)) == NULL)
89 errx(EXIT_FAILURE, "No PKCS7 signature"); 89 errx(EXIT_FAILURE, "No PKCS7 signature");
90 end_pkgvul = begin_sig;  90 end_pkgvul = begin_sig;
91 } 91 }
92 if ((end_sig = strstr(begin_sig, pkcs7_end)) == NULL) 92 if ((end_sig = strstr(begin_sig, pkcs7_end)) == NULL)
93 errx(EXIT_FAILURE, "Invalid PKCS7 signature"); 93 errx(EXIT_FAILURE, "Invalid PKCS7 signature");
94 end_sig += strlen(pkcs7_end); 94 end_sig += strlen(pkcs7_end);
95 95
96 if (easy_pkcs7_verify(begin_pkgvul, end_pkgvul - begin_pkgvul, 96 if (easy_pkcs7_verify(begin_pkgvul, end_pkgvul - begin_pkgvul,
97 begin_sig, end_sig - begin_sig, certs_pkg_vulnerabilities, 0)) 97 begin_sig, end_sig - begin_sig, certs_pkg_vulnerabilities, 0))
98 errx(EXIT_FAILURE, "Unable to verify PKCS7 signature"); 98 errx(EXIT_FAILURE, "Unable to verify PKCS7 signature");
99#else 99#else
100 errx(EXIT_FAILURE, "OpenSSL support is not compiled in"); 100 errx(EXIT_FAILURE, "OpenSSL support is not compiled in");
101#endif 101#endif
102} 102}
103 103
104static void 104static void
105verify_signature(const char *input, size_t input_len) 105verify_signature(const char *input, size_t input_len)
106{ 106{
107 if (gpg_cmd == NULL && certs_pkg_vulnerabilities == NULL) 107 if (gpg_cmd == NULL && certs_pkg_vulnerabilities == NULL)
108 errx(EXIT_FAILURE, 108 errx(EXIT_FAILURE,
109 "At least GPG or CERTIFICATE_ANCHOR_PKGVULN " 109 "At least GPG or CERTIFICATE_ANCHOR_PKGVULN "
110 "must be configured"); 110 "must be configured");
111 if (gpg_cmd != NULL) 111 if (gpg_cmd != NULL)
112 inline_gpg_verify(input, input_len, gpg_keyring_pkgvuln); 112 inline_gpg_verify(input, input_len, gpg_keyring_pkgvuln);
113 if (certs_pkg_vulnerabilities != NULL) 113 if (certs_pkg_vulnerabilities != NULL)
114 verify_signature_pkcs7(input); 114 verify_signature_pkcs7(input);
115} 115}
116 116
117static void * 117static void *
118sha512_hash_init(void) 118sha512_hash_init(void)
119{ 119{
120 static SHA512_CTX hash_ctx; 120 static SHA512_CTX hash_ctx;
121 121
122 SHA512_Init(&hash_ctx); 122 SHA512_Init(&hash_ctx);
123 return &hash_ctx; 123 return &hash_ctx;
124} 124}
125 125
126static void 126static void
127sha512_hash_update(void *ctx, const void *data, size_t len) 127sha512_hash_update(void *ctx, const void *data, size_t len)
128{ 128{
129 SHA512_CTX *hash_ctx = ctx; 129 SHA512_CTX *hash_ctx = ctx;
130 130
131 SHA512_Update(hash_ctx, data, len); 131 SHA512_Update(hash_ctx, data, len);
132} 132}
133 133
134static const char * 134static const char *
135sha512_hash_finish(void *ctx) 135sha512_hash_finish(void *ctx)
136{ 136{
137 static char hash[SHA512_DIGEST_STRING_LENGTH]; 137 static char hash[SHA512_DIGEST_STRING_LENGTH];
138 unsigned char digest[SHA512_DIGEST_LENGTH]; 138 unsigned char digest[SHA512_DIGEST_LENGTH];
139 SHA512_CTX *hash_ctx = ctx; 139 SHA512_CTX *hash_ctx = ctx;
140 int i; 140 int i;
141 141
142 SHA512_Final(digest, hash_ctx); 142 SHA512_Final(digest, hash_ctx);
143 for (i = 0; i < SHA512_DIGEST_LENGTH; ++i) { 143 for (i = 0; i < SHA512_DIGEST_LENGTH; ++i) {
144 unsigned char c; 144 unsigned char c;
145 145
146 c = digest[i] / 16; 146 c = digest[i] / 16;
147 if (c < 10) 147 if (c < 10)
148 hash[2 * i] = '0' + c; 148 hash[2 * i] = '0' + c;
149 else 149 else
150 hash[2 * i] = 'a' - 10 + c; 150 hash[2 * i] = 'a' - 10 + c;
151 151
152 c = digest[i] % 16; 152 c = digest[i] % 16;
153 if (c < 10) 153 if (c < 10)
154 hash[2 * i + 1] = '0' + c; 154 hash[2 * i + 1] = '0' + c;
155 else 155 else
156 hash[2 * i + 1] = 'a' - 10 + c; 156 hash[2 * i + 1] = 'a' - 10 + c;
157 } 157 }
158 hash[2 * i] = '\0'; 158 hash[2 * i] = '\0';
159 159
160 return hash; 160 return hash;
161} 161}
162 162
163static void * 163static void *
164sha1_hash_init(void) 164sha1_hash_init(void)
165{ 165{
166 static SHA1_CTX hash_ctx; 166 static SHA1_CTX hash_ctx;
167 167
168 SHA1Init(&hash_ctx); 168 SHA1Init(&hash_ctx);
169 return &hash_ctx; 169 return &hash_ctx;
170} 170}
171 171
172static void 172static void
173sha1_hash_update(void *ctx, const void *data, size_t len) 173sha1_hash_update(void *ctx, const void *data, size_t len)
174{ 174{
175 SHA1_CTX *hash_ctx = ctx; 175 SHA1_CTX *hash_ctx = ctx;
176 176
177 SHA1Update(hash_ctx, data, len); 177 SHA1Update(hash_ctx, data, len);
178} 178}
179 179
180static const char * 180static const char *
181sha1_hash_finish(void *ctx) 181sha1_hash_finish(void *ctx)
182{ 182{
183 static char hash[SHA1_DIGEST_STRING_LENGTH]; 183 static char hash[SHA1_DIGEST_STRING_LENGTH];
184 SHA1_CTX *hash_ctx = ctx; 184 SHA1_CTX *hash_ctx = ctx;
185 185
186 SHA1End(hash_ctx, hash); 186 SHA1End(hash_ctx, hash);
187 187
188 return hash; 188 return hash;
189} 189}
190 190
191static const struct hash_algorithm { 191static const struct hash_algorithm {
192 const char *name; 192 const char *name;
193 size_t name_len; 193 size_t name_len;
194 void * (*init)(void); 194 void * (*init)(void);
195 void (*update)(void *, const void *, size_t); 195 void (*update)(void *, const void *, size_t);
196 const char * (* finish)(void *); 196 const char * (* finish)(void *);
197} hash_algorithms[] = { 197} hash_algorithms[] = {
198 { "SHA512", 6, sha512_hash_init, sha512_hash_update, 198 { "SHA512", 6, sha512_hash_init, sha512_hash_update,
199 sha512_hash_finish }, 199 sha512_hash_finish },
200 { "SHA1", 4, sha1_hash_init, sha1_hash_update, 200 { "SHA1", 4, sha1_hash_init, sha1_hash_update,
201 sha1_hash_finish }, 201 sha1_hash_finish },
202 { NULL, 0, NULL, NULL, NULL } 202 { NULL, 0, NULL, NULL, NULL }
203}; 203};
204 204
205static void 205static void
206verify_hash(const char *input, const char *hash_line) 206verify_hash(const char *input, const char *hash_line)
207{ 207{
208 const struct hash_algorithm *hash; 208 const struct hash_algorithm *hash;
209 void *ctx; 209 void *ctx;
210 const char *last_start, *next, *hash_value; 210 const char *last_start, *next, *hash_value;
211 int in_pgp_msg; 211 int in_pgp_msg;
212 212
213 for (hash = hash_algorithms; hash->name != NULL; ++hash) { 213 for (hash = hash_algorithms; hash->name != NULL; ++hash) {
214 if (strncmp(hash_line, hash->name, hash->name_len)) 214 if (strncmp(hash_line, hash->name, hash->name_len))
215 continue; 215 continue;
216 if (isspace((unsigned char)hash_line[hash->name_len])) 216 if (isspace((unsigned char)hash_line[hash->name_len]))
217 break; 217 break;
218 } 218 }
219 if (hash->name == NULL) { 219 if (hash->name == NULL) {
220 const char *end_name; 220 const char *end_name;
221 for (end_name = hash_line; *end_name != '\0'; ++end_name) { 221 for (end_name = hash_line; *end_name != '\0'; ++end_name) {
222 if (!isalnum((unsigned char)*end_name)) 222 if (!isalnum((unsigned char)*end_name))
223 break; 223 break;
224 } 224 }
225 warnx("Unsupported hash algorithm: %.*s", 225 warnx("Unsupported hash algorithm: %.*s",
226 (int)(end_name - hash_line), hash_line);  226 (int)(end_name - hash_line), hash_line);
227 return; 227 return;
228 } 228 }
229 229
230 hash_line += hash->name_len; 230 hash_line += hash->name_len;
231 if (!isspace((unsigned char)*hash_line)) 231 if (!isspace((unsigned char)*hash_line))
232 errx(EXIT_FAILURE, "Invalid #CHECKSUM"); 232 errx(EXIT_FAILURE, "Invalid #CHECKSUM");
233 while (isspace((unsigned char)*hash_line) && *hash_line != '\n') 233 while (isspace((unsigned char)*hash_line) && *hash_line != '\n')
234 ++hash_line; 234 ++hash_line;
235 235
236 if (*hash_line == '\n') 236 if (*hash_line == '\n')
237 errx(EXIT_FAILURE, "Invalid #CHECKSUM"); 237 errx(EXIT_FAILURE, "Invalid #CHECKSUM");
238 238
239 ctx = (*hash->init)(); 239 ctx = (*hash->init)();
240 if (strncmp(input, pgp_msg_start, strlen(pgp_msg_start)) == 0) { 240 if (strncmp(input, pgp_msg_start, strlen(pgp_msg_start)) == 0) {
241 input += strlen(pgp_msg_start); 241 input += strlen(pgp_msg_start);
242 in_pgp_msg = 1; 242 in_pgp_msg = 1;
243 } else { 243 } else {
244 in_pgp_msg = 0; 244 in_pgp_msg = 0;
245 } 245 }
246 for (last_start = input; *input != '\0'; input = next) { 246 for (last_start = input; *input != '\0'; input = next) {
247 if ((next = strchr(input, '\n')) == NULL) 247 if ((next = strchr(input, '\n')) == NULL)
248 errx(EXIT_FAILURE, "Missing newline in pkg-vulnerabilities"); 248 errx(EXIT_FAILURE, "Missing newline in pkg-vulnerabilities");
249 ++next; 249 ++next;
250 if (in_pgp_msg && strncmp(input, pgp_msg_end, strlen(pgp_msg_end)) == 0) 250 if (in_pgp_msg && strncmp(input, pgp_msg_end, strlen(pgp_msg_end)) == 0)
251 break; 251 break;
252 if (!in_pgp_msg && strncmp(input, pkcs7_begin, strlen(pkcs7_begin)) == 0) 252 if (!in_pgp_msg && strncmp(input, pkcs7_begin, strlen(pkcs7_begin)) == 0)
253 break; 253 break;
254 if (*input == '\n' || 254 if (*input == '\n' ||
255 strncmp(input, "Hash:", 5) == 0 || 255 strncmp(input, "Hash:", 5) == 0 ||
256 strncmp(input, "# $NetBSD", 9) == 0 || 256 strncmp(input, "# $NetBSD", 9) == 0 ||
257 strncmp(input, "#CHECKSUM", 9) == 0) { 257 strncmp(input, "#CHECKSUM", 9) == 0) {
258 (*hash->update)(ctx, last_start, input - last_start); 258 (*hash->update)(ctx, last_start, input - last_start);
259 last_start = next; 259 last_start = next;
260 } 260 }
261 } 261 }
262 (*hash->update)(ctx, last_start, input - last_start); 262 (*hash->update)(ctx, last_start, input - last_start);
263 hash_value = (*hash->finish)(ctx); 263 hash_value = (*hash->finish)(ctx);
264 if (strncmp(hash_line, hash_value, strlen(hash_value))) 264 if (strncmp(hash_line, hash_value, strlen(hash_value)))
265 errx(EXIT_FAILURE, "%s hash doesn't match", hash->name); 265 errx(EXIT_FAILURE, "%s hash doesn't match", hash->name);
266 hash_line += strlen(hash_value); 266 hash_line += strlen(hash_value);
267 267
268 while (isspace((unsigned char)*hash_line) && *hash_line != '\n') 268 while (isspace((unsigned char)*hash_line) && *hash_line != '\n')
269 ++hash_line; 269 ++hash_line;
270  270
271 if (!isspace((unsigned char)*hash_line)) 271 if (!isspace((unsigned char)*hash_line))
272 errx(EXIT_FAILURE, "Invalid #CHECKSUM"); 272 errx(EXIT_FAILURE, "Invalid #CHECKSUM");
273} 273}
274 274
275static void 275static void
276add_vulnerability(struct pkg_vulnerabilities *pv, size_t *allocated, const char *line) 276add_vulnerability(struct pkg_vulnerabilities *pv, size_t *allocated, const char *line)
277{ 277{
278 size_t len_pattern, len_class, len_url; 278 size_t len_pattern, len_class, len_url;
279 const char *start_pattern, *start_class, *start_url; 279 const char *start_pattern, *start_class, *start_url;
280 280
281 start_pattern = line; 281 start_pattern = line;
282 282
283 start_class = line; 283 start_class = line;
284 while (*start_class != '\0' && !isspace((unsigned char)*start_class)) 284 while (*start_class != '\0' && !isspace((unsigned char)*start_class))
285 ++start_class; 285 ++start_class;
286 len_pattern = start_class - line; 286 len_pattern = start_class - line;
287 287
288 while (*start_class != '\n' && isspace((unsigned char)*start_class)) 288 while (*start_class != '\n' && isspace((unsigned char)*start_class))
289 ++start_class; 289 ++start_class;
290 290
291 if (*start_class == '0' || *start_class == '\n') 291 if (*start_class == '0' || *start_class == '\n')
292 errx(EXIT_FAILURE, "Input error: missing classification"); 292 errx(EXIT_FAILURE, "Input error: missing classification");
293 293
294 start_url = start_class; 294 start_url = start_class;
295 while (*start_url != '\0' && !isspace((unsigned char)*start_url)) 295 while (*start_url != '\0' && !isspace((unsigned char)*start_url))
296 ++start_url; 296 ++start_url;
297 len_class = start_url - start_class; 297 len_class = start_url - start_class;
298 298
299 while (*start_url != '\n' && isspace((unsigned char)*start_url)) 299 while (*start_url != '\n' && isspace((unsigned char)*start_url))
300 ++start_url; 300 ++start_url;
301 301
302 if (*start_url == '0' || *start_url == '\n') 302 if (*start_url == '0' || *start_url == '\n')
303 errx(EXIT_FAILURE, "Input error: missing URL"); 303 errx(EXIT_FAILURE, "Input error: missing URL");
304 304
305 line = start_url; 305 line = start_url;
306 while (*line != '\0' && !isspace((unsigned char)*line)) 306 while (*line != '\0' && !isspace((unsigned char)*line))
307 ++line; 307 ++line;
308 len_url = line - start_url; 308 len_url = line - start_url;
309 309
310 if (pv->entries == *allocated) { 310 if (pv->entries == *allocated) {
311 if (*allocated == 0) 311 if (*allocated == 0)
312 *allocated = 16; 312 *allocated = 16;
313 else if (*allocated <= SSIZE_MAX / 2) 313 else if (*allocated <= SSIZE_MAX / 2)
314 *allocated *= 2; 314 *allocated *= 2;
315 else 315 else
316 errx(EXIT_FAILURE, "Too many vulnerabilities"); 316 errx(EXIT_FAILURE, "Too many vulnerabilities");
317 pv->vulnerability = xrealloc(pv->vulnerability, 317 pv->vulnerability = xrealloc(pv->vulnerability,
318 sizeof(char *) * *allocated); 318 sizeof(char *) * *allocated);
319 pv->classification = xrealloc(pv->classification, 319 pv->classification = xrealloc(pv->classification,
320 sizeof(char *) * *allocated); 320 sizeof(char *) * *allocated);
321 pv->advisory = xrealloc(pv->advisory, 321 pv->advisory = xrealloc(pv->advisory,
322 sizeof(char *) * *allocated); 322 sizeof(char *) * *allocated);
323 } 323 }
324 324
325 pv->vulnerability[pv->entries] = xmalloc(len_pattern + 1); 325 pv->vulnerability[pv->entries] = xmalloc(len_pattern + 1);
326 memcpy(pv->vulnerability[pv->entries], start_pattern, len_pattern); 326 memcpy(pv->vulnerability[pv->entries], start_pattern, len_pattern);
327 pv->vulnerability[pv->entries][len_pattern] = '\0'; 327 pv->vulnerability[pv->entries][len_pattern] = '\0';
328 pv->classification[pv->entries] = xmalloc(len_class + 1); 328 pv->classification[pv->entries] = xmalloc(len_class + 1);
329 memcpy(pv->classification[pv->entries], start_class, len_class); 329 memcpy(pv->classification[pv->entries], start_class, len_class);
330 pv->classification[pv->entries][len_class] = '\0'; 330 pv->classification[pv->entries][len_class] = '\0';
331 pv->advisory[pv->entries] = xmalloc(len_url + 1); 331 pv->advisory[pv->entries] = xmalloc(len_url + 1);
332 memcpy(pv->advisory[pv->entries], start_url, len_url); 332 memcpy(pv->advisory[pv->entries], start_url, len_url);
333 pv->advisory[pv->entries][len_url] = '\0'; 333 pv->advisory[pv->entries][len_url] = '\0';
334 334
335 ++pv->entries; 335 ++pv->entries;
336} 336}
337 337
338struct pkg_vulnerabilities * 338struct pkg_vulnerabilities *
339read_pkg_vulnerabilities(const char *path, int ignore_missing, int check_sum) 339read_pkg_vulnerabilities(const char *path, int ignore_missing, int check_sum)
340{ 340{
341 struct pkg_vulnerabilities *pv; 341 struct pkg_vulnerabilities *pv;
342 struct stat st; 342 struct stat st;
343 int fd; 343 int fd;
344 char *input, *decompressed_input; 344 char *input, *decompressed_input;
345 size_t input_len, decompressed_len; 345 size_t input_len, decompressed_len;
346 ssize_t bytes_read; 346 ssize_t bytes_read;
347 347
348 if ((fd = open(path, O_RDONLY)) == -1) { 348 if ((fd = open(path, O_RDONLY)) == -1) {
349 if (errno == ENOENT && ignore_missing) 349 if (errno == ENOENT && ignore_missing)
350 return NULL; 350 return NULL;
351 err(EXIT_FAILURE, "Cannot open %s", path); 351 err(EXIT_FAILURE, "Cannot open %s", path);
352 } 352 }
353 353
354 if (fstat(fd, &st) == -1) 354 if (fstat(fd, &st) == -1)
355 err(EXIT_FAILURE, "Cannot stat %s", path); 355 err(EXIT_FAILURE, "Cannot stat %s", path);
356 356
357 if ((st.st_mode & S_IFMT) != S_IFREG) 357 if ((st.st_mode & S_IFMT) != S_IFREG)
358 errx(EXIT_FAILURE, "Input is not regular file"); 358 errx(EXIT_FAILURE, "Input is not regular file");
359 if (st.st_size > SSIZE_MAX - 1) 359 if (st.st_size > SSIZE_MAX - 1)
360 errx(EXIT_FAILURE, "Input too large"); 360 errx(EXIT_FAILURE, "Input too large");
361 361
362 input_len = (size_t)st.st_size; 362 input_len = (size_t)st.st_size;
363 if (input_len < 4) 363 if (input_len < 4)
364 err(EXIT_FAILURE, "Input too short for a pkg_vulnerability file"); 364 err(EXIT_FAILURE, "Input too short for a pkg_vulnerability file");
365 input = xmalloc(input_len + 1); 365 input = xmalloc(input_len + 1);
366 if ((bytes_read = read(fd, input, input_len)) == -1) 366 if ((bytes_read = read(fd, input, input_len)) == -1)
367 err(1, "Failed to read input"); 367 err(1, "Failed to read input");
368 if (bytes_read != st.st_size) 368 if (bytes_read != st.st_size)
369 errx(1, "Unexpected short read"); 369 errx(1, "Unexpected short read");
370 370
 371 close(fd);
 372
371 if (decompress_buffer(input, input_len, &decompressed_input, 373 if (decompress_buffer(input, input_len, &decompressed_input,
372 &decompressed_len)) { 374 &decompressed_len)) {
373 free(input); 375 free(input);
374 input = decompressed_input; 376 input = decompressed_input;
375 input_len = decompressed_len; 377 input_len = decompressed_len;
376 } 378 }
377 pv = parse_pkg_vulnerabilities(input, input_len, check_sum); 379 pv = parse_pkg_vulnerabilities(input, input_len, check_sum);
378 free(input); 380 free(input);
379 381
380 return pv; 382 return pv;
381} 383}
382 384
383struct pkg_vulnerabilities * 385struct pkg_vulnerabilities *
384parse_pkg_vulnerabilities(const char *input, size_t input_len, int check_sum) 386parse_pkg_vulnerabilities(const char *input, size_t input_len, int check_sum)
385{ 387{
386 struct pkg_vulnerabilities *pv; 388 struct pkg_vulnerabilities *pv;
387 long version; 389 long version;
388 char *end; 390 char *end;
389 const char *iter, *next; 391 const char *iter, *next;
390 size_t allocated_vulns; 392 size_t allocated_vulns;
391 int in_pgp_msg; 393 int in_pgp_msg;
392 394
393 pv = xmalloc(sizeof(*pv)); 395 pv = xmalloc(sizeof(*pv));
394 396
395 allocated_vulns = pv->entries = 0; 397 allocated_vulns = pv->entries = 0;
396 pv->vulnerability = NULL; 398 pv->vulnerability = NULL;
397 pv->classification = NULL; 399 pv->classification = NULL;
398 pv->advisory = NULL; 400 pv->advisory = NULL;
399 401
400 if (strlen(input) != input_len) 402 if (strlen(input) != input_len)
401 errx(1, "Invalid input (NUL character found)"); 403 errx(1, "Invalid input (NUL character found)");
402 404
403 if (check_sum) 405 if (check_sum)
404 verify_signature(input, input_len); 406 verify_signature(input, input_len);
405 407
406 if (strncmp(input, pgp_msg_start, strlen(pgp_msg_start)) == 0) { 408 if (strncmp(input, pgp_msg_start, strlen(pgp_msg_start)) == 0) {
407 iter = input + strlen(pgp_msg_start); 409 iter = input + strlen(pgp_msg_start);
408 in_pgp_msg = 1; 410 in_pgp_msg = 1;
409 } else { 411 } else {
410 iter = input; 412 iter = input;
411 in_pgp_msg = 0; 413 in_pgp_msg = 0;
412 } 414 }
413 415
414 for (; *iter; iter = next) { 416 for (; *iter; iter = next) {
415 if ((next = strchr(iter, '\n')) == NULL) 417 if ((next = strchr(iter, '\n')) == NULL)
416 errx(EXIT_FAILURE, "Missing newline in pkg-vulnerabilities"); 418 errx(EXIT_FAILURE, "Missing newline in pkg-vulnerabilities");
417 ++next; 419 ++next;
418 if (*iter == '\0' || *iter == '\n') 420 if (*iter == '\0' || *iter == '\n')
419 continue; 421 continue;
420 if (strncmp(iter, "Hash:", 5) == 0) 422 if (strncmp(iter, "Hash:", 5) == 0)
421 continue; 423 continue;
422 if (strncmp(iter, "# $NetBSD", 9) == 0) 424 if (strncmp(iter, "# $NetBSD", 9) == 0)
423 continue; 425 continue;
424 if (*iter == '#' && isspace((unsigned char)iter[1])) { 426 if (*iter == '#' && isspace((unsigned char)iter[1])) {
425 for (++iter; iter != next; ++iter) { 427 for (++iter; iter != next; ++iter) {
426 if (!isspace((unsigned char)*iter)) 428 if (!isspace((unsigned char)*iter))
427 errx(EXIT_FAILURE, "Invalid header"); 429 errx(EXIT_FAILURE, "Invalid header");
428 } 430 }
429 continue; 431 continue;
430 } 432 }
431 433
432 if (strncmp(iter, "#FORMAT", 7) != 0) 434 if (strncmp(iter, "#FORMAT", 7) != 0)
433 errx(EXIT_FAILURE, "Input header is malformed"); 435 errx(EXIT_FAILURE, "Input header is malformed");
434 436
435 iter += 7; 437 iter += 7;
436 if (!isspace((unsigned char)*iter)) 438 if (!isspace((unsigned char)*iter))
437 errx(EXIT_FAILURE, "Invalid #FORMAT"); 439 errx(EXIT_FAILURE, "Invalid #FORMAT");
438 ++iter; 440 ++iter;
439 version = strtol(iter, &end, 10); 441 version = strtol(iter, &end, 10);
440 if (iter == end || version != 1 || *end != '.') 442 if (iter == end || version != 1 || *end != '.')
441 errx(EXIT_FAILURE, "Input #FORMAT"); 443 errx(EXIT_FAILURE, "Input #FORMAT");
442 iter = end + 1; 444 iter = end + 1;
443 version = strtol(iter, &end, 10); 445 version = strtol(iter, &end, 10);
444 if (iter == end || version != 1 || *end != '.') 446 if (iter == end || version != 1 || *end != '.')
445 errx(EXIT_FAILURE, "Input #FORMAT"); 447 errx(EXIT_FAILURE, "Input #FORMAT");
446 iter = end + 1; 448 iter = end + 1;
447 version = strtol(iter, &end, 10); 449 version = strtol(iter, &end, 10);
448 if (iter == end || version != 0) 450 if (iter == end || version != 0)
449 errx(EXIT_FAILURE, "Input #FORMAT"); 451 errx(EXIT_FAILURE, "Input #FORMAT");
450 for (iter = end; iter != next; ++iter) { 452 for (iter = end; iter != next; ++iter) {
451 if (!isspace((unsigned char)*iter)) 453 if (!isspace((unsigned char)*iter))
452 errx(EXIT_FAILURE, "Input #FORMAT"); 454 errx(EXIT_FAILURE, "Input #FORMAT");
453 } 455 }
454 break; 456 break;
455 } 457 }
456 if (*iter == '\0') 458 if (*iter == '\0')
457 errx(EXIT_FAILURE, "Missing #CHECKSUM or content"); 459 errx(EXIT_FAILURE, "Missing #CHECKSUM or content");
458 460
459 for (iter = next; *iter; iter = next) { 461 for (iter = next; *iter; iter = next) {
460 if ((next = strchr(iter, '\n')) == NULL) 462 if ((next = strchr(iter, '\n')) == NULL)
461 errx(EXIT_FAILURE, "Missing newline in pkg-vulnerabilities"); 463 errx(EXIT_FAILURE, "Missing newline in pkg-vulnerabilities");
462 ++next; 464 ++next;
463 if (*iter == '\0' || *iter == '\n') 465 if (*iter == '\0' || *iter == '\n')
464 continue; 466 continue;
465 if (in_pgp_msg && strncmp(iter, pgp_msg_end, strlen(pgp_msg_end)) == 0) 467 if (in_pgp_msg && strncmp(iter, pgp_msg_end, strlen(pgp_msg_end)) == 0)
466 break; 468 break;
467 if (!in_pgp_msg && strncmp(iter, pkcs7_begin, strlen(pkcs7_begin)) == 0) 469 if (!in_pgp_msg && strncmp(iter, pkcs7_begin, strlen(pkcs7_begin)) == 0)
468 break; 470 break;
469 if (*iter == '#' && 471 if (*iter == '#' &&
470 (iter[1] == '\0' || iter[1] == '\n' || isspace((unsigned char)iter[1]))) 472 (iter[1] == '\0' || iter[1] == '\n' || isspace((unsigned char)iter[1])))
471 continue; 473 continue;
472 if (strncmp(iter, "#CHECKSUM", 9) == 0) { 474 if (strncmp(iter, "#CHECKSUM", 9) == 0) {
473 iter += 9; 475 iter += 9;
474 if (!isspace((unsigned char)*iter)) 476 if (!isspace((unsigned char)*iter))
475 errx(EXIT_FAILURE, "Invalid #CHECKSUM"); 477 errx(EXIT_FAILURE, "Invalid #CHECKSUM");
476 while (isspace((unsigned char)*iter)) 478 while (isspace((unsigned char)*iter))
477 ++iter; 479 ++iter;
478 verify_hash(input, iter); 480 verify_hash(input, iter);
479 continue; 481 continue;
480 } 482 }
481 if (*iter == '#') { 483 if (*iter == '#') {
482 /* 484 /*
483 * This should really be an error, 485 * This should really be an error,
484 * but it is still used. 486 * but it is still used.
485 */ 487 */
486 /* errx(EXIT_FAILURE, "Invalid data line starting with #"); */ 488 /* errx(EXIT_FAILURE, "Invalid data line starting with #"); */
487 continue; 489 continue;
488 } 490 }
489 add_vulnerability(pv, &allocated_vulns, iter); 491 add_vulnerability(pv, &allocated_vulns, iter);
490 } 492 }
491 493
492 if (pv->entries != allocated_vulns) { 494 if (pv->entries != allocated_vulns) {
493 pv->vulnerability = xrealloc(pv->vulnerability, 495 pv->vulnerability = xrealloc(pv->vulnerability,
494 sizeof(char *) * pv->entries); 496 sizeof(char *) * pv->entries);
495 pv->classification = xrealloc(pv->classification, 497 pv->classification = xrealloc(pv->classification,
496 sizeof(char *) * pv->entries); 498 sizeof(char *) * pv->entries);
497 pv->advisory = xrealloc(pv->advisory, 499 pv->advisory = xrealloc(pv->advisory,
498 sizeof(char *) * pv->entries); 500 sizeof(char *) * pv->entries);
499 } 501 }
500 502
501 return pv; 503 return pv;
502} 504}
503 505
504void 506void
505free_pkg_vulnerabilities(struct pkg_vulnerabilities *pv) 507free_pkg_vulnerabilities(struct pkg_vulnerabilities *pv)
506{ 508{
507 size_t i; 509 size_t i;
508 510
509 for (i = 0; i < pv->entries; ++i) { 511 for (i = 0; i < pv->entries; ++i) {
510 free(pv->vulnerability[i]); 512 free(pv->vulnerability[i]);
511 free(pv->classification[i]); 513 free(pv->classification[i]);
512 free(pv->advisory[i]); 514 free(pv->advisory[i]);
513 } 515 }
514 free(pv->vulnerability); 516 free(pv->vulnerability);
515 free(pv->classification); 517 free(pv->classification);
516 free(pv->advisory); 518 free(pv->advisory);
517 free(pv); 519 free(pv);
518} 520}
519 521
520static int 522static int
521check_ignored_entry(struct pkg_vulnerabilities *pv, size_t i) 523check_ignored_entry(struct pkg_vulnerabilities *pv, size_t i)
522{ 524{
523 const char *iter, *next; 525 const char *iter, *next;
524 size_t entry_len, url_len; 526 size_t entry_len, url_len;
525 527
526 if (ignore_advisories == NULL) 528 if (ignore_advisories == NULL)
527 return 0; 529 return 0;
528 530
529 url_len = strlen(pv->advisory[i]); 531 url_len = strlen(pv->advisory[i]);
530 532
531 for (iter = ignore_advisories; *iter; iter = next) { 533 for (iter = ignore_advisories; *iter; iter = next) {
532 if ((next = strchr(iter, '\n')) == NULL) { 534 if ((next = strchr(iter, '\n')) == NULL) {
533 entry_len = strlen(iter); 535 entry_len = strlen(iter);
534 next = iter + entry_len; 536 next = iter + entry_len;
535 } else { 537 } else {
536 entry_len = next - iter; 538 entry_len = next - iter;
537 ++next; 539 ++next;
538 } 540 }
539 if (url_len != entry_len) 541 if (url_len != entry_len)
540 continue; 542 continue;
541 if (strncmp(pv->advisory[i], iter, entry_len) == 0) 543 if (strncmp(pv->advisory[i], iter, entry_len) == 0)
542 return 1; 544 return 1;
543 } 545 }
544 return 0; 546 return 0;
545} 547}
546 548
547int 549int
548audit_package(struct pkg_vulnerabilities *pv, const char *pkgname, 550audit_package(struct pkg_vulnerabilities *pv, const char *pkgname,
549 const char *limit_vul_types, int check_eol, int output_type) 551 const char *limit_vul_types, int check_eol, int output_type)
550{ 552{
551 FILE *output = output_type == 1 ? stdout : stderr; 553 FILE *output = output_type == 1 ? stdout : stderr;
552 size_t i; 554 size_t i;
553 int retval; 555 int retval;
554 556
555 retval = 0; 557 retval = 0;
556 558
557 for (i = 0; i < pv->entries; ++i) { 559 for (i = 0; i < pv->entries; ++i) {
558 if (check_ignored_entry(pv, i)) 560 if (check_ignored_entry(pv, i))
559 continue; 561 continue;
560 if (limit_vul_types != NULL && 562 if (limit_vul_types != NULL &&
561 strcmp(limit_vul_types, pv->classification[i])) 563 strcmp(limit_vul_types, pv->classification[i]))
562 continue; 564 continue;
563 if (!pkg_match(pv->vulnerability[i], pkgname)) 565 if (!pkg_match(pv->vulnerability[i], pkgname))
564 continue; 566 continue;
565 if (strcmp("eol", pv->classification[i]) == 0) { 567 if (strcmp("eol", pv->classification[i]) == 0) {
566 if (!check_eol) 568 if (!check_eol)
567 continue; 569 continue;
568 if (output_type == 0) { 570 if (output_type == 0) {
569 puts(pkgname); 571 puts(pkgname);
570 continue; 572 continue;
571 } 573 }
572 fprintf(output, 574 fprintf(output,
573 "Package %s has reached end-of-life (eol), " 575 "Package %s has reached end-of-life (eol), "
574 "see %s/eol-packages\n", pkgname, 576 "see %s/eol-packages\n", pkgname,
575 tnf_vulnerability_base); 577 tnf_vulnerability_base);
576 continue; 578 continue;
577 } 579 }
578 retval = 1; 580 retval = 1;
579 if (output_type == 0) { 581 if (output_type == 0) {
580 puts(pkgname); 582 puts(pkgname);
581 } else { 583 } else {
582 fprintf(output, 584 fprintf(output,
583 "Package %s has a %s vulnerability, see %s\n", 585 "Package %s has a %s vulnerability, see %s\n",
584 pkgname, pv->classification[i], pv->advisory[i]); 586 pkgname, pv->classification[i], pv->advisory[i]);
585 } 587 }
586 } 588 }
587 return retval; 589 return retval;
588} 590}