csomh / source-git / rpm

Forked from source-git/rpm 4 years ago
Clone
2ff057
#include "system.h"
2ff057
#include <errno.h>
2ff057
#include <sys/wait.h>
2ff057
#include <termios.h>
2ff057
2ff057
#include <popt.h>
2ff057
#include <rpm/rpmcli.h>
2ff057
#include <rpm/rpmsign.h>
2ff057
#include "cliutils.h"
2ff057
#include "debug.h"
2ff057
2ff057
enum modes {
2ff057
    MODE_NONE    = 0,
2ff057
    MODE_ADDSIGN = (1 << 0),
2ff057
    MODE_RESIGN  = (1 << 1),
2ff057
    MODE_DELSIGN = (1 << 2),
2ff057
};
2ff057
2ff057
static int mode = MODE_NONE;
2ff057
2ff057
#ifdef WITH_IMAEVM
2ff057
static int signfiles = 0, fskpass = 0;
2ff057
static char * fileSigningKey = NULL;
2ff057
#endif
2ff057
2ff057
static struct rpmSignArgs sargs = {NULL, 0, 0};
2ff057
2ff057
static struct poptOption signOptsTable[] = {
2ff057
    { "addsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_ADDSIGN,
2ff057
	N_("sign package(s)"), NULL },
2ff057
    { "resign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_RESIGN,
2ff057
	N_("sign package(s) (identical to --addsign)"), NULL },
2ff057
    { "delsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_DELSIGN,
2ff057
	N_("delete package signatures"), NULL },
2ff057
#ifdef WITH_IMAEVM
2ff057
    { "signfiles", '\0', POPT_ARG_NONE, &signfiles, 0,
2ff057
	N_("sign package(s) files"), NULL},
2ff057
    { "fskpath", '\0', POPT_ARG_STRING, &fileSigningKey, 0,
2ff057
	N_("use file signing key <key>"),
2ff057
	N_("<key>") },
2ff057
    { "fskpass", '\0', POPT_ARG_NONE, &fskpass, 0,
2ff057
	N_("prompt for file signing key password"), NULL},
2ff057
#endif
2ff057
    POPT_TABLEEND
2ff057
};
2ff057
2ff057
static struct poptOption optionsTable[] = {
2ff057
    { NULL, '\0', POPT_ARG_INCLUDE_TABLE, signOptsTable, 0,
2ff057
	N_("Signature options:"), NULL },
2ff057
    { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
2ff057
	N_("Common options for all rpm modes and executables:"), NULL },
2ff057
2ff057
    POPT_AUTOALIAS
2ff057
    POPT_AUTOHELP
2ff057
    POPT_TABLEEND
2ff057
};
2ff057
2ff057
#ifdef WITH_IMAEVM
2ff057
static char *get_fskpass(void)
2ff057
{
2ff057
    struct termios flags, tmp_flags;
2ff057
    int passlen = 64;
2ff057
    char *password = xmalloc(passlen);
2ff057
    char *pwd = NULL;
2ff057
2ff057
    tcgetattr(fileno(stdin), &flags);
2ff057
    tmp_flags = flags;
2ff057
    tmp_flags.c_lflag &= ~ECHO;
2ff057
    tmp_flags.c_lflag |= ECHONL;
2ff057
2ff057
    if (tcsetattr(fileno(stdin), TCSANOW, &tmp_flags) != 0) {
2ff057
	perror("tcsetattr");
2ff057
	goto exit;
2ff057
    }
2ff057
2ff057
    printf("PEM password: ");
2ff057
    pwd = fgets(password, passlen, stdin);
2ff057
2ff057
    if (tcsetattr(fileno(stdin), TCSANOW, &flags) != 0) {
2ff057
	perror("tcsetattr");
2ff057
	pwd = NULL;
2ff057
	goto exit;
2ff057
    }
2ff057
2ff057
exit:
2ff057
    if (pwd)
2ff057
	pwd[strlen(pwd) - 1] = '\0';  /* remove newline */
2ff057
    else
2ff057
	free(password);
2ff057
    return pwd;
2ff057
}
2ff057
#endif
2ff057
2ff057
/* TODO: permit overriding macro setup on the command line */
2ff057
static int doSign(poptContext optCon, struct rpmSignArgs *sargs)
2ff057
{
2ff057
    int rc = EXIT_FAILURE;
2ff057
    char * name = rpmExpand("%{?_gpg_name}", NULL);
2ff057
2ff057
    if (rstreq(name, "")) {
2ff057
	fprintf(stderr, _("You must set \"%%_gpg_name\" in your macro file\n"));
2ff057
	goto exit;
2ff057
    }
2ff057
2ff057
#ifdef WITH_IMAEVM
2ff057
    if (fileSigningKey) {
2ff057
	rpmPushMacro(NULL, "_file_signing_key", NULL, fileSigningKey, RMIL_GLOBAL);
2ff057
    }
2ff057
2ff057
    if (signfiles) {
2ff057
	char *fileSigningKeyPassword = NULL;
2ff057
	char *key = rpmExpand("%{?_file_signing_key}", NULL);
2ff057
	if (rstreq(key, "")) {
2ff057
	    fprintf(stderr, _("You must set \"%%_file_signing_key\" in your macro file or on the command line with --fskpath\n"));
2ff057
	    goto exit;
2ff057
	}
2ff057
2ff057
	if (fskpass) {
2ff057
	    fileSigningKeyPassword = get_fskpass();
2ff057
	}
2ff057
2ff057
	if (fileSigningKeyPassword) {
2ff057
	    rpmPushMacro(NULL, "_file_signing_key_password", NULL,
2ff057
			fileSigningKeyPassword, RMIL_CMDLINE);
2ff057
	    memset(fileSigningKeyPassword, 0, strlen(fileSigningKeyPassword));
2ff057
	    free(fileSigningKeyPassword);
2ff057
	}
2ff057
2ff057
	sargs->signfiles = 1;
2ff057
	free(key);
2ff057
    }
2ff057
#endif
2ff057
2ff057
    const char *arg;
2ff057
    rc = 0;
2ff057
    while ((arg = poptGetArg(optCon)) != NULL) {
Panu Matilainen 4f16af
	if (rpmPkgSign(arg, sargs) < 0)
Panu Matilainen 4f16af
	    rc++;
2ff057
    }
2ff057
2ff057
exit:
2ff057
    free(name);
2ff057
    return rc;
2ff057
}
2ff057
2ff057
int main(int argc, char *argv[])
2ff057
{
2ff057
    int ec = EXIT_FAILURE;
2ff057
    poptContext optCon = NULL;
2ff057
    const char *arg;
2ff057
    
2ff057
    xsetprogname(argv[0]); /* Portability call -- see system.h */
2ff057
2ff057
    optCon = rpmcliInit(argc, argv, optionsTable);
2ff057
2ff057
    if (argc <= 1) {
2ff057
	printUsage(optCon, stderr, 0);
2ff057
	goto exit;
2ff057
    }
2ff057
2ff057
    if (poptPeekArg(optCon) == NULL) {
2ff057
	argerror(_("no arguments given"));
2ff057
    }
2ff057
2ff057
#ifdef WITH_IMAEVM
2ff057
    if (fileSigningKey && !signfiles) {
2ff057
	argerror(_("--fskpath may only be specified when signing files"));
2ff057
    }
2ff057
#endif
2ff057
2ff057
    switch (mode) {
2ff057
    case MODE_ADDSIGN:
2ff057
    case MODE_RESIGN:
2ff057
	ec = doSign(optCon, &sargs);
2ff057
	break;
2ff057
    case MODE_DELSIGN:
2ff057
	ec = 0;
2ff057
	while ((arg = poptGetArg(optCon)) != NULL) {
Panu Matilainen 4f16af
	    if (rpmPkgDelSign(arg, &sargs) < 0)
Panu Matilainen 4f16af
		ec++;
2ff057
	}
2ff057
	break;
2ff057
    case MODE_NONE:
2ff057
	printUsage(optCon, stderr, 0);
2ff057
	break;
2ff057
    default:
2ff057
	argerror(_("only one major mode may be specified"));
2ff057
	break;
2ff057
    }
2ff057
2ff057
exit:
2ff057
    rpmcliFini(optCon);
Panu Matilainen 4f16af
    return RETVAL(ec);
2ff057
}