Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Implement signing the repo with an external command
Baptiste Daroussin committed 12 years ago
commit c4596620a8510c8fe81be6efafa5c7de0a8353f7
parent 06cd326
3 files changed +127 -15
modified libpkg/pkg.h.in
@@ -925,7 +925,7 @@ int pkg_is_installed(struct pkgdb *db, const char *origin);
 * @param sum An 65 long char array to receive the sha256 sum
 */
int pkg_create_repo(char *path, bool force, bool filelist, void (*callback)(struct pkg *, void *), void *);
-
int pkg_finish_repo(char *path, pem_password_cb *cb, char *rsa_key_path, bool filelist);
+
int pkg_finish_repo(char *path, pem_password_cb *cb, char **argv, int argc, bool filelist);

/**
 * Test if the EUID has sufficient privilege to carry out some
modified libpkg/pkg_repo.c
@@ -37,6 +37,8 @@
#include <libgen.h>
#include <sqlite3.h>
#include <string.h>
+
#define _WITH_GETLINE
+
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>

@@ -512,11 +514,80 @@ read_pkg_file(void *data)
}

static int
-
pack_db(const char *name, const char *archive, char *path, struct rsa_key *rsa)
+
cmd_sign(char *path, char **argv, int argc, struct sbuf **sig, struct sbuf **cert)
+
{
+
	FILE *fp;
+
	char sha256[SHA256_DIGEST_LENGTH * 2 + 1];
+
	struct sbuf *cmd;
+
	struct sbuf *buf = NULL;
+
	char *line = NULL;
+
	size_t linecap = 0;
+
	ssize_t linelen;
+
	int i;
+

+
	if (sha256_file(path, sha256) != EPKG_OK)
+
		return (EPKG_FATAL);
+

+
	cmd = sbuf_new_auto();
+

+
	for (i = 0; i < argc; i++) {
+
		if (strspn(argv[i], " \t\n") > 0)
+
			sbuf_printf(cmd, " \"%s\" ", argv[i]);
+
		else
+
			sbuf_printf(cmd, " %s ", argv[i]);
+
	}
+
	sbuf_done(cmd);
+

+
	if ((fp = popen(sbuf_data(cmd), "r+")) == NULL) {
+
		sbuf_delete(cmd);
+
		return (EPKG_FATAL);
+
	}
+

+
	fprintf(fp, "%s\n", sha256);
+

+
	if (*sig == NULL)
+
		*sig = sbuf_new_auto();
+
	if (*cert == NULL)
+
		*cert = sbuf_new_auto();
+

+
	while ((linelen = getline(&line, &linecap, fp)) > 0 ) {
+
		if (strcmp(line, "SIGNATURE\n") == 0) {
+
			buf = *sig;
+
			continue;
+
		} else if (strcmp(line, "CERT\n") == 0) {
+
			buf = *cert;
+
			continue;
+
		} else if (strcmp(line, "END\n") == 0) {
+
			break;
+
		}
+
		if (buf != NULL)
+
			sbuf_bcat(buf, line, linelen);
+
	}
+

+
	if (sbuf_data(*sig)[sbuf_len(*sig) -1 ] == '\n')
+
		sbuf_setpos(*sig, sbuf_len(*sig) -1);
+
	if (sbuf_data(*cert)[sbuf_len(*cert) -1 ] == '\n')
+
		sbuf_setpos(*cert, sbuf_len(*cert) -1);
+

+
	sbuf_finish(*sig);
+
	sbuf_finish(*cert);
+

+
	printf("%s\n", sbuf_data(*cert));
+
	
+
	return (EPKG_OK);
+
}
+

+
static int
+
pack_db(const char *name, const char *archive, char *path, struct rsa_key *rsa, char **argv, int argc)
{
	struct packing *pack;
	unsigned char *sigret = NULL;
	unsigned int siglen = 0;
+
	char fname[MAXPATHLEN];
+
	struct sbuf *sig, *pub;
+

+
	sig = NULL;
+
	pub = NULL;

	if (packing_init(&pack, archive, TXZ) != EPKG_OK)
		return (EPKG_FATAL);
@@ -524,27 +595,56 @@ pack_db(const char *name, const char *archive, char *path, struct rsa_key *rsa)
	if (rsa != NULL) {
		if (rsa_sign(path, rsa, &sigret, &siglen) != EPKG_OK) {
			packing_finish(pack);
+
			packing_finish(pack);
			return (EPKG_FATAL);
		}

		if (packing_append_buffer(pack, sigret, "signature", siglen + 1) != EPKG_OK) {
			free(sigret);
			free(pack);
+
			unlink(path);
			return (EPKG_FATAL);
		}

		free(sigret);
+
	} else if (argc > 1) {
+
		if (cmd_sign(path, argv, argc, &sig, &pub) != EPKG_OK) {
+
			packing_finish(pack);
+
			unlink(path);
+
			return (EPKG_FATAL);
+
		}
+

+
		snprintf(fname, sizeof(fname), "%s.sig", name);
+
		if (packing_append_buffer(pack, sbuf_data(sig), fname, sbuf_len(sig)) != EPKG_OK) {
+
			packing_finish(pack);
+
			sbuf_delete(sig);
+
			sbuf_delete(pub);
+
			unlink(path);
+
			return (EPKG_FATAL);
+
		}
+

+
		snprintf(fname, sizeof(fname), "%s.pub", name);
+
		if (packing_append_buffer(pack, sbuf_data(pub), fname, sbuf_len(pub)) != EPKG_OK) {
+
			packing_finish(pack);
+
			unlink(path);
+
			sbuf_delete(sig);
+
			sbuf_delete(pub);
+
			return (EPKG_FATAL);
+
		}
+

	}
	packing_append_file_attr(pack, path, name, "root", "wheel", 0644);

-
	unlink(path);
	packing_finish(pack);
+
	unlink(path);
+
	sbuf_delete(sig);
+
	sbuf_delete(pub);

	return (EPKG_OK);
}

int
-
pkg_finish_repo(char *path, pem_password_cb *password_cb, char *rsa_key_path, bool filelist)
+
pkg_finish_repo(char *path, pem_password_cb *password_cb, char **argv, int argc, bool filelist)
{
	char repo_path[MAXPATHLEN + 1];
	char repo_archive[MAXPATHLEN + 1];
@@ -557,19 +657,28 @@ pkg_finish_repo(char *path, pem_password_cb *password_cb, char *rsa_key_path, bo
	    return (EPKG_FATAL);
	}

-
	if (rsa_key_path != NULL)
-
		rsa_new(&rsa, password_cb, rsa_key_path);
+
	if (argc == 1) {
+
		rsa_new(&rsa, password_cb, argv[0]);
+
	}
+

+
	if (argc > 1 && strcmp(argv[0], "signing_command:") != 0)
+
		return (EPKG_FATAL);
+

+
	if (argc > 1) {
+
		argc--;
+
		argv++;
+
	}

	snprintf(repo_path, sizeof(repo_path), "%s/%s", path, repo_packagesite_file);
	snprintf(repo_archive, sizeof(repo_archive), "%s/%s", path, repo_packagesite_archive);
-
	if (pack_db(repo_packagesite_file, repo_archive, repo_path, rsa) != EPKG_OK) {
+
	if (pack_db(repo_packagesite_file, repo_archive, repo_path, rsa, argv, argc) != EPKG_OK) {
		ret = EPKG_FATAL;
		goto cleanup;
	}

	snprintf(repo_path, sizeof(repo_path), "%s/%s", path, repo_db_file);
	snprintf(repo_archive, sizeof(repo_archive), "%s/%s", path, repo_db_archive);
-
	if (pack_db(repo_db_file, repo_archive, repo_path, rsa) != EPKG_OK) {
+
	if (pack_db(repo_db_file, repo_archive, repo_path, rsa, argv, argc) != EPKG_OK) {
		ret = EPKG_FATAL;
		goto cleanup;
	}
@@ -577,7 +686,7 @@ pkg_finish_repo(char *path, pem_password_cb *password_cb, char *rsa_key_path, bo
	if (filelist) {
		snprintf(repo_path, sizeof(repo_path), "%s/%s", path, repo_filesite_file);
		snprintf(repo_archive, sizeof(repo_archive), "%s/%s", path, repo_filesite_archive);
-
		if (pack_db(repo_filesite_file, repo_archive, repo_path, rsa) != EPKG_OK) {
+
		if (pack_db(repo_filesite_file, repo_archive, repo_path, rsa, argv, argc) != EPKG_OK) {
			ret = EPKG_FATAL;
			goto cleanup;
		}
@@ -585,7 +694,7 @@ pkg_finish_repo(char *path, pem_password_cb *password_cb, char *rsa_key_path, bo

	snprintf(repo_path, sizeof(repo_path), "%s/%s", path, repo_digests_file);
	snprintf(repo_archive, sizeof(repo_archive), "%s/%s", path, repo_digests_archive);
-
	if (pack_db(repo_digests_file, repo_archive, repo_path, rsa) != EPKG_OK) {
+
	if (pack_db(repo_digests_file, repo_archive, repo_path, rsa, argv, argc) != EPKG_OK) {
		ret = EPKG_FATAL;
		goto cleanup;
	}
modified pkg/repo.c
@@ -37,7 +37,7 @@
void
usage_repo(void)
{
-
	fprintf(stderr, "Usage: pkg repo [-flq] <repo-path> <rsa-key>\n\n");
+
	fprintf(stderr, "Usage: pkg repo [-flq] <repo-path> [<rsa-key>|signing_command: <the command>]\n\n");
	fprintf(stderr, "For more information see 'pkg help repo'.\n");
}

@@ -88,7 +88,6 @@ exec_repo(int argc, char **argv)
	int ret;
	int pos = 0;
	int ch;
-
	char *rsa_key;
	bool force = false, filelist = false;

	while ((ch = getopt(argc, argv, "flq")) != -1) {
@@ -110,7 +109,12 @@ exec_repo(int argc, char **argv)
	argc -= optind;
	argv += optind;

-
	if (argc < 1 || argc > 2) {
+
	if (argc < 1) {
+
		usage_repo();
+
		return (EX_USAGE);
+
	}
+

+
	if (argc > 2 && strcmp(argv[1], "signing_command:") != 0) {
		usage_repo();
		return (EX_USAGE);
	}
@@ -129,8 +133,7 @@ exec_repo(int argc, char **argv)
			printf("\bdone!\n");
	}
	
-
	rsa_key = (argc == 2) ? argv[1] : NULL;
-
	pkg_finish_repo(argv[0], password_cb, rsa_key, filelist);
+
	pkg_finish_repo(argv[0], password_cb, argv + 1, argc - 1, filelist);

	return (EX_OK);
}