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

Generated at Mon Dec 3 13:19:37 2001 for rpm by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001