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 }

Generated on Fri Apr 4 14:39:40 2003 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002