00001
00005 #include "system.h"
00006
00007 #include <netinet/in.h>
00008
00009 #include <rpmio_internal.h>
00010 #include <rpmcb.h>
00011
00012 #include <rpmtag.h>
00013 #include <rpmtypes.h>
00014 #include <pkgio.h>
00015 #include "signature.h"
00016
00017 #include "rpmts.h"
00018
00019 #include "debug.h"
00020
00021 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
00022
00023
00024
00025
00026
00027
00028
00029 static int _print_pkts = 0;
00030
00031
00032 static unsigned int nkeyids_max = 256;
00033
00034 static unsigned int nkeyids = 0;
00035
00036 static unsigned int nextkeyid = 0;
00037
00038 unsigned int * keyids = NULL;
00039
00045 static int pgpStashKeyid(pgpDig dig)
00046
00047
00048 {
00049 pgpDigParams sigp = pgpGetSignature(dig);
00050 const void * sig = pgpGetSig(dig);
00051 unsigned int keyid;
00052 unsigned int i;
00053
00054 if (sig == NULL || dig == NULL || sigp == NULL)
00055 return 0;
00056
00057 keyid = pgpGrab(sigp->signid+4, 4);
00058 if (keyid == 0)
00059 return 0;
00060
00061 if (keyids != NULL)
00062 for (i = 0; i < nkeyids; i++) {
00063 if (keyid == keyids[i])
00064 return 1;
00065 }
00066
00067 if (nkeyids < nkeyids_max) {
00068 nkeyids++;
00069 keyids = xrealloc(keyids, nkeyids * sizeof(*keyids));
00070 }
00071 if (keyids)
00072 keyids[nextkeyid] = keyid;
00073 nextkeyid++;
00074 nextkeyid %= nkeyids_max;
00075
00076 return 0;
00077 }
00078
00079
00080 rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
00081 {
00082 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00083 HE_t she = memset(alloca(sizeof(*she)), 0, sizeof(*she));
00084 pgpDig dig = rpmtsDig(ts);
00085 char buf[8*BUFSIZ];
00086 ssize_t count;
00087 Header sigh = NULL;
00088 rpmtsOpX opx;
00089 rpmop op = NULL;
00090 size_t nb;
00091 Header h = NULL;
00092 const char * msg = NULL;
00093 rpmVSFlags vsflags;
00094 rpmRC rc = RPMRC_FAIL;
00095 rpmop opsave = memset(alloca(sizeof(*opsave)), 0, sizeof(*opsave));
00096 int xx;
00097
00098 if (hdrp) *hdrp = NULL;
00099
00100 assert(dig != NULL);
00101 (void) fdSetDig(fd, dig);
00102
00103
00104 (void) rpmswAdd(opsave, fdstat_op(fd, FDSTAT_READ));
00105
00106 { const char item[] = "Lead";
00107 msg = NULL;
00108 rc = rpmpkgRead(item, fd, NULL, &msg);
00109 switch (rc) {
00110 default:
00111 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
00112
00113 case RPMRC_NOTFOUND:
00114 msg = _free(msg);
00115 goto exit;
00116 break;
00117 case RPMRC_OK:
00118 break;
00119 }
00120 msg = _free(msg);
00121 }
00122
00123 { const char item[] = "Signature";
00124 msg = NULL;
00125 rc = rpmpkgRead(item, fd, &sigh, &msg);
00126 switch (rc) {
00127 default:
00128 rpmlog(RPMLOG_ERR, "%s: %s: %s", fn, item,
00129 (msg && *msg ? msg : _("read failed\n")));
00130 msg = _free(msg);
00131 goto exit;
00132 break;
00133 case RPMRC_OK:
00134 if (sigh == NULL) {
00135 rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), fn);
00136 rc = RPMRC_FAIL;
00137 goto exit;
00138 }
00139 break;
00140 }
00141 msg = _free(msg);
00142 }
00143
00144 #define _chk(_mask) (she->tag == 0 && !(vsflags & (_mask)))
00145
00146
00147
00148
00149
00150
00151
00152 she->tag = 0;
00153 opx = 0;
00154 vsflags = pgpDigVSFlags;
00155 if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, (rpmTag)RPMSIGTAG_DSA)) {
00156 she->tag = (rpmTag)RPMSIGTAG_DSA;
00157 } else
00158 if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, (rpmTag)RPMSIGTAG_RSA)) {
00159 she->tag = (rpmTag)RPMSIGTAG_RSA;
00160 } else
00161 if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, (rpmTag)RPMSIGTAG_SHA1)) {
00162 she->tag = (rpmTag)RPMSIGTAG_SHA1;
00163 } else
00164 if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) &&
00165 headerIsEntry(sigh, (rpmTag)RPMSIGTAG_MD5))
00166 {
00167 she->tag = (rpmTag)RPMSIGTAG_MD5;
00168 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00169 opx = RPMTS_OP_DIGEST;
00170 }
00171
00172
00173 h = NULL;
00174 msg = NULL;
00175
00176
00177
00178 if (opx > 0) {
00179 op = pgpStatsAccumulator(dig, opx);
00180 (void) rpmswEnter(op, 0);
00181 }
00182
00183 nb = fd->stats->ops[FDSTAT_READ].bytes;
00184 { const char item[] = "Header";
00185 msg = NULL;
00186 rc = rpmpkgRead(item, fd, &h, &msg);
00187 if (rc != RPMRC_OK) {
00188 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
00189 msg = _free(msg);
00190 goto exit;
00191 }
00192 msg = _free(msg);
00193 }
00194 nb = fd->stats->ops[FDSTAT_READ].bytes - nb;
00195
00196 if (opx > 0 && op != NULL) {
00197 (void) rpmswExit(op, nb);
00198 op = NULL;
00199 }
00200
00201
00202 if (she->tag == 0) {
00203 rc = RPMRC_OK;
00204 goto exit;
00205 }
00206
00207 dig->nbytes = 0;
00208
00209
00210 xx = headerGet(sigh, she, 0);
00211 if (she->p.ptr == NULL) {
00212 rc = RPMRC_FAIL;
00213 goto exit;
00214 }
00215
00216 xx = pgpSetSig(dig, she->tag, she->t, she->p.ptr, she->c);
00217
00218
00219 switch ((rpmSigTag)she->tag) {
00220 default:
00221 assert(0);
00222 break;
00223 case RPMSIGTAG_RSA:
00224
00225 xx = pgpPrtPkts(she->p.ptr, she->c, dig, (_print_pkts & rpmIsDebug()));
00226 if (dig->signature.version != 3 && dig->signature.version != 4) {
00227 rpmlog(RPMLOG_ERR,
00228 _("skipping package %s with unverifiable V%u signature\n"),
00229 fn, dig->signature.version);
00230 rc = RPMRC_FAIL;
00231 goto exit;
00232 }
00233 { void * uh = NULL;
00234 rpmTagType uht;
00235 rpmTagCount uhc;
00236 unsigned char * hmagic = NULL;
00237 size_t nmagic = 0;
00238
00239 he->tag = RPMTAG_HEADERIMMUTABLE;
00240 xx = headerGet(h, he, 0);
00241 uht = he->t;
00242 uh = he->p.ptr;
00243 uhc = he->c;
00244 if (!xx)
00245 break;
00246 (void) headerGetMagic(NULL, &hmagic, &nmagic);
00247 op = pgpStatsAccumulator(dig, 10);
00248 (void) rpmswEnter(op, 0);
00249 dig->hdrctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE);
00250 if (hmagic && nmagic > 0) {
00251 (void) rpmDigestUpdate(dig->hdrctx, hmagic, nmagic);
00252 dig->nbytes += nmagic;
00253 }
00254 (void) rpmDigestUpdate(dig->hdrctx, uh, uhc);
00255 dig->nbytes += uhc;
00256 (void) rpmswExit(op, dig->nbytes);
00257 op->count--;
00258 uh = _free(uh);
00259 } break;
00260 case RPMSIGTAG_DSA:
00261
00262 xx = pgpPrtPkts(she->p.ptr, she->c, dig, (_print_pkts & rpmIsDebug()));
00263 if (dig->signature.version != 3 && dig->signature.version != 4) {
00264 rpmlog(RPMLOG_ERR,
00265 _("skipping package %s with unverifiable V%u signature\n"),
00266 fn, dig->signature.version);
00267 rc = RPMRC_FAIL;
00268 goto exit;
00269 }
00270
00271 case RPMSIGTAG_SHA1:
00272 { void * uh = NULL;
00273 rpmTagType uht;
00274 rpmTagCount uhc;
00275 unsigned char * hmagic = NULL;
00276 size_t nmagic = 0;
00277
00278 he->tag = RPMTAG_HEADERIMMUTABLE;
00279 xx = headerGet(h, he, 0);
00280 uht = he->t;
00281 uh = he->p.ptr;
00282 uhc = he->c;
00283 if (!xx)
00284 break;
00285 (void) headerGetMagic(NULL, &hmagic, &nmagic);
00286 op = pgpStatsAccumulator(dig, 10);
00287 (void) rpmswEnter(op, 0);
00288 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00289 if (hmagic && nmagic > 0) {
00290 (void) rpmDigestUpdate(dig->hdrsha1ctx, hmagic, nmagic);
00291 dig->nbytes += nmagic;
00292 }
00293 (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
00294 dig->nbytes += uhc;
00295 (void) rpmswExit(op, dig->nbytes);
00296 if ((rpmSigTag)she->tag == RPMSIGTAG_SHA1)
00297 op->count--;
00298 uh = _free(uh);
00299 } break;
00300 case RPMSIGTAG_MD5:
00301
00302 op = pgpStatsAccumulator(dig, 10);
00303 (void) rpmswEnter(op, 0);
00304 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
00305 dig->nbytes += count;
00306 (void) rpmswExit(op, dig->nbytes);
00307 op->count--;
00308 dig->nbytes += nb;
00309 if (count < 0) {
00310 rpmlog(RPMLOG_ERR, _("%s: Fread failed: %s\n"),
00311 fn, Fstrerror(fd));
00312 rc = RPMRC_FAIL;
00313 goto exit;
00314 }
00315
00316
00317 fdStealDigest(fd, dig);
00318 break;
00319 }
00320
00323 buf[0] = '\0';
00324 rc = rpmVerifySignature(dig, buf);
00325 switch (rc) {
00326 case RPMRC_OK:
00327 rpmlog(RPMLOG_DEBUG, "%s: %s\n", fn, buf);
00328 break;
00329 case RPMRC_NOTTRUSTED:
00330 case RPMRC_NOKEY:
00331
00332 { int lvl = (pgpStashKeyid(dig) ? RPMLOG_DEBUG : RPMLOG_WARNING);
00333 rpmlog(lvl, "%s: %s\n", fn, buf);
00334 } break;
00335 case RPMRC_NOTFOUND:
00336 rpmlog(RPMLOG_WARNING, "%s: %s\n", fn, buf);
00337 break;
00338 default:
00339 case RPMRC_FAIL:
00340 rpmlog(RPMLOG_ERR, "%s: %s\n", fn, buf);
00341 break;
00342 }
00343
00344 exit:
00345 if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
00346
00347
00348 headerMergeLegacySigs(h, sigh);
00349
00350
00351 *hdrp = headerLink(h);
00352 }
00353 (void)headerFree(h);
00354 h = NULL;
00355
00356
00357 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_READHDR),
00358 fdstat_op(fd, FDSTAT_READ));
00359 (void) rpmswSub(rpmtsOp(ts, RPMTS_OP_READHDR),
00360 opsave);
00361
00362 rpmtsCleanDig(ts);
00363 (void)headerFree(sigh);
00364 sigh = NULL;
00365 return rc;
00366 }
00367