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

Generated at Thu Apr 19 15:29:43 2001 for rpm by doxygen1.2.6-20010408 written by Dimitri van Heesch, © 1997-2001