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