# 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 }