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