rpmsign.c 4.4 KB
Newer Older
1 2 3
#include "system.h"
#include <errno.h>
#include <sys/wait.h>
4
#include <termios.h>
5 6 7 8 9 10 11 12

#include <popt.h>
#include <rpm/rpmcli.h>
#include <rpm/rpmsign.h>
#include "cliutils.h"
#include "debug.h"

enum modes {
13
    MODE_NONE    = 0,
14 15 16 17 18
    MODE_ADDSIGN = (1 << 0),
    MODE_RESIGN  = (1 << 1),
    MODE_DELSIGN = (1 << 2),
};

19
static int mode = MODE_NONE;
20

21
#ifdef WITH_IMAEVM
22 23
static int signfiles = 0, fskpass = 0;
static char * fileSigningKey = NULL;
24 25 26
#endif

static struct rpmSignArgs sargs = {NULL, 0, 0};
27

28 29 30 31 32 33 34
static struct poptOption signOptsTable[] = {
    { "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 },
35
#ifdef WITH_IMAEVM
36 37 38 39 40 41 42
    { "signfiles", '\0', POPT_ARG_NONE, &signfiles, 0,
	N_("sign package(s) files"), NULL},
    { "fskpath", '\0', POPT_ARG_STRING, &fileSigningKey, 0,
	N_("use file signing key <key>"),
	N_("<key>") },
    { "fskpass", '\0', POPT_ARG_NONE, &fskpass, 0,
	N_("prompt for file signing key password"), NULL},
43
#endif
44 45 46 47 48 49 50 51 52 53 54 55 56 57
    POPT_TABLEEND
};

static struct poptOption optionsTable[] = {
    { NULL, '\0', POPT_ARG_INCLUDE_TABLE, signOptsTable, 0,
	N_("Signature options:"), NULL },
    { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
	N_("Common options for all rpm modes and executables:"), NULL },

    POPT_AUTOALIAS
    POPT_AUTOHELP
    POPT_TABLEEND
};

58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
#ifdef WITH_IMAEVM
static char *get_fskpass(void)
{
    struct termios flags, tmp_flags;
    int passlen = 64;
    char *password = xmalloc(passlen);
    char *pwd = NULL;

    tcgetattr(fileno(stdin), &flags);
    tmp_flags = flags;
    tmp_flags.c_lflag &= ~ECHO;
    tmp_flags.c_lflag |= ECHONL;

    if (tcsetattr(fileno(stdin), TCSANOW, &tmp_flags) != 0) {
	perror("tcsetattr");
	goto exit;
    }

    printf("PEM password: ");
    pwd = fgets(password, passlen, stdin);

    if (tcsetattr(fileno(stdin), TCSANOW, &flags) != 0) {
	perror("tcsetattr");
	pwd = NULL;
	goto exit;
    }

exit:
    if (pwd)
	pwd[strlen(pwd) - 1] = '\0';  /* remove newline */
    else
	free(password);
    return pwd;
}
#endif

94
/* TODO: permit overriding macro setup on the command line */
95
static int doSign(poptContext optCon, struct rpmSignArgs *sargs)
96 97 98 99 100 101 102 103 104
{
    int rc = EXIT_FAILURE;
    char * name = rpmExpand("%{?_gpg_name}", NULL);

    if (rstreq(name, "")) {
	fprintf(stderr, _("You must set \"%%_gpg_name\" in your macro file\n"));
	goto exit;
    }

105
#ifdef WITH_IMAEVM
106
    if (fileSigningKey) {
107
	rpmPushMacro(NULL, "_file_signing_key", NULL, fileSigningKey, RMIL_GLOBAL);
108 109 110
    }

    if (signfiles) {
111 112
	char *fileSigningKeyPassword = NULL;
	char *key = rpmExpand("%{?_file_signing_key}", NULL);
113
	if (rstreq(key, "")) {
114
	    fprintf(stderr, _("You must set \"%%_file_signing_key\" in your macro file or on the command line with --fskpath\n"));
115 116 117 118 119 120 121 122
	    goto exit;
	}

	if (fskpass) {
	    fileSigningKeyPassword = get_fskpass();
	}

	if (fileSigningKeyPassword) {
123 124
	    rpmPushMacro(NULL, "_file_signing_key_password", NULL,
			fileSigningKeyPassword, RMIL_CMDLINE);
125 126
	    memset(fileSigningKeyPassword, 0, strlen(fileSigningKeyPassword));
	    free(fileSigningKeyPassword);
127
	}
128

129 130
	sargs->signfiles = 1;
	free(key);
131
    }
132
#endif
133 134 135 136

    const char *arg;
    rc = 0;
    while ((arg = poptGetArg(optCon)) != NULL) {
137
	rc += rpmPkgSign(arg, sargs);
138 139 140 141 142 143 144 145 146 147
    }

exit:
    free(name);
    return rc;
}

int main(int argc, char *argv[])
{
    int ec = EXIT_FAILURE;
148
    poptContext optCon = NULL;
149 150
    const char *arg;
    
151 152 153 154
    xsetprogname(argv[0]); /* Portability call -- see system.h */

    optCon = rpmcliInit(argc, argv, optionsTable);

155 156 157 158 159 160 161 162 163
    if (argc <= 1) {
	printUsage(optCon, stderr, 0);
	goto exit;
    }

    if (poptPeekArg(optCon) == NULL) {
	argerror(_("no arguments given"));
    }

164
#ifdef WITH_IMAEVM
165 166 167
    if (fileSigningKey && !signfiles) {
	argerror(_("--fskpath may only be specified when signing files"));
    }
168
#endif
169

170 171 172
    switch (mode) {
    case MODE_ADDSIGN:
    case MODE_RESIGN:
173
	ec = doSign(optCon, &sargs);
174 175 176 177
	break;
    case MODE_DELSIGN:
	ec = 0;
	while ((arg = poptGetArg(optCon)) != NULL) {
178
	    ec += rpmPkgDelSign(arg, &sargs);
179 180
	}
	break;
181 182 183
    case MODE_NONE:
	printUsage(optCon, stderr, 0);
	break;
184 185 186 187 188 189 190 191 192
    default:
	argerror(_("only one major mode may be specified"));
	break;
    }

exit:
    rpmcliFini(optCon);
    return ec;
}