00001 #include "system.h"
00002 #include <errno.h>
00003 #include <sys/wait.h>
00004
00005 #include <popt.h>
00006 #include <rpm/rpmcli.h>
00007 #include <rpm/rpmsign.h>
00008 #include "cliutils.h"
00009 #include "debug.h"
00010
00011 #if !defined(__GLIBC__) && !defined(__APPLE__)
00012 char ** environ = NULL;
00013 #endif
00014
00015 enum modes {
00016 MODE_ADDSIGN = (1 << 0),
00017 MODE_RESIGN = (1 << 1),
00018 MODE_DELSIGN = (1 << 2),
00019 };
00020
00021 static int mode = 0;
00022
00023 static struct poptOption signOptsTable[] = {
00024 { "addsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_ADDSIGN,
00025 N_("sign package(s)"), NULL },
00026 { "resign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_RESIGN,
00027 N_("sign package(s) (identical to --addsign)"), NULL },
00028 { "delsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_DELSIGN,
00029 N_("delete package signatures"), NULL },
00030 POPT_TABLEEND
00031 };
00032
00033 static struct poptOption optionsTable[] = {
00034 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, signOptsTable, 0,
00035 N_("Signature options:"), NULL },
00036 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
00037 N_("Common options for all rpm modes and executables:"), NULL },
00038
00039 POPT_AUTOALIAS
00040 POPT_AUTOHELP
00041 POPT_TABLEEND
00042 };
00043
00044 static int checkPassPhrase(const char * passPhrase)
00045 {
00046 int passPhrasePipe[2];
00047 int pid, status;
00048 int rc;
00049 int xx;
00050
00051 if (passPhrase == NULL)
00052 return -1;
00053
00054 passPhrasePipe[0] = passPhrasePipe[1] = 0;
00055 xx = pipe(passPhrasePipe);
00056 if (!(pid = fork())) {
00057 char * cmd, * gpg_path;
00058 char *const *av;
00059 int fdno;
00060
00061 xx = close(STDIN_FILENO);
00062 xx = close(STDOUT_FILENO);
00063 xx = close(passPhrasePipe[1]);
00064 if ((fdno = open("/dev/null", O_RDONLY)) != STDIN_FILENO) {
00065 xx = dup2(fdno, STDIN_FILENO);
00066 xx = close(fdno);
00067 }
00068 if ((fdno = open("/dev/null", O_WRONLY)) != STDOUT_FILENO) {
00069 xx = dup2(fdno, STDOUT_FILENO);
00070 xx = close(fdno);
00071 }
00072 xx = dup2(passPhrasePipe[0], 3);
00073
00074 unsetenv("MALLOC_CHECK_");
00075 gpg_path = rpmExpand("%{?_gpg_path}", NULL);
00076
00077 if (!rstreq(gpg_path, ""))
00078 setenv("GNUPGHOME", gpg_path, 1);
00079
00080 cmd = rpmExpand("%{?__gpg_check_password_cmd}", NULL);
00081 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00082 if (!rc)
00083 rc = execve(av[0], av+1, environ);
00084
00085 fprintf(stderr, _("Could not exec %s: %s\n"), "gpg",
00086 strerror(errno));
00087 _exit(EXIT_FAILURE);
00088 }
00089
00090 xx = close(passPhrasePipe[0]);
00091 xx = write(passPhrasePipe[1], passPhrase, strlen(passPhrase));
00092 xx = write(passPhrasePipe[1], "\n", 1);
00093 xx = close(passPhrasePipe[1]);
00094
00095 (void) waitpid(pid, &status, 0);
00096
00097 return ((WIFEXITED(status) && WEXITSTATUS(status) == 0)) ? 0 : 1;
00098 }
00099
00100
00101 static int doSign(poptContext optCon)
00102 {
00103 int rc = EXIT_FAILURE;
00104 char * passPhrase = NULL;
00105 char * name = rpmExpand("%{?_gpg_name}", NULL);
00106
00107 if (rstreq(name, "")) {
00108 fprintf(stderr, _("You must set \"%%_gpg_name\" in your macro file\n"));
00109 goto exit;
00110 }
00111
00112
00113 passPhrase = getpass(_("Enter pass phrase: "));
00114 passPhrase = (passPhrase != NULL) ? rstrdup(passPhrase) : NULL;
00115 if (checkPassPhrase(passPhrase) == 0) {
00116 const char *arg;
00117 fprintf(stderr, _("Pass phrase is good.\n"));
00118 rc = 0;
00119 while ((arg = poptGetArg(optCon)) != NULL) {
00120 rc += rpmPkgSign(arg, NULL, passPhrase);
00121 }
00122 } else {
00123 fprintf(stderr, _("Pass phrase check failed\n"));
00124 }
00125
00126 exit:
00127 free(passPhrase);
00128 free(name);
00129 return rc;
00130 }
00131
00132 int main(int argc, char *argv[])
00133 {
00134 int ec = EXIT_FAILURE;
00135 poptContext optCon = rpmcliInit(argc, argv, optionsTable);
00136 const char *arg;
00137
00138 if (argc <= 1) {
00139 printUsage(optCon, stderr, 0);
00140 goto exit;
00141 }
00142
00143 if (poptPeekArg(optCon) == NULL) {
00144 argerror(_("no arguments given"));
00145 }
00146
00147 switch (mode) {
00148 case MODE_ADDSIGN:
00149 case MODE_RESIGN:
00150 ec = doSign(optCon);
00151 break;
00152 case MODE_DELSIGN:
00153 ec = 0;
00154 while ((arg = poptGetArg(optCon)) != NULL) {
00155 ec += rpmPkgDelSign(arg);
00156 }
00157 break;
00158 default:
00159 argerror(_("only one major mode may be specified"));
00160 break;
00161 }
00162
00163 exit:
00164 rpmcliFini(optCon);
00165 return ec;
00166 }