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

Generated on Wed Mar 13 15:34:48 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002