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