00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "system.h"
00015
00016 #include "rpmio_internal.h"
00017 #include "rpmlib.h"
00018 #include "rpmmacro.h"
00019
00020 #include "md5.h"
00021 #include "misc.h"
00022 #include "rpmlead.h"
00023 #include "signature.h"
00024 #include "debug.h"
00025
00026
00027
00028
00029 typedef int (*md5func)(const char * fn, byte * digest);
00030
00031 int rpmLookupSignatureType(int action)
00032 {
00033 static int disabled = 0;
00034 int rc = 0;
00035
00036 switch (action) {
00037 case RPMLOOKUPSIG_DISABLE:
00038 disabled = -2;
00039 break;
00040 case RPMLOOKUPSIG_ENABLE:
00041 disabled = 0;
00042
00043 case RPMLOOKUPSIG_QUERY:
00044 if (disabled)
00045 break;
00046 { const char *name = rpmExpand("%{?_signature}", NULL);
00047 if (!(name && *name != '\0'))
00048 rc = 0;
00049 else if (!xstrcasecmp(name, "none"))
00050 rc = 0;
00051 else if (!xstrcasecmp(name, "pgp"))
00052 rc = RPMSIGTAG_PGP;
00053 else if (!xstrcasecmp(name, "pgp5"))
00054 rc = RPMSIGTAG_PGP;
00055 else if (!xstrcasecmp(name, "gpg"))
00056 rc = RPMSIGTAG_GPG;
00057 else
00058 rc = -1;
00059 name = _free(name);
00060 } break;
00061 }
00062 return rc;
00063 }
00064
00065
00066
00067
00068 const char * rpmDetectPGPVersion(pgpVersion * pgpVer)
00069 {
00070
00071
00072
00073
00074 static pgpVersion saved_pgp_version = PGP_UNKNOWN;
00075 const char *pgpbin = rpmGetPath("%{?_pgpbin}", NULL);
00076
00077 if (saved_pgp_version == PGP_UNKNOWN) {
00078 char *pgpvbin;
00079 struct stat st;
00080
00081 if (!(pgpbin && pgpbin[0] != '\0')) {
00082 pgpbin = _free(pgpbin);
00083 saved_pgp_version = -1;
00084 return NULL;
00085 }
00086 pgpvbin = (char *)alloca(strlen(pgpbin) + sizeof("v"));
00087 (void)stpcpy(stpcpy(pgpvbin, pgpbin), "v");
00088
00089 if (stat(pgpvbin, &st) == 0)
00090 saved_pgp_version = PGP_5;
00091 else if (stat(pgpbin, &st) == 0)
00092 saved_pgp_version = PGP_2;
00093 else
00094 saved_pgp_version = PGP_NOTDETECTED;
00095 }
00096
00097 if (pgpVer && pgpbin)
00098 *pgpVer = saved_pgp_version;
00099 return pgpbin;
00100 }
00101
00111 static inline rpmRC checkSize(FD_t fd, int siglen, int pad, int datalen)
00112
00113
00114 {
00115 struct stat st;
00116 int delta;
00117 rpmRC rc;
00118
00119 if (fstat(Fileno(fd), &st))
00120 return RPMRC_FAIL;
00121
00122 if (!S_ISREG(st.st_mode)) {
00123 rpmMessage(RPMMESS_DEBUG,
00124 _("file is not regular -- skipping size check\n"));
00125 return RPMRC_OK;
00126 }
00127
00128 delta = (sizeof(struct rpmlead) + siglen + pad + datalen) - st.st_size;
00129 switch (delta) {
00130 case -32:
00131 case 32:
00132 case 0:
00133 rc = RPMRC_OK;
00134 break;
00135 default:
00136 rc = RPMRC_BADSIZE;
00137 break;
00138 }
00139
00140 rpmMessage((rc == RPMRC_OK ? RPMMESS_DEBUG : RPMMESS_WARNING),
00141 _("Expected size: %12d = lead(%d)+sigs(%d)+pad(%d)+data(%d)\n"),
00142 (int)sizeof(struct rpmlead)+siglen+pad+datalen,
00143 (int)sizeof(struct rpmlead), siglen, pad, datalen);
00144 rpmMessage((rc == RPMRC_OK ? RPMMESS_DEBUG : RPMMESS_WARNING),
00145 _(" Actual size: %12d\n"), (int)st.st_size);
00146
00147 return rc;
00148 }
00149
00150 rpmRC rpmReadSignature(FD_t fd, Header * headerp, sigType sig_type)
00151 {
00152 byte buf[2048];
00153 int sigSize, pad;
00154 int_32 type, count;
00155 int_32 *archSize;
00156 Header h = NULL;
00157 rpmRC rc = RPMRC_FAIL;
00158
00159 if (headerp)
00160 *headerp = NULL;
00161
00162 buf[0] = 0;
00163 switch (sig_type) {
00164 case RPMSIGTYPE_NONE:
00165 rpmMessage(RPMMESS_DEBUG, _("No signature\n"));
00166 rc = RPMRC_OK;
00167 break;
00168 case RPMSIGTYPE_PGP262_1024:
00169 rpmMessage(RPMMESS_DEBUG, _("Old PGP signature\n"));
00170
00171 if (timedRead(fd, buf, 256) != 256)
00172 break;
00173 h = headerNew();
00174 (void) headerAddEntry(h, RPMSIGTAG_PGP, RPM_BIN_TYPE, buf, 152);
00175 rc = RPMRC_OK;
00176 break;
00177 case RPMSIGTYPE_MD5:
00178 case RPMSIGTYPE_MD5_PGP:
00179 rpmError(RPMERR_BADSIGTYPE,
00180 _("Old (internal-only) signature! How did you get that!?\n"));
00181 break;
00182 case RPMSIGTYPE_HEADERSIG:
00183 case RPMSIGTYPE_DISABLE:
00184
00185 h = headerRead(fd, HEADER_MAGIC_YES);
00186 if (h == NULL)
00187 break;
00188
00189 rc = RPMRC_OK;
00190 sigSize = headerSizeof(h, HEADER_MAGIC_YES);
00191
00192 pad = (8 - (sigSize % 8)) % 8;
00193 if (sig_type == RPMSIGTYPE_HEADERSIG) {
00194 if (! headerGetEntry(h, RPMSIGTAG_SIZE, &type,
00195 (void **)&archSize, &count))
00196 break;
00197 rc = checkSize(fd, sigSize, pad, *archSize);
00198 }
00199 if (pad && timedRead(fd, buf, pad) != pad)
00200 rc = RPMRC_SHORTREAD;
00201 break;
00202 default:
00203 break;
00204 }
00205
00206 if (headerp && rc == RPMRC_OK)
00207 *headerp = h;
00208 else if (h)
00209 h = headerFree(h);
00210
00211 return rc;
00212 }
00213
00214 int rpmWriteSignature(FD_t fd, Header h)
00215 {
00216 static byte buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
00217 int sigSize, pad;
00218 int rc;
00219
00220 rc = headerWrite(fd, h, HEADER_MAGIC_YES);
00221 if (rc)
00222 return rc;
00223
00224 sigSize = headerSizeof(h, HEADER_MAGIC_YES);
00225 pad = (8 - (sigSize % 8)) % 8;
00226 if (pad) {
00227 if (Fwrite(buf, sizeof(buf[0]), pad, fd) != pad)
00228 rc = 1;
00229 }
00230 rpmMessage(RPMMESS_DEBUG, _("Signature: size(%d)+pad(%d)\n"), sigSize, pad);
00231 return rc;
00232 }
00233
00234 Header rpmNewSignature(void)
00235 {
00236 Header h = headerNew();
00237 return h;
00238 }
00239
00240 Header rpmFreeSignature(Header h)
00241 {
00242 return headerFree(h);
00243 }
00244
00245 static int makePGPSignature(const char * file, void ** sig,
00246 int_32 * size, const char * passPhrase)
00247
00248
00249 {
00250 char * sigfile = alloca(1024);
00251 int pid, status;
00252 int inpipe[2];
00253 struct stat st;
00254 const char * cmd;
00255 char *const *av;
00256 int rc;
00257
00258 (void) stpcpy( stpcpy(sigfile, file), ".sig");
00259
00260 addMacro(NULL, "__plaintext_filename", NULL, file, -1);
00261 addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
00262
00263 inpipe[0] = inpipe[1] = 0;
00264 (void) pipe(inpipe);
00265
00266 if (!(pid = fork())) {
00267 const char *pgp_path = rpmExpand("%{?_pgp_path}", NULL);
00268 const char *path;
00269 pgpVersion pgpVer;
00270
00271 (void) close(STDIN_FILENO);
00272 (void) dup2(inpipe[0], 3);
00273 (void) close(inpipe[1]);
00274
00275 (void) dosetenv("PGPPASSFD", "3", 1);
00276 if (pgp_path && *pgp_path != '\0')
00277 (void) dosetenv("PGPPATH", pgp_path, 1);
00278
00279
00280
00281 if ((path = rpmDetectPGPVersion(&pgpVer)) != NULL) {
00282 switch(pgpVer) {
00283 case PGP_2:
00284 cmd = rpmExpand("%{?__pgp_sign_cmd}", NULL);
00285 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00286 if (!rc)
00287 rc = execve(av[0], av+1, environ);
00288 break;
00289 case PGP_5:
00290 cmd = rpmExpand("%{?__pgp5_sign_cmd}", NULL);
00291 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00292 if (!rc)
00293 rc = execve(av[0], av+1, environ);
00294 break;
00295 case PGP_UNKNOWN:
00296 case PGP_NOTDETECTED:
00297 errno = ENOENT;
00298 break;
00299 }
00300 }
00301 rpmError(RPMERR_EXEC, _("Could not exec %s: %s\n"), "pgp",
00302 strerror(errno));
00303 _exit(RPMERR_EXEC);
00304 }
00305
00306 delMacro(NULL, "__plaintext_filename");
00307 delMacro(NULL, "__signature_filename");
00308
00309 (void) close(inpipe[0]);
00310 if (passPhrase)
00311 (void) write(inpipe[1], passPhrase, strlen(passPhrase));
00312 (void) write(inpipe[1], "\n", 1);
00313 (void) close(inpipe[1]);
00314
00315 (void)waitpid(pid, &status, 0);
00316 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
00317 rpmError(RPMERR_SIGGEN, _("pgp failed\n"));
00318 return 1;
00319 }
00320
00321 if (stat(sigfile, &st)) {
00322
00323 if (sigfile) (void) unlink(sigfile);
00324 rpmError(RPMERR_SIGGEN, _("pgp failed to write signature\n"));
00325 return 1;
00326 }
00327
00328 *size = st.st_size;
00329 rpmMessage(RPMMESS_DEBUG, _("PGP sig size: %d\n"), *size);
00330 *sig = xmalloc(*size);
00331
00332 { FD_t fd;
00333 rc = 0;
00334 fd = Fopen(sigfile, "r.fdio");
00335 if (fd != NULL && !Ferror(fd)) {
00336 rc = timedRead(fd, *sig, *size);
00337 if (sigfile) (void) unlink(sigfile);
00338 (void) Fclose(fd);
00339 }
00340 if (rc != *size) {
00341 *sig = _free(*sig);
00342 rpmError(RPMERR_SIGGEN, _("unable to read the signature\n"));
00343 return 1;
00344 }
00345 }
00346
00347 rpmMessage(RPMMESS_DEBUG, _("Got %d bytes of PGP sig\n"), *size);
00348
00349 return 0;
00350 }
00351
00352
00353
00354
00355
00356
00357 static int makeGPGSignature(const char * file, void ** sig,
00358 int_32 * size, const char * passPhrase)
00359
00360
00361 {
00362 char * sigfile = alloca(1024);
00363 int pid, status;
00364 int inpipe[2];
00365 FILE * fpipe;
00366 struct stat st;
00367 const char * cmd;
00368 char *const *av;
00369 int rc;
00370
00371 (void) stpcpy( stpcpy(sigfile, file), ".sig");
00372
00373 addMacro(NULL, "__plaintext_filename", NULL, file, -1);
00374 addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
00375
00376 inpipe[0] = inpipe[1] = 0;
00377 (void) pipe(inpipe);
00378
00379 if (!(pid = fork())) {
00380 const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
00381
00382 (void) close(STDIN_FILENO);
00383 (void) dup2(inpipe[0], 3);
00384 (void) close(inpipe[1]);
00385
00386 if (gpg_path && *gpg_path != '\0')
00387 (void) dosetenv("GNUPGHOME", gpg_path, 1);
00388
00389 cmd = rpmExpand("%{?__gpg_sign_cmd}", NULL);
00390 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00391 if (!rc)
00392 rc = execve(av[0], av+1, environ);
00393
00394 rpmError(RPMERR_EXEC, _("Could not exec %s: %s\n"), "gpg",
00395 strerror(errno));
00396 _exit(RPMERR_EXEC);
00397 }
00398
00399 delMacro(NULL, "__plaintext_filename");
00400 delMacro(NULL, "__signature_filename");
00401
00402 fpipe = fdopen(inpipe[1], "w");
00403 (void) close(inpipe[0]);
00404 if (fpipe) {
00405 fprintf(fpipe, "%s\n", (passPhrase ? passPhrase : ""));
00406 (void) fclose(fpipe);
00407 }
00408
00409 (void)waitpid(pid, &status, 0);
00410 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
00411 rpmError(RPMERR_SIGGEN, _("gpg failed\n"));
00412 return 1;
00413 }
00414
00415 if (stat(sigfile, &st)) {
00416
00417 if (sigfile) (void) unlink(sigfile);
00418 rpmError(RPMERR_SIGGEN, _("gpg failed to write signature\n"));
00419 return 1;
00420 }
00421
00422 *size = st.st_size;
00423 rpmMessage(RPMMESS_DEBUG, _("GPG sig size: %d\n"), *size);
00424 *sig = xmalloc(*size);
00425
00426 { FD_t fd;
00427 int rc = 0;
00428 fd = Fopen(sigfile, "r.fdio");
00429 if (fd != NULL && !Ferror(fd)) {
00430 rc = timedRead(fd, *sig, *size);
00431 if (sigfile) (void) unlink(sigfile);
00432 (void) Fclose(fd);
00433 }
00434 if (rc != *size) {
00435 *sig = _free(*sig);
00436 rpmError(RPMERR_SIGGEN, _("unable to read the signature\n"));
00437 return 1;
00438 }
00439 }
00440
00441 rpmMessage(RPMMESS_DEBUG, _("Got %d bytes of GPG sig\n"), *size);
00442
00443 return 0;
00444 }
00445
00446 int rpmAddSignature(Header h, const char * file, int_32 sigTag,
00447 const char *passPhrase)
00448 {
00449 struct stat st;
00450 int_32 size;
00451 byte buf[16];
00452 void *sig;
00453 int ret = -1;
00454
00455 switch (sigTag) {
00456 case RPMSIGTAG_SIZE:
00457 (void) stat(file, &st);
00458 size = st.st_size;
00459 ret = 0;
00460 (void) headerAddEntry(h, RPMSIGTAG_SIZE, RPM_INT32_TYPE, &size, 1);
00461 break;
00462 case RPMSIGTAG_MD5:
00463 ret = mdbinfile(file, buf);
00464 if (ret == 0)
00465 (void) headerAddEntry(h, sigTag, RPM_BIN_TYPE, buf, 16);
00466 break;
00467 case RPMSIGTAG_PGP5:
00468 case RPMSIGTAG_PGP:
00469 rpmMessage(RPMMESS_VERBOSE, _("Generating signature using PGP.\n"));
00470 ret = makePGPSignature(file, &sig, &size, passPhrase);
00471 if (ret == 0)
00472 (void) headerAddEntry(h, sigTag, RPM_BIN_TYPE, sig, size);
00473 break;
00474 case RPMSIGTAG_GPG:
00475 rpmMessage(RPMMESS_VERBOSE, _("Generating signature using GPG.\n"));
00476 ret = makeGPGSignature(file, &sig, &size, passPhrase);
00477 if (ret == 0)
00478 (void) headerAddEntry(h, sigTag, RPM_BIN_TYPE, sig, size);
00479 break;
00480 }
00481
00482 return ret;
00483 }
00484
00485 static rpmVerifySignatureReturn
00486 verifySizeSignature(const char * datafile, int_32 size, char * result)
00487
00488
00489 {
00490 struct stat st;
00491
00492 (void) stat(datafile, &st);
00493 if (size != st.st_size) {
00494 sprintf(result, "Header+Archive size mismatch.\n"
00495 "Expected %d, saw %d.\n",
00496 size, (int)st.st_size);
00497 return RPMSIG_BAD;
00498 }
00499
00500 sprintf(result, "Header+Archive size OK: %d bytes\n", size);
00501 return RPMSIG_OK;
00502 }
00503
00504 #define X(_x) (unsigned)((_x) & 0xff)
00505
00506 static rpmVerifySignatureReturn
00507 verifyMD5Signature(const char * datafile, const byte * sig,
00508 char * result, md5func fn)
00509
00510
00511 {
00512 byte md5sum[16];
00513
00514 memset(md5sum, 0, sizeof(md5sum));
00515 (void) fn(datafile, md5sum);
00516 if (memcmp(md5sum, sig, 16)) {
00517 sprintf(result, "MD5 sum mismatch\n"
00518 "Expected: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
00519 "%02x%02x%02x%02x%02x\n"
00520 "Saw : %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
00521 "%02x%02x%02x%02x%02x\n",
00522 X(sig[0]), X(sig[1]), X(sig[2]), X(sig[3]),
00523 X(sig[4]), X(sig[5]), X(sig[6]), X(sig[7]),
00524 X(sig[8]), X(sig[9]), X(sig[10]), X(sig[11]),
00525 X(sig[12]), X(sig[13]), X(sig[14]), X(sig[15]),
00526 X(md5sum[0]), X(md5sum[1]), X(md5sum[2]), X(md5sum[3]),
00527 X(md5sum[4]), X(md5sum[5]), X(md5sum[6]), X(md5sum[7]),
00528 X(md5sum[8]), X(md5sum[9]), X(md5sum[10]), X(md5sum[11]),
00529 X(md5sum[12]), X(md5sum[13]), X(md5sum[14]), X(md5sum[15]) );
00530 return RPMSIG_BAD;
00531 }
00532
00533 sprintf(result, "MD5 sum OK: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
00534 "%02x%02x%02x%02x%02x\n",
00535 X(md5sum[0]), X(md5sum[1]), X(md5sum[2]), X(md5sum[3]),
00536 X(md5sum[4]), X(md5sum[5]), X(md5sum[6]), X(md5sum[7]),
00537 X(md5sum[8]), X(md5sum[9]), X(md5sum[10]), X(md5sum[11]),
00538 X(md5sum[12]), X(md5sum[13]), X(md5sum[14]), X(md5sum[15]) );
00539
00540 return RPMSIG_OK;
00541 }
00542
00543 static rpmVerifySignatureReturn
00544 verifyPGPSignature(const char * datafile, const void * sig, int count,
00545 char * result)
00546
00547
00548 {
00549 int pid, status, outpipe[2];
00550 const char * sigfile = NULL;
00551 byte buf[BUFSIZ];
00552 FILE *file;
00553 int res = RPMSIG_OK;
00554 const char *path;
00555 pgpVersion pgpVer;
00556 const char * cmd;
00557 char *const *av;
00558 int rc;
00559
00560
00561 if ((path = rpmDetectPGPVersion(&pgpVer)) == NULL) {
00562 errno = ENOENT;
00563 rpmError(RPMERR_EXEC, ("Could not exec %s: %s\n"), "pgp",
00564 strerror(errno));
00565 _exit(RPMERR_EXEC);
00566 }
00567
00568
00569
00570
00571
00572 if (pgpVer == PGP_5)
00573 res = RPMSIG_BAD;
00574
00575
00576 #ifdef DYING
00577 { const char *tmppath = rpmGetPath("%{_tmppath}", NULL);
00578 sigfile = tempnam(tmppath, "rpmsig");
00579 tmppath = _free(tmppath);
00580 }
00581 sfd = Fopen(sigfile, "w.fdio");
00582 if (sfd != NULL && !Ferror(sfd)) {
00583 (void) Fwrite(sig, sizeof(char), count, sfd);
00584 (void) Fclose(sfd);
00585 }
00586 #else
00587 { FD_t sfd;
00588 if (!makeTempFile(NULL, &sigfile, &sfd)) {
00589 (void) Fwrite(sig, sizeof(char), count, sfd);
00590 (void) Fclose(sfd);
00591 sfd = NULL;
00592 }
00593 }
00594 #endif
00595 if (sigfile == NULL)
00596 return RPMSIG_BAD;
00597
00598 addMacro(NULL, "__plaintext_filename", NULL, datafile, -1);
00599 addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
00600
00601
00602 outpipe[0] = outpipe[1] = 0;
00603 (void) pipe(outpipe);
00604
00605 if (!(pid = fork())) {
00606 const char *pgp_path = rpmExpand("%{?_pgp_path}", NULL);
00607
00608 (void) close(outpipe[0]);
00609 (void) close(STDOUT_FILENO);
00610 (void) dup2(outpipe[1], STDOUT_FILENO);
00611
00612 if (pgp_path && *pgp_path != '\0')
00613 (void) dosetenv("PGPPATH", pgp_path, 1);
00614
00615 switch (pgpVer) {
00616 case PGP_2:
00617 cmd = rpmExpand("%{?__pgp_verify_cmd}", NULL);
00618 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00619 if (!rc)
00620 rc = execve(av[0], av+1, environ);
00621 break;
00622 case PGP_5:
00623
00624
00625
00626 { int save_stderr = dup(2);
00627 (void) dup2(1, 2);
00628
00629 cmd = rpmExpand("%{?__pgp5_verify_cmd}", NULL);
00630 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00631 if (!rc)
00632 rc = execve(av[0], av+1, environ);
00633
00634
00635 (void) dup2(save_stderr, 2);
00636 (void) close(save_stderr);
00637 } break;
00638 case PGP_UNKNOWN:
00639 case PGP_NOTDETECTED:
00640 break;
00641 }
00642
00643 rpmError(RPMERR_EXEC, _("Could not exec %s: %s\n"), "pgp",
00644 strerror(errno));
00645 _exit(RPMERR_EXEC);
00646 }
00647
00648 delMacro(NULL, "__plaintext_filename");
00649 delMacro(NULL, "__signature_filename");
00650
00651 (void) close(outpipe[1]);
00652 file = fdopen(outpipe[0], "r");
00653 result[0] = '\0';
00654 if (file) {
00655 char *t = result;
00656 int nb = 8*BUFSIZ - 1;
00657 while (fgets(buf, 1024, file)) {
00658 if (strncmp("File '", buf, 6) &&
00659 strncmp("Text is assu", buf, 12) &&
00660 strncmp("This signature applies to another message", buf, 41) &&
00661 buf[0] != '\n') {
00662 nb -= strlen(buf);
00663 if (nb > 0) t = stpncpy(t, buf, nb);
00664 }
00665 if (!strncmp("WARNING: Can't find the right public key", buf, 40))
00666 res = RPMSIG_NOKEY;
00667 else if (!strncmp("Signature by unknown keyid:", buf, 27))
00668 res = RPMSIG_NOKEY;
00669 else if (!strncmp("WARNING: The signing key is not trusted", buf, 39))
00670 res = RPMSIG_NOTTRUSTED;
00671 else if (!strncmp("Good signature", buf, 14))
00672 res = RPMSIG_OK;
00673 }
00674 (void) fclose(file);
00675 *t = '\0';
00676 }
00677
00678 (void) waitpid(pid, &status, 0);
00679 if (sigfile) (void) unlink(sigfile);
00680 sigfile = _free(sigfile);
00681 if (!res && (!WIFEXITED(status) || WEXITSTATUS(status))) {
00682 res = RPMSIG_BAD;
00683 }
00684
00685 return res;
00686 }
00687
00688 static rpmVerifySignatureReturn
00689 do_verifyGPGSignature(const char *gpghome, const char *sigfile, const char *datafile, char *result)
00690
00691
00692 {
00693 int pid, outpipe[2];
00694
00695 if ( !sigfile || !datafile )
00696 return RPMSIG_BAD;
00697
00698
00699 outpipe[0] = outpipe[1] = 0;
00700 pipe(outpipe);
00701
00702 pid = fork();
00703
00704 if ( pid < 0 )
00705 {
00706 rpmError( RPMERR_FORK, _("Couldn't fork %s: %s"), "gpg", strerror(errno) );
00707 return RPMSIG_BAD;
00708 } else
00709 {
00710 if ( !pid )
00711 {
00712
00713 const char * cmd;
00714 char *const *av;
00715 int rc;
00716
00717 close( outpipe[0] );
00718
00719 dup2(outpipe[1], STDERR_FILENO);
00720
00721 addMacro(NULL, "__plaintext_filename", NULL, datafile, -1);
00722 addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
00723
00724 if ( rpm_close_all() ) {
00725 perror( "rpm_close_all" );
00726 _exit( -1 );
00727 }
00728
00729 dosetenv( "LANG", "C", 1 );
00730 dosetenv( "LANGUAGE", "C", 1 );
00731 dosetenv( "LC_ALL", "C", 1 );
00732
00733 if ( gpghome && *gpghome )
00734 dosetenv( "GNUPGHOME", gpghome, 1 );
00735
00736 cmd = rpmExpand("%{?__gpg_verify_cmd}", NULL);
00737 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00738 if (!rc)
00739 rc = execv(av[0], av+1);
00740 rpmError(RPMERR_EXEC, _("Could not exec %s: %s\n"), "gpg",
00741 strerror(errno));
00742 _exit( RPMERR_EXEC );
00743 } else
00744 {
00745
00746 int res = RPMSIG_OK, status;
00747 FILE *file = fdopen( outpipe[0], "r" );
00748 unsigned char buf[BUFSIZ];
00749 const char nokey[] = "gpg: Can't check signature: public key not found";
00750
00751 close(outpipe[1]);
00752 result[0] = '\0';
00753
00754 if ( file )
00755 {
00756 while ( fgets( buf, sizeof(buf), file ) )
00757 {
00758 strcat(result, buf);
00759 if ( !xstrncasecmp( nokey, buf, sizeof(nokey)-1 ) )
00760 res = RPMSIG_NOKEY;
00761 }
00762
00763 fclose(file);
00764 }
00765
00766 while ( waitpid( pid, &status, 0 ) < 0 )
00767 {
00768 if ( EINTR != errno )
00769 {
00770 rpmError( RPMERR_FORK, _("waitpid failure: %s"), strerror(errno) );
00771 return RPMSIG_BAD;
00772 }
00773 }
00774
00775 if ( !res && (!WIFEXITED(status) || WEXITSTATUS(status)) )
00776 res = RPMSIG_BAD;
00777 return res;
00778 }
00779 }
00780 }
00781
00782 static rpmVerifySignatureReturn
00783 verifyGPGSignature(const char * datafile, const void * sig, int count,
00784 char * result)
00785
00786
00787 {
00788 char *sigfile = 0;
00789
00790
00791 { FD_t sfd;
00792 if (!makeTempFile(NULL, &sigfile, &sfd)) {
00793 (void) Fwrite(sig, sizeof(char), count, sfd);
00794 (void) Fclose(sfd);
00795 sfd = NULL;
00796 }
00797 }
00798
00799 if (!sigfile)
00800 {
00801 rpmError(RPMERR_SCRIPT, _("Unable to open temp file."));
00802 return RPMSIG_BAD;
00803 }
00804
00805
00806 {
00807 const char *gpg_path = rpmExpand( "%{?_internal_gpg_path}", NULL );
00808 const char *gpg_home = ( gpg_path && *gpg_path ) ? gpg_path : 0;
00809 rpmVerifySignatureReturn res = gpg_home ?
00810 do_verifyGPGSignature( gpg_home, sigfile, datafile, result ) : RPMSIG_NOKEY;
00811 gpg_path = _free( gpg_path );
00812
00813 if ( RPMSIG_NOKEY == res )
00814 {
00815 gpg_path = rpmExpand( "%{?_gpg_path}", NULL );
00816 gpg_home = ( gpg_path && *gpg_path ) ? gpg_path : 0;
00817 res = do_verifyGPGSignature( gpg_home, sigfile, datafile, result );
00818 gpg_path = _free( gpg_path );
00819 }
00820
00821 unlink(sigfile);
00822 return res;
00823 }
00824 }
00825
00826 static int checkPassPhrase(const char * passPhrase, const int sigTag)
00827
00828
00829 {
00830 int passPhrasePipe[2];
00831 int pid, status;
00832 int fd;
00833 const char * cmd;
00834 char *const *av;
00835 int rc;
00836
00837 passPhrasePipe[0] = passPhrasePipe[1] = 0;
00838 (void) pipe(passPhrasePipe);
00839 if (!(pid = fork())) {
00840 (void) close(STDIN_FILENO);
00841 (void) close(STDOUT_FILENO);
00842 (void) close(passPhrasePipe[1]);
00843 if (! rpmIsVerbose()) {
00844 (void) close(STDERR_FILENO);
00845 }
00846 if ((fd = open("/dev/null", O_RDONLY)) != STDIN_FILENO) {
00847 (void) dup2(fd, STDIN_FILENO);
00848 (void) close(fd);
00849 }
00850 if ((fd = open("/dev/null", O_WRONLY)) != STDOUT_FILENO) {
00851 (void) dup2(fd, STDOUT_FILENO);
00852 (void) close(fd);
00853 }
00854 (void) dup2(passPhrasePipe[0], 3);
00855
00856 switch (sigTag) {
00857 case RPMSIGTAG_GPG:
00858 { const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
00859
00860 if (gpg_path && *gpg_path != '\0')
00861 (void) dosetenv("GNUPGHOME", gpg_path, 1);
00862
00863 cmd = rpmExpand("%{?__gpg_check_password_cmd}", NULL);
00864 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00865 if (!rc)
00866 rc = execve(av[0], av+1, environ);
00867
00868 rpmError(RPMERR_EXEC, _("Could not exec %s: %s\n"), "gpg",
00869 strerror(errno));
00870 _exit(RPMERR_EXEC);
00871 } break;
00872 case RPMSIGTAG_PGP5:
00873 case RPMSIGTAG_PGP:
00874 { const char *pgp_path = rpmExpand("%{?_pgp_path}", NULL);
00875 const char *path;
00876 pgpVersion pgpVer;
00877
00878 (void) dosetenv("PGPPASSFD", "3", 1);
00879 if (pgp_path && *pgp_path != '\0')
00880 (void) dosetenv("PGPPATH", pgp_path, 1);
00881
00882 if ((path = rpmDetectPGPVersion(&pgpVer)) != NULL) {
00883 switch(pgpVer) {
00884 case PGP_2:
00885 cmd = rpmExpand("%{?__pgp_check_password_cmd}", NULL);
00886 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00887 if (!rc)
00888 rc = execve(av[0], av+1, environ);
00889 break;
00890 case PGP_5:
00891 cmd = rpmExpand("%{?__pgp5_check_password_cmd}", NULL);
00892 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00893 if (!rc)
00894 rc = execve(av[0], av+1, environ);
00895 break;
00896 case PGP_UNKNOWN:
00897 case PGP_NOTDETECTED:
00898 break;
00899 }
00900 }
00901 rpmError(RPMERR_EXEC, _("Could not exec %s: %s\n"), "pgp",
00902 strerror(errno));
00903 _exit(RPMERR_EXEC);
00904 } break;
00905 default:
00906 rpmError(RPMERR_SIGGEN, _("Invalid %%_signature spec in macro file\n"));
00907 _exit(RPMERR_SIGGEN);
00908 break;
00909 }
00910 }
00911
00912 (void) close(passPhrasePipe[0]);
00913 (void) write(passPhrasePipe[1], passPhrase, strlen(passPhrase));
00914 (void) write(passPhrasePipe[1], "\n", 1);
00915 (void) close(passPhrasePipe[1]);
00916
00917 (void)waitpid(pid, &status, 0);
00918 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
00919 return 1;
00920 }
00921
00922
00923 return 0;
00924 }
00925
00926 char * rpmGetPassPhrase(const char * prompt, const int sigTag)
00927 {
00928 char *pass;
00929 int aok;
00930
00931 switch (sigTag) {
00932 case RPMSIGTAG_GPG:
00933 { const char *name = rpmExpand("%{?_gpg_name}", NULL);
00934 aok = (name && *name != '\0');
00935 name = _free(name);
00936 }
00937 if (!aok) {
00938 rpmError(RPMERR_SIGGEN,
00939 _("You must set \"%%_gpg_name\" in your macro file\n"));
00940 return NULL;
00941 }
00942 break;
00943 case RPMSIGTAG_PGP5:
00944 case RPMSIGTAG_PGP:
00945 { const char *name = rpmExpand("%{?_pgp_name}", NULL);
00946 aok = (name && *name != '\0');
00947 name = _free(name);
00948 }
00949 if (!aok) {
00950 rpmError(RPMERR_SIGGEN,
00951 _("You must set \"%%_pgp_name\" in your macro file\n"));
00952 return NULL;
00953 }
00954 break;
00955 default:
00956
00957
00958
00959 rpmError(RPMERR_SIGGEN, _("Invalid %%_signature spec in macro file\n"));
00960 return NULL;
00961 break;
00962 }
00963
00964 pass = getpass( (prompt ? prompt : "") ) ;
00965
00966 if (checkPassPhrase(pass, sigTag))
00967 return NULL;
00968
00969 return pass;
00970 }
00971
00972 rpmVerifySignatureReturn
00973 rpmVerifySignature(const char * file, int_32 sigTag, const void * sig,
00974 int count, char * result)
00975 {
00976 rpmVerifySignatureReturn res;
00977
00978 switch (sigTag) {
00979 case RPMSIGTAG_SIZE:
00980 res = verifySizeSignature(file, *(int_32 *)sig, result);
00981 break;
00982 case RPMSIGTAG_MD5:
00983 res = verifyMD5Signature(file, sig, result, mdbinfile);
00984 break;
00985 case RPMSIGTAG_PGP5:
00986 case RPMSIGTAG_PGP:
00987 res = verifyPGPSignature(file, sig, count, result);
00988 break;
00989 case RPMSIGTAG_GPG:
00990 res = verifyGPGSignature(file, sig, count, result);
00991 break;
00992 case RPMSIGTAG_LEMD5_1:
00993 case RPMSIGTAG_LEMD5_2:
00994 sprintf(result, _("Broken MD5 digest: UNSUPPORTED\n"));
00995 res = RPMSIG_UNKNOWN;
00996 break;
00997 default:
00998 sprintf(result, "Do not know how to verify sig type %d\n", sigTag);
00999 res = RPMSIG_UNKNOWN;
01000 break;
01001 }
01002 return res;
01003 }