Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
ssh: add ssh_args per repositories
Baptiste Daroussin committed 1 month ago
commit a245a7e3b79d4f4d026e63441024f9ab4bb2c4d2
parent ebee824
9 files changed +108 -1
modified docs/pkg-repository.5
@@ -234,6 +234,21 @@ schemes are used with
.Cm SRV
mirror type to enable DNS-based mirror discovery.
.Pp
+
For
+
.Cm ssh://
+
repositories, extra arguments can be passed to
+
.Xr ssh 1
+
via the
+
.Cm SSH_ARGS
+
per-repository option or the global
+
.Cm PKG_SSH_ARGS
+
setting in
+
.Xr pkg.conf 5 .
+
The per-repository setting takes precedence over the global one.
+
This is useful for specifying a private key
+
.Pq Fl i
+
or other connection options for a specific repository.
+
.Pp
Additional URL schemes can be configured via the
.Cm VALID_URL_SCHEME
option in
modified docs/pkg.conf.5
@@ -312,6 +312,10 @@ Default:
.It Cm PKG_SSH_ARGS: string
Extra arguments to pass to
.Xr ssh 1 .
+
This is a global setting; it can be overridden on a per-repository basis
+
using the
+
.Cm SSH_ARGS
+
option in the repository configuration.
Default: not set.
.It Cm PLIST_KEYWORDS_DIR: string
Directory containing definitions of plist keywords.
@@ -570,6 +574,16 @@ Default: 0.
Set the priority of the repository.
Higher values are preferred.
Default: 0.
+
.It Cm SSH_ARGS: string
+
Extra arguments to pass to
+
.Xr ssh 1
+
when fetching from this repository.
+
This overrides the global
+
.Cm PKG_SSH_ARGS
+
setting for this repository only.
+
Useful for specifying a private key or connection options on a
+
per-repository basis.
+
Default: not set.
.El
.El
.Pp
modified libpkg/fetch_ssh.c
@@ -188,7 +188,10 @@ ssh_connect(struct pkg_repo *repo, struct yuarel *u)
		cmd = xstring_new();
		fputs("/usr/bin/ssh -e none -T ", cmd->fp);

-
		ssh_args = pkg_object_string(pkg_config_get("PKG_SSH_ARGS"));
+
		ssh_args = repo->ssh_args;
+
		if (ssh_args == NULL)
+
			ssh_args = pkg_object_string(
+
			    pkg_config_get("PKG_SSH_ARGS"));
		if (ssh_args != NULL)
			fprintf(cmd->fp, "%s ", ssh_args);
		if (repo->ip == IPV4)
modified libpkg/libpkg.ver
@@ -165,6 +165,7 @@ global:
	pkg_repo_mirror_type;
	pkg_repo_name;
	pkg_repo_priority;
+
	pkg_repo_ssh_args;
	pkg_repo_signature_type;
	pkg_repo_url;
	pkg_repos;
