00001
00004 #include "system.h"
00005
00006 #define _RPMIOB_INTERNAL
00007 #include <rpmiotypes.h>
00008 #include <rpmio.h>
00009 #include <rpmmacro.h>
00010 #include <rpmcb.h>
00011
00012 #define _RPMPGP_INTERNAL
00013 #include <rpmpgp.h>
00014
00015 #include <rpmtypes.h>
00016 #include <rpmtag.h>
00017 #define _RPMEVR_INTERNAL
00018 #include <rpmevr.h>
00019 #define _RPMNS_INTERNAL
00020 #include <rpmns.h>
00021 #include <rpmdb.h>
00022
00023 #include <rpmps.h>
00024 #define _RPMTS_INTERNAL
00025 #include <rpmts.h>
00026
00027 #include "debug.h"
00028
00029
00030
00031
00032
00033 int _rpmns_debug = 0;
00034
00035
00036 const char *_rpmns_N_at_A = ".";
00037
00038
00039
00040 static const char *rpmnsArches[] = {
00041 "i386", "i486", "i586", "i686", "athlon", "pentium3", "pentium4",
00042 "x86_64", "amd64", "ia32e",
00043 "alpha", "alphaev5", "alphaev56", "alphapca56", "alphaev6", "alphaev67",
00044 "sparc", "sun4", "sun4m", "sun4c", "sun4d", "sparcv8",
00045 "sparcv9", "sparcv9b", "sparcv9v", "sparcv9v2",
00046 "sparc64", "sun4u", "sparc64v",
00047 "mips", "mipsel", "IP",
00048 "ppc", "ppciseries", "ppcpseries",
00049 "ppc64", "ppc64iseries", "ppc64pseries",
00050 "m68k",
00051 "rs6000",
00052 "ia64",
00053 "armv3l", "armv4b", "armv4l",
00054 "armv5teb", "armv5tel", "armv5tejl",
00055 "armv6l",
00056 "s390", "i370", "s390x",
00057 "sh", "sh3", "sh4", "sh4a", "xtensa",
00058 "noarch", "fat",
00059 NULL,
00060 };
00061
00062
00063 nsType rpmnsArch(const char * str)
00064 {
00065 nsType rc = RPMNS_TYPE_UNKNOWN;
00066 const char ** av;
00067
00068 #if defined(RPM_VENDOR_WINDRIVER)
00069 const char * known_arch = rpmExpand("%{?_known_arch}", NULL);
00070 const char *p, *pe, *t;
00071 for (p = pe = known_arch ; rc == RPMNS_TYPE_UNKNOWN && pe && *pe ; ) {
00072 while (*p && xisspace(*p)) p++;
00073 pe = p ; while (*pe && !xisspace(*pe)) pe++;
00074 if (p == pe)
00075 break;
00076 t = strndup(p, (pe - p));
00077 p = pe;
00078 if (!strcmp(str, t))
00079 rc = RPMNS_TYPE_ARCH;
00080 t = _free(t);
00081 }
00082 known_arch = _free(known_arch);
00083 #endif
00084
00085 if (rc == RPMNS_TYPE_UNKNOWN)
00086 for (av = rpmnsArches; *av != NULL; av++) {
00087 if (strcmp(str, *av))
00088 continue;
00089 rc = RPMNS_TYPE_ARCH;
00090 break;
00091 }
00092
00093 return rc;
00094 }
00095
00099
00100 static struct _rpmnsProbes_s {
00101
00102 const char * NS;
00103 nsType Type;
00104 } rpmnsProbes[] = {
00105 { "rpmlib", RPMNS_TYPE_RPMLIB },
00106 { "config", RPMNS_TYPE_CONFIG },
00107 { "cpuinfo", RPMNS_TYPE_CPUINFO },
00108 { "getconf", RPMNS_TYPE_GETCONF },
00109 { "uname", RPMNS_TYPE_UNAME },
00110 { "soname", RPMNS_TYPE_SONAME },
00111 { "user", RPMNS_TYPE_USER },
00112 { "group", RPMNS_TYPE_GROUP },
00113 { "mounted", RPMNS_TYPE_MOUNTED },
00114 { "diskspace", RPMNS_TYPE_DISKSPACE },
00115 { "digest", RPMNS_TYPE_DIGEST },
00116 { "gnupg", RPMNS_TYPE_GNUPG },
00117 { "macro", RPMNS_TYPE_MACRO },
00118 { "envvar", RPMNS_TYPE_ENVVAR },
00119 { "running", RPMNS_TYPE_RUNNING },
00120 { "sanitycheck", RPMNS_TYPE_SANITY },
00121 { "vcheck", RPMNS_TYPE_VCHECK },
00122 { "signature", RPMNS_TYPE_SIGNATURE },
00123 { "verify", RPMNS_TYPE_VERIFY },
00124 { "exists", RPMNS_TYPE_ACCESS },
00125 { "executable", RPMNS_TYPE_ACCESS },
00126 { "readable", RPMNS_TYPE_ACCESS },
00127 { "writable", RPMNS_TYPE_ACCESS },
00128 { "RWX", RPMNS_TYPE_ACCESS },
00129 { "RWx", RPMNS_TYPE_ACCESS },
00130 { "RW_", RPMNS_TYPE_ACCESS },
00131 { "RwX", RPMNS_TYPE_ACCESS },
00132 { "Rwx", RPMNS_TYPE_ACCESS },
00133 { "Rw_", RPMNS_TYPE_ACCESS },
00134 { "R_X", RPMNS_TYPE_ACCESS },
00135 { "R_x", RPMNS_TYPE_ACCESS },
00136 { "R__", RPMNS_TYPE_ACCESS },
00137 { "rWX", RPMNS_TYPE_ACCESS },
00138 { "rWx", RPMNS_TYPE_ACCESS },
00139 { "rW_", RPMNS_TYPE_ACCESS },
00140 { "rwX", RPMNS_TYPE_ACCESS },
00141 { "rwx", RPMNS_TYPE_ACCESS },
00142 { "rw_", RPMNS_TYPE_ACCESS },
00143 { "r_X", RPMNS_TYPE_ACCESS },
00144 { "r_x", RPMNS_TYPE_ACCESS },
00145 { "r__", RPMNS_TYPE_ACCESS },
00146 { "_WX", RPMNS_TYPE_ACCESS },
00147 { "_Wx", RPMNS_TYPE_ACCESS },
00148 { "_W_", RPMNS_TYPE_ACCESS },
00149 { "_wX", RPMNS_TYPE_ACCESS },
00150 { "_wx", RPMNS_TYPE_ACCESS },
00151 { "_w_", RPMNS_TYPE_ACCESS },
00152 { "__X", RPMNS_TYPE_ACCESS },
00153 { "__x", RPMNS_TYPE_ACCESS },
00154 { "___", RPMNS_TYPE_ACCESS },
00155 { NULL, 0 }
00156 };
00157
00158 nsType rpmnsProbe(const char * str)
00159 {
00160 const struct _rpmnsProbes_s * av;
00161 size_t sn = strlen(str);
00162 size_t nb;
00163
00164 if (sn >= 5 && str[sn-1] == ')')
00165 for (av = rpmnsProbes; av->NS != NULL; av++) {
00166 nb = strlen(av->NS);
00167 if (sn > nb && str[nb] == '(' && !strncmp(str, av->NS, nb))
00168 return av->Type;
00169 }
00170 return RPMNS_TYPE_UNKNOWN;
00171 }
00172
00173 nsType rpmnsClassify(const char * str)
00174 {
00175 const char * s;
00176 nsType Type = RPMNS_TYPE_STRING;
00177
00178 if (*str == '!')
00179 str++;
00180 if (*str == '/')
00181 return RPMNS_TYPE_PATH;
00182 s = str + strlen(str);
00183 if (str[0] == '%' && str[1] == '{' && s[-1] == '}')
00184 return RPMNS_TYPE_FUNCTION;
00185 if ((s - str) > 3 && s[-3] == '.' && s[-2] == 's' && s[-1] == 'o')
00186 return RPMNS_TYPE_DSO;
00187 Type = rpmnsProbe(str);
00188 if (Type != RPMNS_TYPE_UNKNOWN)
00189 return Type;
00190 for (s = str; *s != '\0'; s++) {
00191 if (s[0] == '(' || s[strlen(s)-1] == ')')
00192 return RPMNS_TYPE_NAMESPACE;
00193 if (s[0] == '.' && s[1] == 's' && s[2] == 'o')
00194 return RPMNS_TYPE_DSO;
00195 if (s[0] == '.' && xisdigit((int)s[-1]) && xisdigit((int)s[1]))
00196 return RPMNS_TYPE_VERSION;
00197 if (_rpmns_N_at_A && _rpmns_N_at_A[0]) {
00198 if (s[0] == _rpmns_N_at_A[0] && rpmnsArch(s+1))
00199 return RPMNS_TYPE_ARCH;
00200 }
00201
00202 if (s[0] == '.')
00203 return RPMNS_TYPE_COMPOUND;
00204 }
00205 return RPMNS_TYPE_STRING;
00206
00207 }
00208
00209 int rpmnsParse(const char * str, rpmns ns)
00210 {
00211 char *t;
00212 ns->str = t = rpmExpand(str, NULL);
00213 ns->Type = rpmnsClassify(ns->str);
00214 switch (ns->Type) {
00215 case RPMNS_TYPE_ARCH:
00216 ns->NS = NULL;
00217 ns->N = ns->str;
00218 if (ns->N[0] == '!')
00219 ns->N++;
00220 if ((t = strrchr(t, _rpmns_N_at_A[0])) != NULL)
00221 *t++ = '\0';
00222 ns->A = t;
00223 break;
00224 case RPMNS_TYPE_RPMLIB:
00225 case RPMNS_TYPE_CPUINFO:
00226 case RPMNS_TYPE_GETCONF:
00227 case RPMNS_TYPE_UNAME:
00228 case RPMNS_TYPE_SONAME:
00229 case RPMNS_TYPE_ACCESS:
00230 case RPMNS_TYPE_USER:
00231 case RPMNS_TYPE_GROUP:
00232 case RPMNS_TYPE_MOUNTED:
00233 case RPMNS_TYPE_DISKSPACE:
00234 case RPMNS_TYPE_DIGEST:
00235 case RPMNS_TYPE_GNUPG:
00236 case RPMNS_TYPE_MACRO:
00237 case RPMNS_TYPE_ENVVAR:
00238 case RPMNS_TYPE_RUNNING:
00239 case RPMNS_TYPE_SANITY:
00240 case RPMNS_TYPE_VCHECK:
00241 case RPMNS_TYPE_SIGNATURE:
00242 case RPMNS_TYPE_VERIFY:
00243 ns->NS = ns->str;
00244 if (ns->NS[0] == '!')
00245 ns->NS++;
00246 if ((t = strchr(t, '(')) != NULL) {
00247 *t++ = '\0';
00248 ns->N = t;
00249 t[strlen(t)-1] = '\0';
00250 } else
00251 ns->N = NULL;
00252 ns->A = NULL;
00253 break;
00254 case RPMNS_TYPE_UNKNOWN:
00255 case RPMNS_TYPE_STRING:
00256 case RPMNS_TYPE_PATH:
00257 case RPMNS_TYPE_DSO:
00258 case RPMNS_TYPE_FUNCTION:
00259 case RPMNS_TYPE_VERSION:
00260 case RPMNS_TYPE_COMPOUND:
00261 case RPMNS_TYPE_NAMESPACE:
00262 case RPMNS_TYPE_TAG:
00263 case RPMNS_TYPE_CONFIG:
00264 default:
00265 ns->NS = NULL;
00266 ns->N = ns->str;
00267 if (ns->N[0] == '!')
00268 ns->N++;
00269 ns->A = NULL;
00270 break;
00271 }
00272 return 0;
00273 }
00274
00280 static inline unsigned char nibble(char c)
00281
00282 {
00283 if (c >= '0' && c <= '9')
00284 return (unsigned char)(c - '0');
00285 if (c >= 'A' && c <= 'F')
00286 return (unsigned char)((int)(c - 'A') + 10);
00287 if (c >= 'a' && c <= 'f')
00288 return (unsigned char)((int)(c - 'a') + 10);
00289 return '\0';
00290 }
00291
00292 rpmRC rpmnsProbeSignature(void * _ts, const char * fn, const char * sigfn,
00293 const char * pubfn, const char * pubid,
00294 int flags)
00295 {
00296 rpmts ts = _ts;
00297 pgpDig dig = rpmtsDig(ts);
00298 pgpDigParams sigp;
00299 pgpDigParams pubp;
00300 rpmuint8_t * sigpkt = NULL;
00301 size_t sigpktlen = 0;
00302 DIGEST_CTX ctx = NULL;
00303 int printing = 0;
00304 rpmRC rc = RPMRC_FAIL;
00305 int xx;
00306
00307 if (_rpmns_debug)
00308 fprintf(stderr, "==> check(%s, %s, %s, %s)\n", fn,
00309 (sigfn ? sigfn : "(null)"),
00310 (pubfn ? pubfn : "(null)"),
00311 (pubid ? pubid : "(null)"));
00312
00313
00314 if (sigfn && *sigfn) {
00315 const char * _sigfn = rpmExpand(sigfn, NULL);
00316 xx = pgpReadPkts(_sigfn, &sigpkt, &sigpktlen);
00317 if (xx != PGPARMOR_SIGNATURE) {
00318 if (_rpmns_debug)
00319 fprintf(stderr, "==> pgpReadPkts(%s) SIG %p[%u] ret %d\n", _sigfn, sigpkt, (unsigned)sigpktlen, xx);
00320 _sigfn = _free(_sigfn);
00321 goto exit;
00322 }
00323 _sigfn = _free(_sigfn);
00324 } else {
00325 const char * _sigfn = rpmExpand(fn, NULL);
00326 xx = pgpReadPkts(_sigfn, &sigpkt, &sigpktlen);
00327 if (xx != PGPARMOR_SIGNATURE) {
00328 if (_rpmns_debug)
00329 fprintf(stderr, "==> pgpReadPkts(%s) SIG %p[%u] ret %d\n", _sigfn, sigpkt, (unsigned)sigpktlen, xx);
00330 _sigfn = _free(_sigfn);
00331 goto exit;
00332 }
00333 _sigfn = _free(_sigfn);
00334 }
00335 xx = pgpPrtPkts((rpmuint8_t *)sigpkt, sigpktlen, dig, printing);
00336 if (xx) {
00337 if (_rpmns_debug)
00338 fprintf(stderr, "==> pgpPrtPkts SIG %p[%u] ret %d\n", sigpkt, (unsigned)sigpktlen, xx);
00339 goto exit;
00340 }
00341
00342 sigp = pgpGetSignature(dig);
00343
00344 if (sigp->version != (rpmuint8_t)3 && sigp->version != (rpmuint8_t)4) {
00345 if (_rpmns_debug)
00346 fprintf(stderr, "==> unverifiable V%u\n", (unsigned)sigp->version);
00347 goto exit;
00348 }
00349
00350
00351 if (pubfn && *pubfn) {
00352 const char * _pubfn = rpmExpand(pubfn, NULL);
00353
00354 xx = pgpReadPkts(_pubfn, &ts->pkpkt, &ts->pkpktlen);
00355
00356 if (xx != PGPARMOR_PUBKEY) {
00357 if (_rpmns_debug)
00358 fprintf(stderr, "==> pgpReadPkts(%s) PUB %p[%u] ret %d\n", _pubfn, ts->pkpkt, (unsigned int)ts->pkpktlen, xx);
00359 _pubfn = _free(_pubfn);
00360 goto exit;
00361 }
00362 _pubfn = _free(_pubfn);
00363 xx = pgpPrtPkts((rpmuint8_t *)ts->pkpkt, ts->pkpktlen, dig, printing);
00364 if (xx) {
00365 if (_rpmns_debug)
00366 fprintf(stderr, "==> pgpPrtPkts PUB %p[%u] ret %d\n", ts->pkpkt, (unsigned int)ts->pkpktlen, xx);
00367 goto exit;
00368 }
00369 } else {
00370 if ((rc = pgpFindPubkey(dig)) != RPMRC_OK) {
00371 if (_rpmns_debug)
00372 fprintf(stderr, "==> pgpFindPubkey ret %d\n", xx);
00373 goto exit;
00374 }
00375 }
00376
00377 pubp = pgpGetPubkey(dig);
00378
00379
00380 if (pubid && *pubid) {
00381 size_t ns = strlen(pubid);
00382 const char * s;
00383 char * t;
00384 size_t i;
00385
00386
00387 for (i = 0, s = pubid; *s && isxdigit(*s); s++, i++)
00388 {};
00389 if (!(*s == '\0' && i > 8 && (i%2) == 0))
00390 goto exit;
00391
00392
00393 s = pubid;
00394 if (ns > 16) {
00395 s += (ns - 16);
00396 ns = 16;
00397 }
00398 ns >>= 1;
00399 t = memset(alloca(ns), 0, ns);
00400 for (i = 0; i < ns; i++)
00401 t[i] = (char)((nibble(s[2*i]) << 4) | nibble(s[2*i+1]));
00402
00403
00404 s = (const char *)pubp->signid;
00405 xx = memcmp(t, s + (8 - ns), ns);
00406
00407
00408 if (pubp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_RSA)
00409 xx = 0;
00410
00411 if (xx) {
00412 if (_rpmns_debug)
00413 fprintf(stderr, "==> mismatched: pubkey id (%08x %08x) != %s\n",
00414 pgpGrab(pubp->signid, 4), pgpGrab(pubp->signid+4, 4), pubid);
00415 goto exit;
00416 }
00417 }
00418
00419
00420 if (!(sigp->pubkey_algo == pubp->pubkey_algo
00421 #ifdef NOTYET
00422 && sigp->hash_algo == pubp->hash_algo
00423 #endif
00424
00425 && (pubp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_RSA || !memcmp(sigp->signid, pubp->signid, sizeof(sigp->signid))) ) ) {
00426 if (_rpmns_debug) {
00427 fprintf(stderr, "==> mismatch between signature and pubkey\n");
00428 fprintf(stderr, "\tpubkey_algo: %u %u\n", (unsigned)sigp->pubkey_algo, (unsigned)pubp->pubkey_algo);
00429 fprintf(stderr, "\tsignid: %08X %08X %08X %08X\n",
00430 pgpGrab(sigp->signid, 4), pgpGrab(sigp->signid+4, 4),
00431 pgpGrab(pubp->signid, 4), pgpGrab(pubp->signid+4, 4));
00432 }
00433 goto exit;
00434 }
00435
00436
00437 ctx = rpmDigestInit((pgpHashAlgo)sigp->hash_algo, RPMDIGEST_NONE);
00438
00439 {
00440 static const char clrtxt[] = "-----BEGIN PGP SIGNED MESSAGE-----";
00441 static const char sigtxt[] = "-----BEGIN PGP SIGNATURE-----";
00442 const char * _fn = rpmExpand(fn, NULL);
00443 rpmiob iob = NULL;
00444 int _rc = rpmiobSlurp(_fn, &iob);
00445
00446 if (!(_rc == 0 && iob != NULL)) {
00447 if (_rpmns_debug)
00448 fprintf(stderr, "==> rpmiobSlurp(%s) MSG ret %d\n", _fn, _rc);
00449 iob = rpmiobFree(iob);
00450 _fn = _free(_fn);
00451 goto exit;
00452 }
00453 _fn = _free(_fn);
00454
00455
00456 if (!strncmp((char *)iob->b, clrtxt, strlen(clrtxt))) {
00457 const char * be = (char *) (iob->b + iob->blen);
00458 const char * t;
00459
00460
00461 t = (char *) iob->b;
00462 while (t && t < be && *t != '\n')
00463 t = strchr(t, '\n') + 1;
00464 if (!(t && t < be))
00465 goto exit;
00466 t++;
00467
00468
00469 while (t < be) {
00470 const char * teol;
00471 const char * te;
00472 if (strncmp(t, "- ", 2) == 0)
00473 t += 2;
00474 if ((teol = te = strchr(t, '\n')) == NULL)
00475 break;
00476 while (te > t && strchr(" \t\r\n", te[-1]))
00477 te--;
00478 xx = rpmDigestUpdate(ctx, t, (te - t));
00479 if (!strncmp((t = teol + 1), sigtxt, strlen(sigtxt)))
00480 break;
00481 xx = rpmDigestUpdate(ctx, "\r\n", sizeof("\r\n")-1);
00482 }
00483 } else
00484 xx = rpmDigestUpdate(ctx, iob->b, iob->blen);
00485
00486 iob = rpmiobFree(iob);
00487 }
00488
00489 if (sigp->hash != NULL)
00490 xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
00491 if (sigp->version == (rpmuint8_t)4) {
00492 rpmuint32_t nb = (rpmuint32_t)sigp->hashlen;
00493 rpmuint8_t trailer[6];
00494 nb = (rpmuint32_t)htonl(nb);
00495 trailer[0] = sigp->version;
00496 trailer[1] = (rpmuint8_t)0xff;
00497 memcpy(trailer+2, &nb, sizeof(nb));
00498 xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
00499 }
00500
00501
00502 switch(sigp->pubkey_algo) {
00503 default:
00504 rc = RPMRC_FAIL;
00505 break;
00506 case PGPPUBKEYALGO_DSA:
00507 rc = (pgpImplSetDSA(ctx, dig, sigp) ? RPMRC_FAIL : RPMRC_OK);
00508 break;
00509 case PGPPUBKEYALGO_RSA:
00510 rc = (pgpImplSetRSA(ctx, dig, sigp) ? RPMRC_FAIL : RPMRC_OK);
00511 break;
00512 }
00513 if (rc != RPMRC_OK) {
00514 if (_rpmns_debug)
00515 fprintf(stderr, "==> can't load pubkey_algo(%u)\n", (unsigned)sigp->pubkey_algo);
00516 goto exit;
00517 }
00518
00519
00520 switch(sigp->pubkey_algo) {
00521 default:
00522 rc = RPMRC_FAIL;
00523 break;
00524 case PGPPUBKEYALGO_DSA:
00525 rc = (pgpImplVerifyDSA(dig) ? RPMRC_OK : RPMRC_FAIL);
00526 break;
00527 case PGPPUBKEYALGO_RSA:
00528 rc = (pgpImplVerifyRSA(dig) ? RPMRC_OK : RPMRC_FAIL);
00529 break;
00530 }
00531
00532 exit:
00533 sigpkt = _free(sigpkt);
00534 ts->pkpkt = _free(ts->pkpkt);
00535 ts->pkpktlen = 0;
00536
00537 rpmtsCleanDig(ts);
00538
00539
00540 if (_rpmns_debug)
00541 fprintf(stderr, "============================ verify: %s\n",
00542 (rc == RPMRC_OK ? "OK" :
00543 (rc == RPMRC_NOKEY ? "NOKEY" :
00544 "FAIL")));
00545
00546 return rc;
00547 }