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

Generated at Wed Mar 27 03:56:50 2002 for rpm by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001