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 sigtype;
00111     const char *rpm, *trpm;
00112     const char *sigtarget = NULL;
00113     char tmprpm[1024+1];
00114     Header sig = NULL;
00115     int res = EXIT_FAILURE;
00116     rpmRC rc;
00117     
00118     tmprpm[0] = '\0';
00119     if (argv)
00120     while ((rpm = *argv++) != NULL) {
00121 
00122         fprintf(stdout, "%s:\n", rpm);
00123 
00124         if (manageFile(&fd, &rpm, O_RDONLY, 0))
00125             goto exit;
00126 
00127         memset(l, 0, sizeof(*l));
00128         if (readLead(fd, l)) {
00129             rpmError(RPMERR_READLEAD, _("%s: readLead failed\n"), rpm);
00130             goto exit;
00131         }
00132         switch (l->major) {
00133         case 1:
00134             rpmError(RPMERR_BADSIGTYPE, _("%s: Can't sign v1.0 RPM\n"), rpm);
00135             goto exit;
00136             /*@notreached@*/ break;
00137         case 2:
00138             rpmError(RPMERR_BADSIGTYPE, _("%s: Can't re-sign v2.0 RPM\n"), rpm);
00139             goto exit;
00140             /*@notreached@*/ break;
00141         default:
00142             break;
00143         }
00144 
00145         rc = rpmReadSignature(fd, &sig, l->signature_type);
00146         if (!(rc == RPMRC_OK || rc == RPMRC_BADSIZE)) {
00147             rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed\n"), rpm);
00148             goto exit;
00149         }
00150         if (sig == NULL) {
00151             rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), rpm);
00152             goto exit;
00153         }
00154 
00155         /* Write the header and archive to a temp file */
00156         /* ASSERT: ofd == NULL && sigtarget == NULL */
00157         if (copyFile(&fd, &rpm, &ofd, &sigtarget))
00158             goto exit;
00159         /* Both fd and ofd are now closed. sigtarget contains tempfile name. */
00160         /* ASSERT: fd == NULL && ofd == NULL */
00161 
00162         /* Generate the new signatures */
00163         if (flags != RESIGN_ADD_SIGNATURE) {
00164             void * uh = NULL;
00165             int_32 uht, uhc;
00166 
00167             /* Dump the immutable region (if present). */
00168             if (headerGetEntry(sig, RPMTAG_HEADERSIGNATURES, &uht, &uh, &uhc)) {
00169                 Header nh = headerCopyLoad(uh);
00170                 sig = headerFree(sig);
00171                 /*@-nullpass@*/
00172                 sig = headerLink(nh);
00173                 /*@=nullpass@*/
00174                 nh = headerFree(nh);
00175             }
00176 
00177             (void) headerRemoveEntry(sig, RPMSIGTAG_SIZE);
00178             (void) headerRemoveEntry(sig, RPMSIGTAG_MD5);
00179             (void) headerRemoveEntry(sig, RPMSIGTAG_LEMD5_1);
00180             (void) headerRemoveEntry(sig, RPMSIGTAG_LEMD5_2);
00181             (void) headerRemoveEntry(sig, RPMSIGTAG_PGP5);
00182             (void) headerRemoveEntry(sig, RPMSIGTAG_PGP);
00183             (void) headerRemoveEntry(sig, RPMSIGTAG_GPG);
00184             (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_SIZE, passPhrase);
00185             (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_MD5, passPhrase);
00186         }
00187 
00188         if ((sigtype = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0)
00189             (void) rpmAddSignature(sig, sigtarget, sigtype, passPhrase);
00190 
00191         /* Write the lead/signature of the output rpm */
00192         strcpy(tmprpm, rpm);
00193         strcat(tmprpm, ".XXXXXX");
00194         (void) /*@-unrecog@*/ mktemp(tmprpm) /*@=unrecog@*/;
00195         trpm = tmprpm;
00196 
00197         if (manageFile(&ofd, &trpm, O_WRONLY|O_CREAT|O_TRUNC, 0))
00198             goto exit;
00199 
00200         l->signature_type = RPMSIGTYPE_HEADERSIG;
00201         if (writeLead(ofd, l)) {
00202             rpmError(RPMERR_WRITELEAD, _("%s: writeLead failed: %s\n"), trpm,
00203                 Fstrerror(ofd));
00204             goto exit;
00205         }
00206 
00207         if (rpmWriteSignature(ofd, sig)) {
00208             rpmError(RPMERR_SIGGEN, _("%s: rpmWriteSignature failed: %s\n"), trpm,
00209                 Fstrerror(ofd));
00210             goto exit;
00211         }
00212 
00213         /* Append the header and archive from the temp file */
00214         /* ASSERT: fd == NULL && ofd != NULL */
00215         if (copyFile(&fd, &sigtarget, &ofd, &trpm))
00216             goto exit;
00217         /* Both fd and ofd are now closed. */
00218         /* ASSERT: fd == NULL && ofd == NULL */
00219 
00220         /* Clean up intermediate target */
00221         (void) unlink(sigtarget);
00222         sigtarget = _free(sigtarget);
00223 
00224         /* Move final target into place. */
00225         (void) unlink(rpm);
00226         (void) rename(trpm, rpm);
00227         tmprpm[0] = '\0';
00228     }
00229 
00230     res = 0;
00231 
00232 exit:
00233     if (fd)     (void) manageFile(&fd, NULL, 0, res);
00234     if (ofd)    (void) manageFile(&ofd, NULL, 0, res);
00235 
00236     sig = rpmFreeSignature(sig);
00237 
00238     if (sigtarget) {
00239         (void) unlink(sigtarget);
00240         sigtarget = _free(sigtarget);
00241     }
00242     if (tmprpm[0] != '\0') {
00243         (void) unlink(tmprpm);
00244         tmprpm[0] = '\0';
00245     }
00246 
00247     return res;
00248 }
00249 
00250 int rpmCheckSig(rpmCheckSigFlags flags, const char ** argv)
00251 {
00252     FD_t fd = NULL;
00253     FD_t ofd = NULL;
00254     int res2, res3;
00255     struct rpmlead lead, *l = &lead;
00256     const char *rpm = NULL;
00257     char result[1024];
00258     const char * sigtarget = NULL;
00259     unsigned char buffer[8192];
00260     unsigned char missingKeys[7164];
00261     unsigned char untrustedKeys[7164];
00262     Header sig;
00263     HeaderIterator hi;
00264     int_32 tag, type, count;
00265     const void * ptr;
00266     int res = 0;
00267     rpmRC rc;
00268 
00269     if (argv)
00270     while ((rpm = *argv++) != NULL) {
00271 
00272         if (manageFile(&fd, &rpm, O_RDONLY, 0)) {
00273             res++;
00274             goto bottom;
00275         }
00276 
00277         memset(l, 0, sizeof(*l));
00278         if (readLead(fd, l)) {
00279             rpmError(RPMERR_READLEAD, _("%s: readLead failed\n"), rpm);
00280             res++;
00281             goto bottom;
00282         }
00283         switch (l->major) {
00284         case 1:
00285             rpmError(RPMERR_BADSIGTYPE, _("%s: No signature available (v1.0 RPM)\n"), rpm);
00286             res++;
00287             goto bottom;
00288             /*@notreached@*/ break;
00289         default:
00290             break;
00291         }
00292 
00293         rc = rpmReadSignature(fd, &sig, l->signature_type);
00294         if (!(rc == RPMRC_OK || rc == RPMRC_BADSIZE)) {
00295             rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed\n"), rpm);
00296             res++;
00297             goto bottom;
00298         }
00299         if (sig == NULL) {
00300             rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), rpm);
00301             res++;
00302             goto bottom;
00303         }
00304         /* Write the header and archive to a temp file */
00305         /* ASSERT: ofd == NULL && sigtarget == NULL */
00306         if (copyFile(&fd, &rpm, &ofd, &sigtarget)) {
00307             res++;
00308             goto bottom;
00309         }
00310         /* Both fd and ofd are now closed. sigtarget contains tempfile name. */
00311         /* ASSERT: fd == NULL && ofd == NULL */
00312 
00313         res2 = 0;
00314         missingKeys[0] = '\0';
00315         untrustedKeys[0] = '\0';
00316         sprintf(buffer, "%s:%c", rpm, (rpmIsVerbose() ? '\n' : ' ') );
00317 
00318         for (hi = headerInitIterator(sig);
00319             headerNextIterator(hi, &tag, &type, &ptr, &count);
00320             ptr = headerFreeData(ptr, type))
00321         {
00322             switch (tag) {
00323             case RPMSIGTAG_PGP5:        /* XXX legacy */
00324             case RPMSIGTAG_PGP:
00325                 if (!(flags & CHECKSIG_PGP)) 
00326                      continue;
00327                 break;
00328             case RPMSIGTAG_GPG:
00329                 if (!(flags & CHECKSIG_GPG)) 
00330                      continue;
00331                 break;
00332             case RPMSIGTAG_LEMD5_2:
00333             case RPMSIGTAG_LEMD5_1:
00334             case RPMSIGTAG_MD5:
00335                 if (!(flags & CHECKSIG_MD5)) 
00336                      continue;
00337                 break;
00338             default:
00339                 continue;
00340                 /*@notreached@*/ break;
00341             }
00342             if (ptr == NULL) continue;  /* XXX can't happen */
00343 
00344             if ((res3 = rpmVerifySignature(sigtarget, tag, ptr, count, 
00345                                            result))) {
00346                 if (rpmIsVerbose()) {
00347                     strcat(buffer, result);
00348                     res2 = 1;
00349                 } else {
00350                     char *tempKey;
00351                     switch (tag) {
00352                       case RPMSIGTAG_SIZE:
00353                         strcat(buffer, "SIZE ");
00354                         res2 = 1;
00355                         break;
00356                       case RPMSIGTAG_LEMD5_2:
00357                       case RPMSIGTAG_LEMD5_1:
00358                       case RPMSIGTAG_MD5:
00359                         strcat(buffer, "MD5 ");
00360                         res2 = 1;
00361                         break;
00362                       case RPMSIGTAG_PGP5:      /* XXX legacy */
00363                       case RPMSIGTAG_PGP:
00364                         switch (res3) {
00365                         case RPMSIG_NOKEY:
00366                             res2 = 1;
00367                             /*@fallthrough@*/
00368                         case RPMSIG_NOTTRUSTED:
00369                         {   int offset = 7;
00370                             strcat(buffer, "(PGP) ");
00371                             tempKey = strstr(result, "Key ID");
00372                             if (tempKey == NULL) {
00373                                 tempKey = strstr(result, "keyid:");
00374                                 offset = 9;
00375                             }
00376                             if (tempKey) {
00377                               if (res3 == RPMSIG_NOKEY) {
00378                                 strcat(missingKeys, " PGP#");
00379                                 /*@-compdef@*/
00380                                 strncat(missingKeys, tempKey + offset, 8);
00381                                 /*@=compdef@*/
00382                               } else {
00383                                 strcat(untrustedKeys, " PGP#");
00384                                 /*@-compdef@*/
00385                                 strncat(untrustedKeys, tempKey + offset, 8);
00386                                 /*@=compdef@*/
00387                               }
00388                             }
00389                         }   break;
00390                         default:
00391                             strcat(buffer, "PGP ");
00392                             res2 = 1;
00393                             break;
00394                         }
00395                         break;
00396                       case RPMSIGTAG_GPG:
00397                         /* Do not consider this a failure */
00398                         switch (res3) {
00399                         case RPMSIG_NOKEY:
00400                             strcat(buffer, "(GPG) ");
00401                             strcat(missingKeys, " GPG#");
00402                             tempKey = strstr(result, "key ID");
00403                             if (tempKey)
00404                                 /*@-compdef@*/
00405                                 strncat(missingKeys, tempKey+7, 8);
00406                                 /*@=compdef@*/
00407                             res2 = 1;
00408                             break;
00409                         default:
00410                             strcat(buffer, "GPG ");
00411                             res2 = 1;
00412                             break;
00413                         }
00414                         break;
00415                       default:
00416                         strcat(buffer, "?UnknownSignatureType? ");
00417                         res2 = 1;
00418                         break;
00419                     }
00420                 }
00421             } else {
00422                 if (rpmIsVerbose()) {
00423                     strcat(buffer, result);
00424                 } else {
00425                     switch (tag) {
00426                     case RPMSIGTAG_SIZE:
00427                         strcat(buffer, "size ");
00428                         break;
00429                     case RPMSIGTAG_LEMD5_2:
00430                     case RPMSIGTAG_LEMD5_1:
00431                     case RPMSIGTAG_MD5:
00432                         strcat(buffer, "md5 ");
00433                         break;
00434                     case RPMSIGTAG_PGP5:        /* XXX legacy */
00435                     case RPMSIGTAG_PGP:
00436                         strcat(buffer, "pgp ");
00437                         break;
00438                     case RPMSIGTAG_GPG:
00439                         strcat(buffer, "gpg ");
00440                         break;
00441                     default:
00442                         strcat(buffer, "??? ");
00443                         break;
00444                     }
00445                 }
00446             }
00447         }
00448         hi = headerFreeIterator(hi);
00449         res += res2;
00450         (void) unlink(sigtarget);
00451         sigtarget = _free(sigtarget);
00452 
00453         if (res2) {
00454             if (rpmIsVerbose()) {
00455                 rpmError(RPMERR_SIGVFY, "%s", (char *)buffer);
00456             } else {
00457                 rpmError(RPMERR_SIGVFY, "%s%s%s%s%s%s%s%s\n", (char *)buffer,
00458                         _("NOT OK"),
00459                         (missingKeys[0] != '\0') ? _(" (MISSING KEYS:") : "",
00460                         (char *)missingKeys,
00461                         (missingKeys[0] != '\0') ? _(") ") : "",
00462                         (untrustedKeys[0] != '\0') ? _(" (UNTRUSTED KEYS:") : "",
00463                         (char *)untrustedKeys,
00464                         (untrustedKeys[0] != '\0') ? _(")") : "");
00465 
00466             }
00467         } else {
00468             if (rpmIsVerbose()) {
00469                 rpmError(RPMERR_SIGVFY, "%s", (char *)buffer);
00470             } else {
00471                 rpmError(RPMERR_SIGVFY, "%s%s%s%s%s%s%s%s\n", (char *)buffer,
00472                         _("OK"),
00473                         (missingKeys[0] != '\0') ? _(" (MISSING KEYS:") : "",
00474                         (char *)missingKeys,
00475                         (missingKeys[0] != '\0') ? _(") ") : "",
00476                         (untrustedKeys[0] != '\0') ? _(" (UNTRUSTED KEYS:") : "",
00477                         (char *)untrustedKeys,
00478                         (untrustedKeys[0] != '\0') ? _(")") : "");
00479             }
00480         }
00481 
00482     bottom:
00483         if (fd)         (void) manageFile(&fd, NULL, 0, 0);
00484         if (ofd)        (void) manageFile(&ofd, NULL, 0, 0);
00485         if (sigtarget) {
00486             (void) unlink(sigtarget);
00487             sigtarget = _free(sigtarget);
00488         }
00489     }
00490 
00491     return res;
00492 }

Generated on Fri Oct 15 05:31:07 2004 for rpm by doxygen 1.3.6