00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifdef __FreeBSD__
00015 extern char **environ;
00016 #endif
00017
00018 #include "system.h"
00019
00020 #include "rpmio_internal.h"
00021 #include <rpmlib.h>
00022 #include <rpmmacro.h>
00023
00024 #include "md5.h"
00025 #include "misc.h"
00026 #include "rpmlead.h"
00027 #include "signature.h"
00028 #include "debug.h"
00029
00030
00031
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 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_DEBUG),
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_DEBUG),
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] = { 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 while (fgets(buf, 1024, file)) {
00656 if (strncmp("File '", buf, 6) &&
00657 strncmp("Text is assu", buf, 12) &&
00658 strncmp("This signature applies to another message", buf, 41) &&
00659 buf[0] != '\n') {
00660 strcat(result, buf);
00661 }
00662 if (!strncmp("WARNING: Can't find the right public key", buf, 40))
00663 res = RPMSIG_NOKEY;
00664 else if (!strncmp("Signature by unknown keyid:", buf, 27))
00665 res = RPMSIG_NOKEY;
00666 else if (!strncmp("WARNING: The signing key is not trusted", buf, 39))
00667 res = RPMSIG_NOTTRUSTED;
00668 else if (!strncmp("Good signature", buf, 14))
00669 res = RPMSIG_OK;
00670 }
00671 (void) fclose(file);
00672 }
00673
00674 (void) waitpid(pid, &status, 0);
00675 if (sigfile) (void) unlink(sigfile);
00676 sigfile = _free(sigfile);
00677 if (!res && (!WIFEXITED(status) || WEXITSTATUS(status))) {
00678 res = RPMSIG_BAD;
00679 }
00680
00681 return res;
00682 }
00683
00684 static rpmVerifySignatureReturn
00685 verifyGPGSignature(const char * datafile, const void * sig, int count,
00686 char * result)
00687
00688
00689 {
00690 int pid, status, outpipe[2];
00691 const char * sigfile = NULL;
00692 byte buf[BUFSIZ];
00693 FILE *file;
00694 int res = RPMSIG_OK;
00695 const char * cmd;
00696 char *const *av;
00697 int rc;
00698
00699
00700 #ifdef DYING
00701 { const char *tmppath = rpmGetPath("%{_tmppath}", NULL);
00702 sigfile = tempnam(tmppath, "rpmsig");
00703 tmppath = _free(tmppath);
00704 }
00705 sfd = Fopen(sigfile, "w.fdio");
00706 if (sfd != NULL && !Ferror(sfd)) {
00707 (void) Fwrite(sig, sizeof(char), count, sfd);
00708 (void) Fclose(sfd);
00709 }
00710 #else
00711 { FD_t sfd;
00712 if (!makeTempFile(NULL, &sigfile, &sfd)) {
00713 (void) Fwrite(sig, sizeof(char), count, sfd);
00714 (void) Fclose(sfd);
00715 sfd = NULL;
00716 }
00717 }
00718 #endif
00719 if (sigfile == NULL)
00720 return RPMSIG_BAD;
00721
00722 addMacro(NULL, "__plaintext_filename", NULL, datafile, -1);
00723 addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
00724
00725
00726 outpipe[0] = outpipe[1] = 0;
00727 (void) pipe(outpipe);
00728
00729 if (!(pid = fork())) {
00730 const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
00731
00732 (void) close(outpipe[0]);
00733
00734 (void) dup2(outpipe[1], STDERR_FILENO);
00735
00736 if (gpg_path && *gpg_path != '\0')
00737 (void) dosetenv("GNUPGHOME", gpg_path, 1);
00738
00739 cmd = rpmExpand("%{?__gpg_verify_cmd}", NULL);
00740 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00741 if (!rc)
00742 rc = execve(av[0], av+1, environ);
00743
00744 rpmError(RPMERR_EXEC, _("Could not exec %s: %s\n"), "gpg",
00745 strerror(errno));
00746 _exit(RPMERR_EXEC);
00747 }
00748
00749 delMacro(NULL, "__plaintext_filename");
00750 delMacro(NULL, "__signature_filename");
00751
00752 (void) close(outpipe[1]);
00753 file = fdopen(outpipe[0], "r");
00754 result[0] = '\0';
00755 if (file) {
00756 while (fgets(buf, 1024, file)) {
00757 strcat(result, buf);
00758 if (!xstrncasecmp("gpg: Can't check signature: Public key not found", buf, 48)) {
00759 res = RPMSIG_NOKEY;
00760 }
00761 }
00762 (void) fclose(file);
00763 }
00764
00765 (void) waitpid(pid, &status, 0);
00766 if (sigfile) (void) unlink(sigfile);
00767 sigfile = _free(sigfile);
00768 if (!res && (!WIFEXITED(status) || WEXITSTATUS(status))) {
00769 res = RPMSIG_BAD;
00770 }
00771
00772 return res;
00773 }
00774
00775 static int checkPassPhrase(const char * passPhrase, const int sigTag)
00776
00777
00778 {
00779 int passPhrasePipe[2];
00780 int pid, status;
00781 int fd;
00782 const char * cmd;
00783 char *const *av;
00784 int rc;
00785
00786 passPhrasePipe[0] = passPhrasePipe[1] = 0;
00787 (void) pipe(passPhrasePipe);
00788 if (!(pid = fork())) {
00789 (void) close(STDIN_FILENO);
00790 (void) close(STDOUT_FILENO);
00791 (void) close(passPhrasePipe[1]);
00792 if (! rpmIsVerbose()) {
00793 (void) close(STDERR_FILENO);
00794 }
00795 if ((fd = open("/dev/null", O_RDONLY)) != STDIN_FILENO) {
00796 (void) dup2(fd, STDIN_FILENO);
00797 (void) close(fd);
00798 }
00799 if ((fd = open("/dev/null", O_WRONLY)) != STDOUT_FILENO) {
00800 (void) dup2(fd, STDOUT_FILENO);
00801 (void) close(fd);
00802 }
00803 (void) dup2(passPhrasePipe[0], 3);
00804
00805 switch (sigTag) {
00806 case RPMSIGTAG_GPG:
00807 { const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
00808
00809 if (gpg_path && *gpg_path != '\0')
00810 (void) dosetenv("GNUPGHOME", gpg_path, 1);
00811
00812 cmd = rpmExpand("%{?__gpg_check_password_cmd}", NULL);
00813 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00814 if (!rc)
00815 rc = execve(av[0], av+1, environ);
00816
00817 rpmError(RPMERR_EXEC, _("Could not exec %s: %s\n"), "gpg",
00818 strerror(errno));
00819 _exit(RPMERR_EXEC);
00820 } break;
00821 case RPMSIGTAG_PGP5:
00822 case RPMSIGTAG_PGP:
00823 { const char *pgp_path = rpmExpand("%{?_pgp_path}", NULL);
00824 const char *path;
00825 pgpVersion pgpVer;
00826
00827 (void) dosetenv("PGPPASSFD", "3", 1);
00828 if (pgp_path && *pgp_path != '\0')
00829 (void) dosetenv("PGPPATH", pgp_path, 1);
00830
00831 if ((path = rpmDetectPGPVersion(&pgpVer)) != NULL) {
00832 switch(pgpVer) {
00833 case PGP_2:
00834 cmd = rpmExpand("%{?__pgp_check_password_cmd}", NULL);
00835 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00836 if (!rc)
00837 rc = execve(av[0], av+1, environ);
00838 break;
00839 case PGP_5:
00840 cmd = rpmExpand("%{?__pgp5_check_password_cmd}", NULL);
00841 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
00842 if (!rc)
00843 rc = execve(av[0], av+1, environ);
00844 break;
00845 case PGP_UNKNOWN:
00846 case PGP_NOTDETECTED:
00847 break;
00848 }
00849 }
00850 rpmError(RPMERR_EXEC, _("Could not exec %s: %s\n"), "pgp",
00851 strerror(errno));
00852 _exit(RPMERR_EXEC);
00853 } break;
00854 default:
00855 rpmError(RPMERR_SIGGEN, _("Invalid %%_signature spec in macro file\n"));
00856 _exit(RPMERR_SIGGEN);
00857 break;
00858 }
00859 }
00860
00861 (void) close(passPhrasePipe[0]);
00862 (void) write(passPhrasePipe[1], passPhrase, strlen(passPhrase));
00863 (void) write(passPhrasePipe[1], "\n", 1);
00864 (void) close(passPhrasePipe[1]);
00865
00866 (void)waitpid(pid, &status, 0);
00867 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
00868 return 1;
00869 }
00870
00871
00872 return 0;
00873 }
00874
00875 char * rpmGetPassPhrase(const char * prompt, const int sigTag)
00876 {
00877 char *pass;
00878 int aok;
00879
00880 switch (sigTag) {
00881 case RPMSIGTAG_GPG:
00882 { const char *name = rpmExpand("%{?_gpg_name}", NULL);
00883 aok = (name && *name != '\0');
00884 name = _free(name);
00885 }
00886 if (!aok) {
00887 rpmError(RPMERR_SIGGEN,
00888 _("You must set \"%%_gpg_name\" in your macro file\n"));
00889 return NULL;
00890 }
00891 break;
00892 case RPMSIGTAG_PGP5:
00893 case RPMSIGTAG_PGP:
00894 { const char *name = rpmExpand("%{?_pgp_name}", NULL);
00895 aok = (name && *name != '\0');
00896 name = _free(name);
00897 }
00898 if (!aok) {
00899 rpmError(RPMERR_SIGGEN,
00900 _("You must set \"%%_pgp_name\" in your macro file\n"));
00901 return NULL;
00902 }
00903 break;
00904 default:
00905
00906
00907
00908 rpmError(RPMERR_SIGGEN, _("Invalid %%_signature spec in macro file\n"));
00909 return NULL;
00910 break;
00911 }
00912
00913 pass = getpass( (prompt ? prompt : "") ) ;
00914
00915 if (checkPassPhrase(pass, sigTag))
00916 return NULL;
00917
00918 return pass;
00919 }
00920
00921 rpmVerifySignatureReturn
00922 rpmVerifySignature(const char * file, int_32 sigTag, const void * sig,
00923 int count, char * result)
00924 {
00925 rpmVerifySignatureReturn res;
00926
00927 switch (sigTag) {
00928 case RPMSIGTAG_SIZE:
00929 res = verifySizeSignature(file, *(int_32 *)sig, result);
00930 break;
00931 case RPMSIGTAG_MD5:
00932 res = verifyMD5Signature(file, sig, result, mdbinfile);
00933 break;
00934 case RPMSIGTAG_PGP5:
00935 case RPMSIGTAG_PGP:
00936 res = verifyPGPSignature(file, sig, count, result);
00937 break;
00938 case RPMSIGTAG_GPG:
00939 res = verifyGPGSignature(file, sig, count, result);
00940 break;
00941 case RPMSIGTAG_LEMD5_1:
00942 case RPMSIGTAG_LEMD5_2:
00943 sprintf(result, _("Broken MD5 digest: UNSUPPORTED\n"));
00944 res = RPMSIG_UNKNOWN;
00945 break;
00946 default:
00947 sprintf(result, "Do not know how to verify sig type %d\n", sigTag);
00948 res = RPMSIG_UNKNOWN;
00949 break;
00950 }
00951 return res;
00952 }