Main Page Modules Data Structures File List Data Fields Globals Related Pages

# lib/rpmchecksig.c

Go to the documentation of this file.

    00001
    00006 #include "system.h"
    00007
    00008 #include <rpmcli.h>
    00009
    00010 #include "rpmlead.h"
    00011 #include "signature.h"
    00012 #include "misc.h"       /* XXX for makeTempFile() */
    00013 #include "debug.h"
    00014
    00015 /*@access Header@*/             /* XXX compared with NULL */
    00016 /*@access FD_t@*/               /* XXX compared with NULL */
    00017
    00018 static int manageFile(FD_t *fdp, const char **fnp, int flags,
    00019                 /*@unused@*/ int rc)
    00020         /*@globals rpmGlobalMacroContext, fileSystem @*/
    00021         /*@modifies *fdp, *fnp, rpmGlobalMacroContext, fileSystem @*/
    00022 {
    00023     const char *fn;
    00024     FD_t fd;
    00025
    00026     if (fdp == NULL) {  /* programmer error */
    00027         return 1;
    00028     }
    00029
    00030     /* close and reset *fdp to NULL */
    00031     if (*fdp && (fnp == NULL || *fnp == NULL)) {
    00032         (void) Fclose(*fdp);
    00033         *fdp = NULL;
    00034         return 0;
    00035     }
    00036
    00037     /* open a file and set *fdp */
    00038     if (*fdp == NULL && fnp && *fnp) {
    00039         fd = Fopen(*fnp, ((flags & O_WRONLY) ? "w.ufdio" : "r.ufdio"));
    00040         if (fd == NULL || Ferror(fd)) {
    00041             rpmError(RPMERR_OPEN, _("%s: open failed: %s\n"), *fnp,
    00042                 Fstrerror(fd));
    00043             return 1;
    00044         }
    00045         *fdp = fd;
    00046         return 0;
    00047     }
    00048
    00049     /* open a temp file */
    00050     if (*fdp == NULL && (fnp == NULL || *fnp == NULL)) {
    00051         fn = NULL;
    00052         if (makeTempFile(NULL, (fnp ? &fn : NULL), &fd)) {
    00053             rpmError(RPMERR_MAKETEMP, _("makeTempFile failed\n"));
    00054             return 1;
    00055         }
    00056         if (fnp)
    00057             *fnp = fn;
    00058         *fdp = fdLink(fd, "manageFile return");
    00059         (void) fdFree(fd, "manageFile return");
    00060         return 0;
    00061     }
    00062
    00063     /* no operation */
    00064     if (*fdp && fnp && *fnp) {
    00065         return 0;
    00066     }
    00067
    00068     /* XXX never reached */
    00069     return 1;
    00070 }
    00071
    00072 static int copyFile(FD_t *sfdp, const char **sfnp,
    00073         FD_t *tfdp, const char **tfnp)
    00074         /*@modifies *sfdp, *sfnp, *tfdp, *tfnp, fileSystem @*/
    00075 {
    00076     unsigned char buffer[BUFSIZ];
    00077     ssize_t count;
    00078     int rc = 1;
    00079
    00080     if (manageFile(sfdp, sfnp, O_RDONLY, 0))
    00081         goto exit;
    00082     if (manageFile(tfdp, tfnp, O_WRONLY|O_CREAT|O_TRUNC, 0))
    00083         goto exit;
    00084
    00085     while ((count = Fread(buffer, sizeof(buffer[0]), sizeof(buffer), *sfdp)) > 0) {
    00086         if (Fwrite(buffer, sizeof(buffer[0]), count, *tfdp) != count) {
    00087             rpmError(RPMERR_FWRITE, _("%s: Fwrite failed: %s\n"), *tfnp,
    00088                 Fstrerror(*tfdp));
    00089             goto exit;
    00090         }
    00091     }
    00092     if (count < 0) {
    00093         rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"), *sfnp, Fstrerror(*sfdp));
    00094         goto exit;
    00095     }
    00096
    00097     rc = 0;
    00098
    00099 exit:
    00100     if (*sfdp)  (void) manageFile(sfdp, NULL, 0, rc);
    00101     if (*tfdp)  (void) manageFile(tfdp, NULL, 0, rc);
    00102     return rc;
    00103 }
    00104
    00105 int rpmReSign(rpmResignFlags flags, char * passPhrase, const char ** argv)
    00106 {
    00107     FD_t fd = NULL;
    00108     FD_t ofd = NULL;
    00109     struct rpmlead lead, *l = &lead;
    00110     int_32 sigtag;
    00111     const char *rpm, *trpm;
    00112     const char *sigtarget = NULL;
    00113     char tmprpm[1024+1];
    00114     Header sig = NULL;
    00115     void * uh = NULL;
    00116     int_32 uht, uhc;
    00117     int res = EXIT_FAILURE;
    00118     rpmRC rc;
    00119     int xx;
    00120
    00121     tmprpm[0] = '\0';
    00122     if (argv)
    00123     while ((rpm = *argv++) != NULL) {
    00124
    00125         fprintf(stdout, "%s:\n", rpm);
    00126
    00127         if (manageFile(&fd, &rpm, O_RDONLY, 0))
    00128             goto exit;
    00129
    00130         memset(l, 0, sizeof(*l));
    00131         if (readLead(fd, l)) {
    00132             rpmError(RPMERR_READLEAD, _("%s: readLead failed\n"), rpm);
    00133             goto exit;
    00134         }
    00135         switch (l->major) {
    00136         case 1:
    00137             rpmError(RPMERR_BADSIGTYPE, _("%s: Can't sign v1.0 RPM\n"), rpm);
    00138             goto exit;
    00139             /*@notreached@*/ break;
    00140         case 2:
    00141             rpmError(RPMERR_BADSIGTYPE, _("%s: Can't re-sign v2.0 RPM\n"), rpm);
    00142             goto exit;
    00143             /*@notreached@*/ break;
    00144         default:
    00145             break;
    00146         }
    00147
    00148         rc = rpmReadSignature(fd, &sig, l->signature_type);
    00149         if (!(rc == RPMRC_OK || rc == RPMRC_BADSIZE)) {
    00150             rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed\n"), rpm);
    00151             goto exit;
    00152         }
    00153         if (sig == NULL) {
    00154             rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), rpm);
    00155             goto exit;
    00156         }
    00157
    00158         /* Write the header and archive to a temp file */
    00159         /* ASSERT: ofd == NULL && sigtarget == NULL */
    00160         if (copyFile(&fd, &rpm, &ofd, &sigtarget))
    00161             goto exit;
    00162         /* Both fd and ofd are now closed. sigtarget contains tempfile name. */
    00163         /* ASSERT: fd == NULL && ofd == NULL */
    00164
    00165         /* Dump the immutable region (if present). */
    00166         if (headerGetEntry(sig, RPMTAG_HEADERSIGNATURES, &uht, &uh, &uhc)) {
    00167             HeaderIterator hi;
    00168             int_32 tag, type, count;
    00169             hPTR_t ptr;
    00170             Header oh;
    00171             Header nh;
    00172
    00173             nh = headerNew();
    00174             if (nh == NULL) {
    00175                 uh = headerFreeData(uh, uht);
    00176                 goto exit;
    00177             }
    00178
    00179             oh = headerCopyLoad(uh);
    00180             for (hi = headerInitIterator(oh);
    00181                 headerNextIterator(hi, &tag, &type, &ptr, &count);
    00182                 ptr = headerFreeData(ptr, type))
    00183             {
    00184                 if (ptr)
    00185                     xx = headerAddEntry(nh, tag, type, ptr, count);
    00186             }
    00187             hi = headerFreeIterator(hi);
    00188             oh = headerFree(oh);
    00189
    00190             sig = headerFree(sig);
    00191             sig = headerLink(nh);
    00192             nh = headerFree(nh);
    00193         }
    00194
    00195         /* Eliminate broken digest values. */
    00196         xx = headerRemoveEntry(sig, RPMSIGTAG_LEMD5_1);
    00197         xx = headerRemoveEntry(sig, RPMSIGTAG_LEMD5_2);
    00198         xx = headerRemoveEntry(sig, RPMSIGTAG_BADSHA1_1);
    00199         xx = headerRemoveEntry(sig, RPMSIGTAG_BADSHA1_2);
    00200
    00201         /* Toss and recalculate header+payload size and digests. */
    00202         xx = headerRemoveEntry(sig, RPMSIGTAG_SIZE);
    00203         xx = rpmAddSignature(sig, sigtarget, RPMSIGTAG_SIZE, passPhrase);
    00204         xx = headerRemoveEntry(sig, RPMSIGTAG_MD5);
    00205         xx = rpmAddSignature(sig, sigtarget, RPMSIGTAG_MD5, passPhrase);
    00206 #ifdef  NOTYET  /* XXX leave new-fangled header-only digest in place. */
    00207         xx = headerRemoveEntry(sig, RPMSIGTAG_SHA1);
    00208         xx = rpmAddSignature(sig, sigtarget, RPMSIGTAG_SHA1, passPhrase);
    00209 #endif
    00210
    00211         if ((sigtag = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0) {
    00212 #ifdef  NOTYET  /* XXX leave new-fangled header-only signatures in place. */
    00213             case RPMSIGTAG_GPG:
    00214                 xx = headerRemoveEntry(sig, RPMSIGTAG_DSA);
    00215                 /*@fallthrough@*/
    00216             case RPMSIGTAG_PGP5:
    00217             case RPMSIGTAG_PGP:
    00218                 xx = headerRemoveEntry(sig, RPMSIGTAG_RSA);
    00219                 /*@switchbreak@*/ break;
    00220             }
    00221 #endif
    00222             xx = headerRemoveEntry(sig, sigtag);
    00223             xx = rpmAddSignature(sig, sigtarget, sigtag, passPhrase);
    00224         }
    00225
    00226         /* Reallocate the signature into one contiguous region. */
    00227         sig = headerReload(sig, RPMTAG_HEADERSIGNATURES);
    00228         if (sig == NULL)        /* XXX can't happen */
    00229             goto exit;
    00230
    00231         /* Write the lead/signature of the output rpm */
    00232         strcpy(tmprpm, rpm);
    00233         strcat(tmprpm, ".XXXXXX");
    00234         (void) /*@-unrecog@*/ mktemp(tmprpm) /*@=unrecog@*/;
    00235         trpm = tmprpm;
    00236
    00237         if (manageFile(&ofd, &trpm, O_WRONLY|O_CREAT|O_TRUNC, 0))
    00238             goto exit;
    00239
    00240         l->signature_type = RPMSIGTYPE_HEADERSIG;
    00241         if (writeLead(ofd, l)) {
    00242             rpmError(RPMERR_WRITELEAD, _("%s: writeLead failed: %s\n"), trpm,
    00243                 Fstrerror(ofd));
    00244             goto exit;
    00245         }
    00246
    00247         if (rpmWriteSignature(ofd, sig)) {
    00248             rpmError(RPMERR_SIGGEN, _("%s: rpmWriteSignature failed: %s\n"), trpm,
    00249                 Fstrerror(ofd));
    00250             goto exit;
    00251         }
    00252
    00253         /* Append the header and archive from the temp file */
    00254         /* ASSERT: fd == NULL && ofd != NULL */
    00255         if (copyFile(&fd, &sigtarget, &ofd, &trpm))
    00256             goto exit;
    00257         /* Both fd and ofd are now closed. */
    00258         /* ASSERT: fd == NULL && ofd == NULL */
    00259
    00260         /* Clean up intermediate target */
    00261         (void) unlink(sigtarget);
    00262         sigtarget = _free(sigtarget);
    00263
    00264         /* Move final target into place. */
    00265         (void) unlink(rpm);
    00266         (void) rename(trpm, rpm);
    00267         tmprpm[0] = '\0';
    00268     }
    00269
    00270     res = 0;
    00271
    00272 exit:
    00273     if (fd)     (void) manageFile(&fd, NULL, 0, res);
    00274     if (ofd)    (void) manageFile(&ofd, NULL, 0, res);
    00275
    00276     sig = rpmFreeSignature(sig);
    00277
    00278     if (sigtarget) {
    00279         (void) unlink(sigtarget);
    00280         sigtarget = _free(sigtarget);
    00281     }
    00282     if (tmprpm[0] != '\0') {
    00283         (void) unlink(tmprpm);
    00284         tmprpm[0] = '\0';
    00285     }
    00286
    00287     return res;
    00288 }
    00289
    00290 int rpmCheckSig(rpmCheckSigFlags flags, const char ** argv)
    00291 {
    00292     FD_t fd = NULL;
    00293     FD_t ofd = NULL;
    00294     int res2, res3;
    00295     struct rpmlead lead, *l = &lead;
    00296     const char *rpm = NULL;
    00297     char result[8*BUFSIZ];
    00298     const char * sigtarget = NULL;
    00299     unsigned char buffer[8192];
    00300     unsigned char missingKeys[7164];
    00301     unsigned char untrustedKeys[7164];
    00302     Header sig;
    00303     HeaderIterator hi;
    00304     int_32 tag, type, count;
    00305     const void * ptr;
    00306     int res = 0;
    00307     rpmRC rc;
    00308
    00309     if (argv)
    00310     while ((rpm = *argv++) != NULL) {
    00311
    00312         if (manageFile(&fd, &rpm, O_RDONLY, 0)) {
    00313             res++;
    00314             goto bottom;
    00315         }
    00316
    00317         memset(l, 0, sizeof(*l));
    00318         if (readLead(fd, l)) {
    00319             rpmError(RPMERR_READLEAD, _("%s: readLead failed\n"), rpm);
    00320             res++;
    00321             goto bottom;
    00322         }
    00323         switch (l->major) {
    00324         case 1:
    00325             rpmError(RPMERR_BADSIGTYPE, _("%s: No signature available (v1.0 RPM)\n"), rpm);
    00326             res++;
    00327             goto bottom;
    00328             /*@notreached@*/ break;
    00329         default:
    00330             break;
    00331         }
    00332
    00333         rc = rpmReadSignature(fd, &sig, l->signature_type);
    00334         if (!(rc == RPMRC_OK || rc == RPMRC_BADSIZE)) {
    00335             rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed\n"), rpm);
    00336             res++;
    00337             goto bottom;
    00338         }
    00339         if (sig == NULL) {
    00340             rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), rpm);
    00341             res++;
    00342             goto bottom;
    00343         }
    00344         /* Write the header and archive to a temp file */
    00345         /* ASSERT: ofd == NULL && sigtarget == NULL */
    00346         if (copyFile(&fd, &rpm, &ofd, &sigtarget)) {
    00347             res++;
    00348             goto bottom;
    00349         }
    00350         /* Both fd and ofd are now closed. sigtarget contains tempfile name. */
    00351         /* ASSERT: fd == NULL && ofd == NULL */
    00352
    00353         res2 = 0;
    00354         missingKeys[0] = '\0';
    00355         untrustedKeys[0] = '\0';
    00356         sprintf(buffer, "%s:%c", rpm, (rpmIsVerbose() ? '\n' : ' ') );
    00357
    00358         for (hi = headerInitIterator(sig);
    00359             headerNextIterator(hi, &tag, &type, &ptr, &count);
    00360             ptr = headerFreeData(ptr, type))
    00361         {
    00362             switch (tag) {
    00363             case RPMSIGTAG_PGP5:        /* XXX legacy */
    00364             case RPMSIGTAG_PGP:
    00365                 if (!(flags & CHECKSIG_PGP))
    00366                      continue;
    00367                 break;
    00368             case RPMSIGTAG_GPG:
    00369                 if (!(flags & CHECKSIG_GPG))
    00370                      continue;
    00371                 break;
    00372             case RPMSIGTAG_LEMD5_2:
    00373             case RPMSIGTAG_LEMD5_1:
    00374             case RPMSIGTAG_MD5:
    00375                 if (!(flags & CHECKSIG_MD5))
    00376                      continue;
    00377                 break;
    00378             default:
    00379                 continue;
    00380                 /*@notreached@*/ break;
    00381             }
    00382             if (ptr == NULL) continue;  /* XXX can't happen */
    00383
    00384             if ((res3 = rpmVerifySignature(sigtarget, tag, ptr, count,
    00385                                            result))) {
    00386                 if (rpmIsVerbose()) {
    00387                     strcat(buffer, result);
    00388                     res2 = 1;
    00389                 } else {
    00390                     char *tempKey;
    00391                     switch (tag) {
    00392                       case RPMSIGTAG_SIZE:
    00393                         strcat(buffer, "SIZE ");
    00394                         res2 = 1;
    00395                         break;
    00396                       case RPMSIGTAG_LEMD5_2:
    00397                       case RPMSIGTAG_LEMD5_1:
    00398                       case RPMSIGTAG_MD5:
    00399                         strcat(buffer, "MD5 ");
    00400                         res2 = 1;
    00401                         break;
    00402                       case RPMSIGTAG_PGP5:      /* XXX legacy */
    00403                       case RPMSIGTAG_PGP:
    00404                         switch (res3) {
    00405                         case RPMSIG_NOKEY:
    00406                             res2 = 1;
    00407                             /*@fallthrough@*/
    00408                         case RPMSIG_NOTTRUSTED:
    00409                         {   int offset = 7;
    00410                             strcat(buffer, "(PGP) ");
    00411                             tempKey = strstr(result, "Key ID");
    00412                             if (tempKey == NULL) {
    00413                                 tempKey = strstr(result, "keyid:");
    00414                                 offset = 9;
    00415                             }
    00416                             if (tempKey) {
    00417                               if (res3 == RPMSIG_NOKEY) {
    00418                                 strcat(missingKeys, " PGP#");
    00419                                 /*@-compdef@*/
    00420                                 strncat(missingKeys, tempKey + offset, 8);
    00421                                 /*@=compdef@*/
    00422                               } else {
    00423                                 strcat(untrustedKeys, " PGP#");
    00424                                 /*@-compdef@*/
    00425                                 strncat(untrustedKeys, tempKey + offset, 8);
    00426                                 /*@=compdef@*/
    00427                               }
    00428                             }
    00429                         }   break;
    00430                         default:
    00431                             strcat(buffer, "PGP ");
    00432                             res2 = 1;
    00433                             break;
    00434                         }
    00435                         break;
    00436                       case RPMSIGTAG_GPG:
    00437                         /* Do not consider this a failure */
    00438                         switch (res3) {
    00439                         case RPMSIG_NOKEY:
    00440                             strcat(buffer, "(GPG) ");
    00441                             strcat(missingKeys, " GPG#");
    00442                             tempKey = strstr(result, "key ID");
    00443                             if (tempKey)
    00444                                 /*@-compdef@*/
    00445                                 strncat(missingKeys, tempKey+7, 8);
    00446                                 /*@=compdef@*/
    00447                             res2 = 1;
    00448                             break;
    00449                         default:
    00450                             strcat(buffer, "GPG ");
    00451                             res2 = 1;
    00452                             break;
    00453                         }
    00454                         break;
    00455                       default:
    00456                         strcat(buffer, "?UnknownSignatureType? ");
    00457                         res2 = 1;
    00458                         break;
    00459                     }
    00460                 }
    00461             } else {
    00462                 if (rpmIsVerbose()) {
    00463                     strcat(buffer, result);
    00464                 } else {
    00465                     switch (tag) {
    00466                     case RPMSIGTAG_SIZE:
    00467                         strcat(buffer, "size ");
    00468                         break;
    00469                     case RPMSIGTAG_LEMD5_2:
    00470                     case RPMSIGTAG_LEMD5_1:
    00471                     case RPMSIGTAG_MD5:
    00472                         strcat(buffer, "md5 ");
    00473                         break;
    00474                     case RPMSIGTAG_PGP5:        /* XXX legacy */
    00475                     case RPMSIGTAG_PGP:
    00476                         strcat(buffer, "pgp ");
    00477                         break;
    00478                     case RPMSIGTAG_GPG:
    00479                         strcat(buffer, "gpg ");
    00480                         break;
    00481                     default:
    00482                         strcat(buffer, "??? ");
    00483                         break;
    00484                     }
    00485                 }
    00486             }
    00487         }
    00488         hi = headerFreeIterator(hi);
    00489         res += res2;
    00490         (void) unlink(sigtarget);
    00491         sigtarget = _free(sigtarget);
    00492
    00493         if (res2) {
    00494             if (rpmIsVerbose()) {
    00495                 rpmError(RPMERR_SIGVFY, "%s", (char *)buffer);
    00496             } else {
    00497                 rpmError(RPMERR_SIGVFY, "%s%s%s%s%s%s%s%s\n", (char *)buffer,
    00498                         _("NOT OK"),
    00499                         (missingKeys[0] != '\0') ? _(" (MISSING KEYS:") : "",
    00500                         (char *)missingKeys,
    00501                         (missingKeys[0] != '\0') ? _(") ") : "",
    00502                         (untrustedKeys[0] != '\0') ? _(" (UNTRUSTED KEYS:") : "",
    00503                         (char *)untrustedKeys,
    00504                         (untrustedKeys[0] != '\0') ? _(")") : "");
    00505
    00506             }
    00507         } else {
    00508             if (rpmIsVerbose()) {
    00509                 rpmError(RPMERR_SIGVFY, "%s", (char *)buffer);
    00510             } else {
    00511                 rpmError(RPMERR_SIGVFY, "%s%s%s%s%s%s%s%s\n", (char *)buffer,
    00512                         _("OK"),
    00513                         (missingKeys[0] != '\0') ? _(" (MISSING KEYS:") : "",
    00514                         (char *)missingKeys,
    00515                         (missingKeys[0] != '\0') ? _(") ") : "",
    00516                         (untrustedKeys[0] != '\0') ? _(" (UNTRUSTED KEYS:") : "",
    00517                         (char *)untrustedKeys,
    00518                         (untrustedKeys[0] != '\0') ? _(")") : "");
    00519             }
    00520         }
    00521
    00522     bottom:
    00523         if (fd)         (void) manageFile(&fd, NULL, 0, 0);
    00524         if (ofd)        (void) manageFile(&ofd, NULL, 0, 0);
    00525         if (sigtarget) {
    00526             (void) unlink(sigtarget);
    00527             sigtarget = _free(sigtarget);
    00528         }
    00529     }
    00530
    00531     return res;
    00532 }