rpm/rpmsign.c

188 lines
4.4 KiB
C

#include "system.h"
#include <errno.h>
#include <sys/wait.h>
#include <popt.h>
#include <rpm/rpmcli.h>
#include "cliutils.h"
#include "debug.h"
#if !defined(__GLIBC__) && !defined(__APPLE__)
char ** environ = NULL;
#endif
enum modes {
MODE_ADDSIGN = (1 << 0),
MODE_RESIGN = (1 << 1),
MODE_DELSIGN = (1 << 2),
};
static int mode = 0;
static struct poptOption optionsTable[] = {
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
N_("Common options for all rpm modes and executables:"), NULL },
{ "addsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_ADDSIGN,
N_("sign package(s)"), NULL },
{ "resign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_RESIGN,
N_("sign package(s) (identical to --addsign)"), NULL },
{ "delsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_DELSIGN,
N_("delete package signatures"), NULL },
POPT_AUTOALIAS
POPT_AUTOHELP
POPT_TABLEEND
};
static rpmSigTag lookupSignatureType(void)
{
rpmSigTag rc = 0;
char *name = rpmExpand("%{?_signature}", NULL);
if (!(name && *name != '\0'))
rc = 0;
else if (!rstrcasecmp(name, "none"))
rc = 0;
else if (!rstrcasecmp(name, "pgp"))
rc = RPMSIGTAG_PGP;
else if (!rstrcasecmp(name, "pgp5")) /* XXX legacy */
rc = RPMSIGTAG_PGP;
else if (!rstrcasecmp(name, "gpg"))
rc = RPMSIGTAG_GPG;
else
rc = -1; /* Invalid %_signature spec in macro file */
name = _free(name);
return rc;
}
static int checkPassPhrase(const char * passPhrase)
{
int passPhrasePipe[2];
int pid, status;
int rc;
int xx;
if (passPhrase == NULL)
return -1;
passPhrasePipe[0] = passPhrasePipe[1] = 0;
xx = pipe(passPhrasePipe);
if (!(pid = fork())) {
char * cmd, * gpg_path;
char *const *av;
int fdno;
xx = close(STDIN_FILENO);
xx = close(STDOUT_FILENO);
xx = close(passPhrasePipe[1]);
if ((fdno = open("/dev/null", O_RDONLY)) != STDIN_FILENO) {
xx = dup2(fdno, STDIN_FILENO);
xx = close(fdno);
}
if ((fdno = open("/dev/null", O_WRONLY)) != STDOUT_FILENO) {
xx = dup2(fdno, STDOUT_FILENO);
xx = close(fdno);
}
xx = dup2(passPhrasePipe[0], 3);
unsetenv("MALLOC_CHECK_");
gpg_path = rpmExpand("%{?_gpg_path}", NULL);
if (!rstreq(gpg_path, ""))
setenv("GNUPGHOME", gpg_path, 1);
cmd = rpmExpand("%{?__gpg_check_password_cmd}", NULL);
rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
if (!rc)
rc = execve(av[0], av+1, environ);
fprintf(stderr, _("Could not exec %s: %s\n"), "gpg",
strerror(errno));
_exit(EXIT_FAILURE);
}
xx = close(passPhrasePipe[0]);
xx = write(passPhrasePipe[1], passPhrase, strlen(passPhrase));
xx = write(passPhrasePipe[1], "\n", 1);
xx = close(passPhrasePipe[1]);
(void) waitpid(pid, &status, 0);
return ((WIFEXITED(status) && WEXITSTATUS(status) == 0)) ? 0 : 1;
}
/* TODO: permit overriding macro setup on the command line */
static int doSign(ARGV_const_t args)
{
int rc = EXIT_FAILURE;
int sigTag = lookupSignatureType();
char * passPhrase = NULL;
char * name = rpmExpand("%{?_gpg_name}", NULL);
if (rstreq(name, "")) {
fprintf(stderr, _("You must set \"%%_gpg_name\" in your macro file\n"));
goto exit;
}
switch (sigTag) {
case RPMSIGTAG_PGP:
case RPMSIGTAG_GPG:
case RPMSIGTAG_DSA:
case RPMSIGTAG_RSA:
break;
default:
fprintf(stderr, _("Invalid %%_signature spec in macro file.\n"));
goto exit;
break;
}
/* XXX FIXME: eliminate obsolete getpass() usage */
passPhrase = getpass(_("Enter pass phrase: "));
passPhrase = (passPhrase != NULL) ? rstrdup(passPhrase) : NULL;
if (checkPassPhrase(passPhrase) == 0) {
fprintf(stderr, _("Pass phrase is good.\n"));
rc = rpmcliSign(args, 0, sigTag, passPhrase);
} else {
fprintf(stderr, _("Pass phrase check failed\n"));
}
exit:
free(name);
return rc;
}
int main(int argc, char *argv[])
{
int ec = EXIT_FAILURE;
poptContext optCon = rpmcliInit(argc, argv, optionsTable);
ARGV_const_t args = NULL;
if (argc <= 1) {
printUsage(optCon, stderr, 0);
goto exit;
}
args = (ARGV_const_t) poptGetArgs(optCon);
if (args == NULL) {
argerror(_("no arguments given"));
}
switch (mode) {
case MODE_ADDSIGN:
case MODE_RESIGN:
ec = doSign(args);
break;
case MODE_DELSIGN:
ec = rpmcliSign(args, 1, 0, NULL);
break;
default:
argerror(_("only one major mode may be specified"));
break;
}
exit:
rpmcliFini(optCon);
return ec;
}