Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bin/xbps-install: add --import-key arg for non-interactive key import #568

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions bin/xbps-install/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ usage(bool fail)
" -h, --help Show usage\n"
" -i, --ignore-conf-repos Ignore repositories defined in xbps.d\n"
" -I, --ignore-file-conflicts Ignore detected file conflicts\n"
" -k, --import-key <key> Import specified key without confirmation\n"
" -U, --unpack-only Unpack packages in transaction, do not configure them\n"
" -M, --memory-sync Remote repository data is fetched and stored\n"
" in memory, ignoring on-disk repodata archives\n"
Expand Down Expand Up @@ -82,11 +83,11 @@ unpack_progress_cb(const struct xbps_unpack_cb_data *xpd, void *cbdata UNUSED)
}

static int
repo_import_key_cb(struct xbps_repo *repo, void *arg UNUSED, bool *done UNUSED)
repo_import_key_cb(struct xbps_repo *repo, void *expfps, bool *done UNUSED)
{
int rv;

if ((rv = xbps_repo_key_import(repo)) != 0)
if ((rv = xbps_repo_key_import(repo, expfps)) != 0)
xbps_error_printf("Failed to import pubkey from %s: %s\n",
repo->uri, strerror(rv));

Expand All @@ -96,7 +97,7 @@ repo_import_key_cb(struct xbps_repo *repo, void *arg UNUSED, bool *done UNUSED)
int
main(int argc, char **argv)
{
const char *shortopts = "AC:c:DdfhIiMnR:r:SuUVvy";
const char *shortopts = "AC:c:DdfhIik:MnR:r:SuUVvy";
const struct option longopts[] = {
{ "automatic", no_argument, NULL, 'A' },
{ "config", required_argument, NULL, 'C' },
Expand All @@ -107,6 +108,7 @@ main(int argc, char **argv)
{ "help", no_argument, NULL, 'h' },
{ "ignore-conf-repos", no_argument, NULL, 'i' },
{ "ignore-file-conflicts", no_argument, NULL, 'I' },
{ "import-key", required_argument, NULL, 'k' },
{ "memory-sync", no_argument, NULL, 'M' },
{ "dry-run", no_argument, NULL, 'n' },
{ "repository", required_argument, NULL, 'R' },
Expand All @@ -126,6 +128,7 @@ main(int argc, char **argv)
int i, c, flags, rv, fflag = 0;
bool syncf, yes, force, drun, update;
int maxcols, eexist = 0;
xbps_array_t expfps = NULL;

rootdir = cachedir = confdir = NULL;
flags = rv = 0;
Expand Down Expand Up @@ -168,6 +171,11 @@ main(int argc, char **argv)
case 'i':
flags |= XBPS_FLAG_IGNORE_CONF_REPOS;
break;
case 'k':
if (expfps == NULL)
expfps = xbps_array_create();
xbps_array_add_cstring_nocopy(expfps, optarg);
break;
case 'M':
flags |= XBPS_FLAG_REPOS_MEMSYNC;
break;
Expand Down Expand Up @@ -235,7 +243,7 @@ main(int argc, char **argv)
if (syncf && !drun) {
if ((rv = xbps_rpool_sync(&xh, NULL)) != 0)
exit(rv);
rv = xbps_rpool_foreach(&xh, repo_import_key_cb, NULL);
rv = xbps_rpool_foreach(&xh, repo_import_key_cb, expfps);
if (rv != 0)
exit(rv);
}
Expand Down
4 changes: 4 additions & 0 deletions bin/xbps-install/state_cb.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ state_cb(const struct xbps_state_cb_data *xscd, void *cbdata UNUSED)
printf("Fingerprint: %s\n", xscd->arg);
rv = yesno("Do you want to import this public key?");
break;
case XBPS_STATE_REPO_KEY_EXPECTED:
printf("%s\n", xscd->desc);
printf("Importing key with fingerprint: %s\n", xscd->arg);
break;
case XBPS_STATE_SHOW_INSTALL_MSG:
printf("%s: post-install message:\n", xscd->arg);
printf("========================================================================\n");
Expand Down
8 changes: 7 additions & 1 deletion bin/xbps-install/xbps-install.1
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,14 @@ Ignore detected file conflicts in a transaction.
.It Fl i , Fl -ignore-conf-repos
Ignore repositories defined in configuration files.
Only repositories specified in the command line via
.Ar --repository
.Fl -repository
will be used.
.It Fl k , Fl -import-key Ar fingerprint
Import the key with the specified
.Ar fingerprint
without confirmation.
Specified keys will only be imported if the key is used by a remote repository and has not already been imported.
This option can be specified multiple times.
.It Fl M , Fl -memory-sync
For remote repositories, the data is fetched and stored in memory for the current
operation.
Expand Down
5 changes: 4 additions & 1 deletion include/xbps.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ extern "C" {
* - XBPS_STATE_UNPACK_FAIL: package unpack has failed.
* - XBPS_STATE_REPOSYNC_FAIL: syncing remote repositories has failed.
* - XBPS_STATE_REPO_KEY_IMPORT: repository is signed and needs to import pubkey.
* - XBPS_STATE_REPO_KEY_EXPECTED: repository is signed and will import expected pubkey.
* - XBPS_STATE_INVALID_DEP: package has an invalid dependency.
* - XBPS_STATE_SHOW_INSTALL_MSG: package must show a post-install message.
* - XBPS_STATE_SHOW_REMOVE_MSG: package must show a pre-remove message.
Expand Down Expand Up @@ -369,6 +370,7 @@ typedef enum xbps_state {
XBPS_STATE_REPOSYNC_FAIL,
XBPS_STATE_CONFIGURE_DONE,
XBPS_STATE_REPO_KEY_IMPORT,
XBPS_STATE_REPO_KEY_EXPECTED,
XBPS_STATE_INVALID_DEP,
XBPS_STATE_SHOW_INSTALL_MSG,
XBPS_STATE_SHOW_REMOVE_MSG,
Expand Down Expand Up @@ -1755,10 +1757,11 @@ xbps_array_t xbps_repo_get_pkg_revdeps(struct xbps_repo *repo, const char *pkg);
* signed properly for this to work.
*
* @param[in] repo Pointer to the target xbps_repo structure.
* @param[in] expfps Proplib array of expected key fingerprints.
*
* @return 0 on success, an errno value otherwise.
*/
int xbps_repo_key_import(struct xbps_repo *repo);
int xbps_repo_key_import(struct xbps_repo *repo, xbps_array_t expfps);

/**@}*/

Expand Down
22 changes: 19 additions & 3 deletions lib/repo.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ repo_open_remote(struct xbps_repo *repo)
free(rpath);
if (rv) {
xbps_dbg_printf("[repo] `%s' used remotely (kept in memory).\n", repo->uri);
if (repo->xhp->state_cb && xbps_repo_key_import(repo) != 0)
if (repo->xhp->state_cb && xbps_repo_key_import(repo, NULL) != 0)
rv = false;
}
return rv;
Expand Down Expand Up @@ -621,13 +621,14 @@ xbps_repo_get_pkg_revdeps(struct xbps_repo *repo, const char *pkg)
}

int
xbps_repo_key_import(struct xbps_repo *repo)
xbps_repo_key_import(struct xbps_repo *repo, xbps_array_t expfps)
{
xbps_dictionary_t repokeyd = NULL;
xbps_data_t pubkey = NULL;
uint16_t pubkey_size = 0;
const char *signedby = NULL;
char *hexfp = NULL;
const char *expfp = NULL;
char *p, *dbkeyd, *rkeyfile = NULL;
int import, rv = 0;

Expand Down Expand Up @@ -662,14 +663,28 @@ xbps_repo_key_import(struct xbps_repo *repo)
goto out;
}
/*
* Check if the public key is alredy stored.
* Check if the public key is already stored.
*/
rkeyfile = xbps_xasprintf("%s/keys/%s.plist", repo->xhp->metadir, hexfp);
repokeyd = xbps_plist_dictionary_from_file(rkeyfile);
if (xbps_object_type(repokeyd) == XBPS_TYPE_DICTIONARY) {
xbps_dbg_printf("[repo] `%s' public key already stored.\n", repo->uri);
goto out;
}
/*
* Check if the public key is expected. If so, import the key
* without prompting for user input.
*/
if (expfps != NULL) {
for (unsigned int i = 0; i < xbps_array_count(expfps); i++) {
if (xbps_array_get_cstring_nocopy(expfps, i, &expfp) && strcmp(hexfp, expfp) == 0) {
xbps_set_cb_state(repo->xhp, XBPS_STATE_REPO_KEY_EXPECTED, 0,
hexfp, "`%s' repository has been RSA signed by \"%s\"",
repo->uri, signedby);
goto importkey;
}
}
}
/*
* Notify the client and take appropiate action to import
* the repository public key. Pass back the public key openssh fingerprint
Expand All @@ -683,6 +698,7 @@ xbps_repo_key_import(struct xbps_repo *repo)
goto out;
}

importkey:
p = strdup(rkeyfile);
dbkeyd = dirname(p);
assert(dbkeyd);
Expand Down
Loading