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