00001
00005 #include "system.h"
00006
00007 #include <netinet/in.h>
00008
00009 #include <rpmio_internal.h>
00010 #include <rpmcb.h>
00011 #include <rpmlib.h>
00012
00013 #include "rpmts.h"
00014
00015 #include <pkgio.h>
00016
00017 #include "signature.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 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, void * _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 FD_t fd = _fd;
00086 char buf[8*BUFSIZ];
00087 ssize_t count;
00088 Header sigh = NULL;
00089 rpmtsOpX opx;
00090 rpmop op = NULL;
00091 size_t nb;
00092 Header h = NULL;
00093 const char * msg = NULL;
00094 rpmVSFlags vsflags;
00095 rpmRC rc = RPMRC_FAIL;
00096 rpmop opsave = memset(alloca(sizeof(*opsave)), 0, sizeof(*opsave));
00097 int xx;
00098
00099 if (hdrp) *hdrp = NULL;
00100
00101 #ifdef DYING
00102 { struct stat st;
00103 memset(&st, 0, sizeof(st));
00104 (void) fstat(Fileno(fd), &st);
00105
00106 if (S_ISREG(st.st_mode) && st.st_size < sizeof(*l)) {
00107 rc = RPMRC_NOTFOUND;
00108 goto exit;
00109 }
00110 }
00111 #endif
00112
00113 assert(dig != NULL);
00114 (void) fdSetDig(fd, dig);
00115
00116
00117 (void) rpmswAdd(opsave, fdstat_op(fd, FDSTAT_READ));
00118
00119 { const char item[] = "Lead";
00120 msg = NULL;
00121 rc = rpmpkgRead(item, fd, NULL, &msg);
00122 switch (rc) {
00123 default:
00124 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
00125
00126 case RPMRC_NOTFOUND:
00127 msg = _free(msg);
00128 goto exit;
00129 break;
00130 case RPMRC_OK:
00131 break;
00132 }
00133 msg = _free(msg);
00134 }
00135
00136 { const char item[] = "Signature";
00137 msg = NULL;
00138 rc = rpmpkgRead(item, fd, &sigh, &msg);
00139 switch (rc) {
00140 default:
00141 rpmlog(RPMLOG_ERR, "%s: %s: %s", fn, item,
00142 (msg && *msg ? msg : _("read failed\n")));
00143 msg = _free(msg);
00144 goto exit;
00145 break;
00146 case RPMRC_OK:
00147 if (sigh == NULL) {
00148 rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), fn);
00149 rc = RPMRC_FAIL;
00150 goto exit;
00151 }
00152 break;
00153 }
00154 msg = _free(msg);
00155 }
00156
00157 #define _chk(_mask) (she->tag == 0 && !(vsflags & (_mask)))
00158
00159
00160
00161
00162
00163
00164
00165 she->tag = 0;
00166 opx = 0;
00167 vsflags = pgpDigVSFlags;
00168 if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, (rpmTag)RPMSIGTAG_DSA)) {
00169 she->tag = (rpmTag)RPMSIGTAG_DSA;
00170 } else
00171 if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, (rpmTag)RPMSIGTAG_RSA)) {
00172 she->tag = (rpmTag)RPMSIGTAG_RSA;
00173 } else
00174 if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, (rpmTag)RPMSIGTAG_SHA1)) {
00175 she->tag = (rpmTag)RPMSIGTAG_SHA1;
00176 } else
00177 if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) &&
00178 headerIsEntry(sigh, (rpmTag)RPMSIGTAG_MD5))
00179 {
00180 she->tag = (rpmTag)RPMSIGTAG_MD5;
00181 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00182 opx = RPMTS_OP_DIGEST;
00183 }
00184
00185
00186 h = NULL;
00187 msg = NULL;
00188
00189
00190
00191 if (opx > 0) {
00192 op = pgpStatsAccumulator(dig, opx);
00193 (void) rpmswEnter(op, 0);
00194 }
00195
00196 nb = -fd->stats->ops[FDSTAT_READ].bytes;
00197 { const char item[] = "Header";
00198 msg = NULL;
00199 rc = rpmpkgRead(item, fd, &h, &msg);
00200 if (rc != RPMRC_OK) {
00201 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
00202 msg = _free(msg);
00203 goto exit;
00204 }
00205 msg = _free(msg);
00206 }
00207 nb += fd->stats->ops[FDSTAT_READ].bytes;
00208
00209 if (opx > 0 && op != NULL) {
00210 (void) rpmswExit(op, nb);
00211 op = NULL;
00212 }
00213
00214
00215 if (she->tag == 0) {
00216 rc = RPMRC_OK;
00217 goto exit;
00218 }
00219
00220 dig->nbytes = 0;
00221
00222
00223 xx = headerGet(sigh, she, 0);
00224 if (she->p.ptr == NULL) {
00225 rc = RPMRC_FAIL;
00226 goto exit;
00227 }
00228
00229 xx = pgpSetSig(dig, she->tag, she->t, she->p.ptr, she->c);
00230
00231
00232 switch ((rpmSigTag)she->tag) {
00233 default:
00234 assert(0);
00235 break;
00236 case RPMSIGTAG_RSA:
00237
00238 xx = pgpPrtPkts(she->p.ptr, she->c, dig, (_print_pkts & rpmIsDebug()));
00239 if (dig->signature.version != 3 && dig->signature.version != 4) {
00240 rpmlog(RPMLOG_ERR,
00241 _("skipping package %s with unverifiable V%u signature\n"),
00242 fn, dig->signature.version);
00243 rc = RPMRC_FAIL;
00244 goto exit;
00245 }
00246 { void * uh = NULL;
00247 rpmTagType uht;
00248 rpmTagCount uhc;
00249 unsigned char * hmagic = NULL;
00250 size_t nmagic = 0;
00251
00252 he->tag = RPMTAG_HEADERIMMUTABLE;
00253 xx = headerGet(h, he, 0);
00254 uht = he->t;
00255 uh = he->p.ptr;
00256 uhc = he->c;
00257 if (!xx)
00258 break;
00259 (void) headerGetMagic(NULL, &hmagic, &nmagic);
00260 op = pgpStatsAccumulator(dig, 10);
00261 (void) rpmswEnter(op, 0);
00262 dig->hdrmd5ctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE);
00263 if (hmagic && nmagic > 0) {
00264 (void) rpmDigestUpdate(dig->hdrmd5ctx, hmagic, nmagic);
00265 dig->nbytes += nmagic;
00266 }
00267 (void) rpmDigestUpdate(dig->hdrmd5ctx, uh, uhc);
00268 dig->nbytes += uhc;
00269 (void) rpmswExit(op, dig->nbytes);
00270 op->count--;
00271 uh = _free(uh);
00272 } break;
00273 case RPMSIGTAG_DSA:
00274
00275 xx = pgpPrtPkts(she->p.ptr, she->c, dig, (_print_pkts & rpmIsDebug()));
00276 if (dig->signature.version != 3 && dig->signature.version != 4) {
00277 rpmlog(RPMLOG_ERR,
00278 _("skipping package %s with unverifiable V%u signature\n"),
00279 fn, dig->signature.version);
00280 rc = RPMRC_FAIL;
00281 goto exit;
00282 }
00283
00284 case RPMSIGTAG_SHA1:
00285 { void * uh = NULL;
00286 rpmTagType uht;
00287 rpmTagCount uhc;
00288 unsigned char * hmagic = NULL;
00289 size_t nmagic = 0;
00290
00291 he->tag = RPMTAG_HEADERIMMUTABLE;
00292 xx = headerGet(h, he, 0);
00293 uht = he->t;
00294 uh = he->p.ptr;
00295 uhc = he->c;
00296 if (!xx)
00297 break;
00298 (void) headerGetMagic(NULL, &hmagic, &nmagic);
00299 op = pgpStatsAccumulator(dig, 10);
00300 (void) rpmswEnter(op, 0);
00301 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00302 if (hmagic && nmagic > 0) {
00303 (void) rpmDigestUpdate(dig->hdrsha1ctx, hmagic, nmagic);
00304 dig->nbytes += nmagic;
00305 }
00306 (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
00307 dig->nbytes += uhc;
00308 (void) rpmswExit(op, dig->nbytes);
00309 if ((rpmSigTag)she->tag == RPMSIGTAG_SHA1)
00310 op->count--;
00311 uh = _free(uh);
00312 } break;
00313 case RPMSIGTAG_MD5:
00314
00315 op = pgpStatsAccumulator(dig, 10);
00316 (void) rpmswEnter(op, 0);
00317 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
00318 dig->nbytes += count;
00319 (void) rpmswExit(op, dig->nbytes);
00320 op->count--;
00321 dig->nbytes += nb;
00322 if (count < 0) {
00323 rpmlog(RPMLOG_ERR, _("%s: Fread failed: %s\n"),
00324 fn, Fstrerror(fd));
00325 rc = RPMRC_FAIL;
00326 goto exit;
00327 }
00328
00329
00330 fdStealDigest(fd, dig);
00331 break;
00332 }
00333
00336 buf[0] = '\0';
00337 rc = rpmVerifySignature(dig, buf);
00338 switch (rc) {
00339 case RPMRC_OK:
00340 rpmlog(RPMLOG_DEBUG, "%s: %s\n", fn, buf);
00341 break;
00342 case RPMRC_NOTTRUSTED:
00343 case RPMRC_NOKEY:
00344
00345 { int lvl = (pgpStashKeyid(dig) ? RPMLOG_DEBUG : RPMLOG_WARNING);
00346 rpmlog(lvl, "%s: %s\n", fn, buf);
00347 } break;
00348 case RPMRC_NOTFOUND:
00349 rpmlog(RPMLOG_WARNING, "%s: %s\n", fn, buf);
00350 break;
00351 default:
00352 case RPMRC_FAIL:
00353 rpmlog(RPMLOG_ERR, "%s: %s\n", fn, buf);
00354 break;
00355 }
00356
00357 exit:
00358 if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
00359
00360
00361 headerMergeLegacySigs(h, sigh);
00362
00363
00364 *hdrp = headerLink(h);
00365 }
00366 h = headerFree(h);
00367
00368
00369 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_READHDR),
00370 fdstat_op(fd, FDSTAT_READ));
00371 (void) rpmswSub(rpmtsOp(ts, RPMTS_OP_READHDR),
00372 opsave);
00373
00374 rpmtsCleanDig(ts);
00375 sigh = headerFree(sigh);
00376 return rc;
00377 }
00378