summaryrefslogtreecommitdiff
path: root/pkgtools/pkg_install/files/lib/pkg_signature.c
diff options
context:
space:
mode:
Diffstat (limited to 'pkgtools/pkg_install/files/lib/pkg_signature.c')
-rw-r--r--pkgtools/pkg_install/files/lib/pkg_signature.c130
1 files changed, 116 insertions, 14 deletions
diff --git a/pkgtools/pkg_install/files/lib/pkg_signature.c b/pkgtools/pkg_install/files/lib/pkg_signature.c
index d6db90005ad..63ad25c9ef1 100644
--- a/pkgtools/pkg_install/files/lib/pkg_signature.c
+++ b/pkgtools/pkg_install/files/lib/pkg_signature.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pkg_signature.c,v 1.1.2.6 2008/08/10 22:09:38 joerg Exp $ */
+/* $NetBSD: pkg_signature.c,v 1.1.2.7 2008/12/30 15:55:57 joerg Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
@@ -7,7 +7,7 @@
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
-__RCSID("$NetBSD: pkg_signature.c,v 1.1.2.6 2008/08/10 22:09:38 joerg Exp $");
+__RCSID("$NetBSD: pkg_signature.c,v 1.1.2.7 2008/12/30 15:55:57 joerg Exp $");
/*-
* Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
@@ -67,6 +67,7 @@ __RCSID("$NetBSD: pkg_signature.c,v 1.1.2.6 2008/08/10 22:09:38 joerg Exp $");
#define HASH_FNAME "+PKG_HASH"
#define SIGNATURE_FNAME "+PKG_SIGNATURE"
+#define GPG_SIGNATURE_FNAME "+PKG_GPG_SIGNATURE"
struct signature_archive {
struct archive *archive;
@@ -335,21 +336,31 @@ pkg_verify_signature(struct archive **archive, struct archive_entry **entry,
goto no_valid_signature;
}
- r = read_file_from_archive(*archive, entry, SIGNATURE_FNAME,
- &signature_file, &signature_len);
- if (r != 0) {
- free(hash_file);
- free(state);
- goto no_valid_signature;
- }
-
if (parse_hash_file(hash_file, pkgname, state))
goto no_valid_signature;
- has_sig = !easy_pkcs7_verify(hash_file, hash_len, signature_file,
- signature_len, certs_packages, 1);
+ r = read_file_from_archive(*archive, entry, SIGNATURE_FNAME,
+ &signature_file, &signature_len);
+ if (r != 0) {
+ if (*entry != NULL)
+ r = read_file_from_archive(*archive, entry,
+ GPG_SIGNATURE_FNAME,
+ &signature_file, &signature_len);
+ if (r != 0) {
+ free(hash_file);
+ free(state);
+ goto no_valid_signature;
+ }
+ has_sig = !detached_gpg_verify(hash_file, hash_len,
+ signature_file, signature_len, NULL);
+
+ free(signature_file);
+ } else {
+ has_sig = !easy_pkcs7_verify(hash_file, hash_len, signature_file,
+ signature_len, certs_packages, 1);
- free(signature_file);
+ free(signature_file);
+ }
r = archive_read_next_header(*archive, &my_entry);
if (r != ARCHIVE_OK) {
@@ -493,7 +504,7 @@ static const char hash_template[] =
static const char hash_trailer[] = "end pkgsrc signature\n";
void
-pkg_sign(const char *name, const char *output, const char *key_file, const char *cert_file)
+pkg_sign_x509(const char *name, const char *output, const char *key_file, const char *cert_file)
{
struct archive *pkg;
struct archive_entry *entry, *hash_entry, *sign_entry;
@@ -582,3 +593,94 @@ pkg_sign(const char *name, const char *output, const char *key_file, const char
exit(0);
}
+
+void
+pkg_sign_gpg(const char *name, const char *output)
+{
+ struct archive *pkg;
+ struct archive_entry *entry, *hash_entry, *sign_entry;
+ int fd;
+ struct stat sb;
+ char *hash_file, *signature_file, *tmp, *pkgname, hash[SHA512_DIGEST_STRING_LENGTH];
+ unsigned char block[65536];
+ off_t i, size;
+ size_t block_len, signature_len;
+
+ if ((fd = open(name, O_RDONLY)) == -1)
+ err(EXIT_FAILURE, "Cannot open binary package %s", name);
+ if (fstat(fd, &sb) == -1)
+ err(EXIT_FAILURE, "Cannot stat %s", name);
+
+ entry = archive_entry_new();
+ archive_entry_copy_stat(entry, &sb);
+
+ pkgname = extract_pkgname(fd);
+ hash_file = xasprintf(hash_template, pkgname,
+ (long long)archive_entry_size(entry));
+ free(pkgname);
+
+ for (i = 0; i < archive_entry_size(entry); i += block_len) {
+ if (i + sizeof(block) < archive_entry_size(entry))
+ block_len = sizeof(block);
+ else
+ block_len = archive_entry_size(entry) % sizeof(block);
+ if (read(fd, block, block_len) != block_len)
+ err(2, "short read");
+ hash_block(block, block_len, hash);
+ tmp = xasprintf("%s%s\n", hash_file, hash);
+ free(hash_file);
+ hash_file = tmp;
+ }
+ tmp = xasprintf("%s%s", hash_file, hash_trailer);
+ free(hash_file);
+ hash_file = tmp;
+
+ if (detached_gpg_sign(hash_file, strlen(hash_file), &signature_file,
+ &signature_len, NULL, NULL))
+ err(EXIT_FAILURE, "Cannot sign hash file");
+
+ lseek(fd, 0, SEEK_SET);
+
+ sign_entry = archive_entry_clone(entry);
+ hash_entry = archive_entry_clone(entry);
+ pkgname = strrchr(name, '/');
+ archive_entry_set_pathname(entry, pkgname != NULL ? pkgname + 1 : name);
+ archive_entry_set_pathname(hash_entry, HASH_FNAME);
+ archive_entry_set_pathname(sign_entry, GPG_SIGNATURE_FNAME);
+ archive_entry_set_size(hash_entry, strlen(hash_file));
+ archive_entry_set_size(sign_entry, signature_len);
+
+ pkg = archive_write_new();
+ archive_write_set_compression_none(pkg);
+ archive_write_set_format_ar_bsd(pkg);
+ archive_write_open_filename(pkg, output);
+
+ archive_write_header(pkg, hash_entry);
+ archive_write_data(pkg, hash_file, strlen(hash_file));
+ archive_write_finish_entry(pkg);
+ archive_entry_free(hash_entry);
+
+ archive_write_header(pkg, sign_entry);
+ archive_write_data(pkg, signature_file, signature_len);
+ archive_write_finish_entry(pkg);
+ archive_entry_free(sign_entry);
+
+ size = archive_entry_size(entry);
+ archive_write_header(pkg, entry);
+
+ for (i = 0; i < size; i += block_len) {
+ if (i + sizeof(block) < size)
+ block_len = sizeof(block);
+ else
+ block_len = size % sizeof(block);
+ if (read(fd, block, block_len) != block_len)
+ err(2, "short read");
+ archive_write_data(pkg, block, block_len);
+ }
+ archive_write_finish_entry(pkg);
+ archive_entry_free(entry);
+
+ archive_write_finish(pkg);
+
+ exit(0);
+}