modified libpkg/pkg.h.in
@@ -1599,6 +1599,7 @@ const char *pkg_repo_url(struct pkg_repo *r);
const char *pkg_repo_name(struct pkg_repo *r);
const char *pkg_repo_key(struct pkg_repo *r);
const char *pkg_repo_fingerprints(struct pkg_repo *r);
+
const char *pkg_repo_ssh_args(struct pkg_repo *r);
signature_t pkg_repo_signature_type(struct pkg_repo *r);
bool pkg_repo_enabled(struct pkg_repo *r);
mirror_t pkg_repo_mirror_type(struct pkg_repo *r);
modified libpkg/pkg_config.c
@@ -615,6 +615,7 @@ add_repo(const ucl_object_t *obj, struct pkg_repo *r, const char *rname, pkg_ini
	bool enable = true;
	const char *url = NULL, *pubkey = NULL, *mirror_type = NULL;
	const char *signature_type = NULL, *fingerprints = NULL;
+
	const char *ssh_args = NULL;
	const char *key;
	const char *type = NULL;
	int use_ipvx = 0;
@@ -711,6 +712,14 @@ add_repo(const ucl_object_t *obj, struct pkg_repo *r, const char *rname, pkg_ini
				return;
			}
			priority = ucl_object_toint(cur);
+
		} else if (STRIEQ(key, "ssh_args")) {
+
			if (cur->type != UCL_STRING) {
+
				pkg_emit_error("Expecting a string for the "
+
					"'%s' key of the '%s' repo",
+
					key, rname);
+
				return;
+
			}
+
			ssh_args = ucl_object_tostring(cur);
		} else if (STRIEQ(key, "env")) {
			if (cur->type != UCL_OBJECT) {
				pkg_emit_error("Expecting an object for the "
@@ -751,6 +760,11 @@ add_repo(const ucl_object_t *obj, struct pkg_repo *r, const char *rname, pkg_ini
		r->pubkey = xstrdup(pubkey);
	}

+
	if (ssh_args != NULL) {
+
		free(r->ssh_args);
+
		r->ssh_args = xstrdup(ssh_args);
+
	}
+

	r->enable = enable;
	r->priority = priority;

@@ -1704,6 +1718,7 @@ pkg_repo_free(struct pkg_repo *r)
	free(r->name);
	free(r->pubkey);
	free(r->fingerprints);
+
	free(r->ssh_args);
	pkg_repo_meta_free(r->meta);
	if (r->fetcher != NULL && r->fetcher->cleanup != NULL)
		r->fetcher->cleanup(r);
@@ -1804,6 +1819,12 @@ pkg_repo_fingerprints(struct pkg_repo *r)
	return (r->fingerprints);
}

+
const char *
+
pkg_repo_ssh_args(struct pkg_repo *r)
+
{
+
	return (r->ssh_args);
+
}
+

signature_t
pkg_repo_signature_type(struct pkg_repo *r)
{
modified libpkg/private/pkg.h
@@ -546,6 +546,7 @@ struct pkg_repo {
	};
	signature_t signature_type;
	char *fingerprints;
+
	char *ssh_args;
	FILE *fh;
	void *fetch_priv;
	bool silent;
modified src/utils.c
@@ -1201,6 +1201,9 @@ print_repository(struct pkg_repo *repo, bool pad)
	if (pkg_repo_key(repo) != NULL)
		printf(",\n    %-16s: \"%s\"",
				"pubkey", pkg_repo_key(repo));
+
	if (pkg_repo_ssh_args(repo) != NULL)
+
		printf(",\n    %-16s: \"%s\"",
+
				"ssh_args", pkg_repo_ssh_args(repo));
	if (pkg_repo_ip_version(repo) != 0)
		printf(",\n    %-16s: %u",
				"ip_version", pkg_repo_ip_version(repo));
modified tests/frontend/config.sh
@@ -5,6 +5,7 @@ tests_init \
	empty_conf \
	duplicate_pkgs_notallowed \
	inline_repo \
+
	repo_ssh_args \
	nameserver \
	expansion \
	validate_shlib_provide_paths
@@ -99,6 +100,53 @@ EOF
		pkg -o REPOS_DIR=/dev/null -C pkgconfiguration -vv
}

+
repo_ssh_args_body() {
+
	# Per-repo ssh_args (issue #725)
+
	mkdir -p reposconf
+
	cat > reposconf/test.conf << EOF
+
myrepo: {
+
    url: "ssh://myhost/repo",
+
    ssh_args: "-i /path/to/key -o ConnectTimeout=10",
+
}
+
EOF
+

+
	# ssh_args should appear in -vv output
+
	atf_check \
+
		-o match:'ssh_args.*-i /path/to/key -o ConnectTimeout=10' \
+
		-s exit:0 \
+
		pkg -o REPOS_DIR="${TMPDIR}/reposconf" -vv
+

+
	# Without ssh_args, it should not appear
+
	cat > reposconf/test.conf << EOF
+
plain: {
+
    url: "ssh://otherhost/repo",
+
}
+
EOF
+

+
	atf_check \
+
		-o not-match:'ssh_args' \
+
		-s exit:0 \
+
		pkg -o REPOS_DIR="${TMPDIR}/reposconf" -vv
+

+
	# Two repos: one with ssh_args, one without
+
	cat > reposconf/test.conf << EOF
+
repo_with_args: {
+
    url: "ssh://host1/repo",
+
    ssh_args: "-i /special/key",
+
}
+
repo_without_args: {
+
    url: "ssh://host2/repo",
+
}
+
EOF
+

+
	atf_check \
+
		-o match:'ssh_args.*-i /special/key' \
+
		-o match:'repo_with_args' \
+
		-o match:'repo_without_args' \
+
		-s exit:0 \
+
		pkg -o REPOS_DIR="${TMPDIR}/reposconf" -vv
+
}
+

nameserver_body()
{
	atf_skip_on Darwin Not possible to inject a namserver on OSX