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