Main Page   Modules   Compound List   File List   Compound Members   File Members   Related Pages  

lib/rpmchecksig.c

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

Generated at Sun Apr 8 18:43:00 2001 for rpm by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000