rpm  5.4.10
rpmns.c
Go to the documentation of this file.
1 
4 #include "system.h"
5 
6 #define _RPMIOB_INTERNAL /* XXX rpmiobSlurp */
7 #include <rpmiotypes.h>
8 #include <rpmio.h>
9 #define _RPMHKP_INTERNAL
10 #include <rpmhkp.h>
11 #include <rpmmacro.h>
12 #include <rpmcb.h>
13 
14 #define _RPMPGP_INTERNAL
15 #include <rpmpgp.h>
16 
17 #include <rpmtypes.h>
18 #include <rpmtag.h>
19 #define _RPMEVR_INTERNAL
20 #include <rpmevr.h>
21 #define _RPMNS_INTERNAL
22 #include <rpmns.h>
23 #include <rpmdb.h>
24 
25 #include <rpmps.h>
26 #define _RPMTS_INTERNAL /* XXX ts->hkp */
27 #include <rpmts.h>
28 
29 #include "debug.h"
30 
31 /*@access rpmts @*/
32 /*@access pgpDigParams @*/
33 /*@access rpmiob @*/
34 
35 #ifdef __cplusplus
36 GENfree(rpmuint8_t **)
37 #endif /* __cplusplus */
38 
39 /*@unchecked@*/
40 int _rpmns_debug = 0;
41 
42 /*@unchecked@*/ /*@observer@*/ /*@relnull@*/
43 const char *_rpmns_N_at_A = ".";
44 
45 /*@-nullassign@*/
46 /*@unchecked@*/ /*@observer@*/
47 static const char *rpmnsArches[] = {
48  "i386", "i486", "i586", "i686", "athlon", "pentium3", "pentium4",
49  "x86_64", "amd64", "ia32e",
50  "alpha", "alphaev5", "alphaev56", "alphapca56", "alphaev6", "alphaev67",
51  "sparc", "sun4", "sun4m", "sun4c", "sun4d", "sparcv8",
52  "sparcv9", "sparcv9b", "sparcv9v", "sparcv9v2",
53  "sparc64", "sun4u", "sparc64v",
54  "mips", "mipsel", "IP",
55  "ppc", "ppciseries", "ppcpseries",
56  "ppc64", "ppc64iseries", "ppc64pseries",
57  "m68k",
58  "rs6000",
59  "ia64",
60  "armv3l", "armv4b", "armv4l",
61  "armv5teb", "armv5tel", "armv5tejl",
62  "armv6l",
63  "s390", "i370", "s390x",
64  "sh", "sh3", "sh4", "sh4a", "xtensa",
65  "noarch", "fat",
66  NULL,
67 };
68 /*@=nullassign@*/
69 
70 nsType rpmnsArch(const char * str)
71 {
73  const char ** av;
74 
75 #if defined(RPM_VENDOR_WINDRIVER)
76  const char * known_arch = rpmExpand("%{?_known_arch}", NULL);
77  const char *p, *pe, *t;
78  for (p = pe = known_arch ; rc == RPMNS_TYPE_UNKNOWN && pe && *pe ; ) {
79  while (*p && xisspace(*p)) p++;
80  pe = p ; while (*pe && !xisspace(*pe)) pe++;
81  if (p == pe)
82  break;
83  t = strndup(p, (pe - p));
84  p = pe;
85  if (!strcmp(str, t))
86  rc = RPMNS_TYPE_ARCH;
87  t = _free(t);
88  }
89  known_arch = _free(known_arch);
90 #endif
91 
92  if (rc == RPMNS_TYPE_UNKNOWN)
93  for (av = rpmnsArches; *av != NULL; av++) {
94  if (strcmp(str, *av))
95  continue;
96  rc = RPMNS_TYPE_ARCH;
97  break;
98  }
99 
100  return rc;
101 }
102 
106 /*@unchecked@*/ /*@observer@*/
107 #define _ENTRY(_s, _type) { #_s, sizeof(#_s)-1, _type }
108 static struct _rpmnsProbes_s {
109 /*@observer@*/ /*@relnull@*/
110  const char * NS;
111  size_t NSlen;
113 } rpmnsProbes[] = {
132  _ENTRY(config, RPMNS_TYPE_CONFIG),
133  _ENTRY(cpuinfo, RPMNS_TYPE_CPUINFO),
134  _ENTRY(digest, RPMNS_TYPE_DIGEST),
135  _ENTRY(diskspace, RPMNS_TYPE_DISKSPACE),
136  _ENTRY(dpkg, RPMNS_TYPE_DPKG),
137  _ENTRY(envvar, RPMNS_TYPE_ENVVAR),
138  _ENTRY(executable, RPMNS_TYPE_ACCESS),
139  _ENTRY(exists, RPMNS_TYPE_ACCESS),
140  _ENTRY(getconf, RPMNS_TYPE_GETCONF),
141  _ENTRY(gnupg, RPMNS_TYPE_GNUPG),
142  _ENTRY(group, RPMNS_TYPE_GROUP),
143  _ENTRY(macro, RPMNS_TYPE_MACRO),
144  _ENTRY(mounted, RPMNS_TYPE_MOUNTED),
151  _ENTRY(readable, RPMNS_TYPE_ACCESS),
152  _ENTRY(rpmlib, RPMNS_TYPE_RPMLIB),
153  _ENTRY(running, RPMNS_TYPE_RUNNING),
157  _ENTRY(sanitycheck, RPMNS_TYPE_SANITY),
158  _ENTRY(set, RPMNS_TYPE_SET),
159  _ENTRY(signature, RPMNS_TYPE_SIGNATURE),
160  _ENTRY(soname, RPMNS_TYPE_SONAME),
161  _ENTRY(uname, RPMNS_TYPE_UNAME),
162  _ENTRY(user, RPMNS_TYPE_USER),
163  _ENTRY(vcheck, RPMNS_TYPE_VCHECK),
164  _ENTRY(verify, RPMNS_TYPE_VERIFY),
165  _ENTRY(writable, RPMNS_TYPE_ACCESS),
166 };
167 #undef _ENTRY
168 static size_t rpmnsProbesCount = sizeof(rpmnsProbes)/sizeof(rpmnsProbes[0]);
169 
170 nsType rpmnsProbe(const char * s, size_t slen)
171 {
172  const char * se = strchr(s, ')');
173  size_t l, u;
174 
175  /* XXX Don't bother if string cannot be "NS(N).A" */
176  if (se == NULL || (slen = (se - s)) < sizeof("ABC()")-1)
177  return RPMNS_TYPE_UNKNOWN;
178 
179  l = 0;
180  u = rpmnsProbesCount;
181  while (l < u) {
182  size_t i = (l + u)/2;
183  struct _rpmnsProbes_s * av = rpmnsProbes + i;
184  size_t NSlen = (slen > av->NSlen) ? av->NSlen : slen;
185  int rc = strncmp(s, av->NS, NSlen);
186 
187  if (rc == 0)
188  return (s[NSlen] == '(' ? rpmnsProbes[i].Type : RPMNS_TYPE_UNKNOWN);
189  else if (rc < 0)
190  u = i;
191  else if (rc > 0)
192  l = i + 1;
193  }
194  return RPMNS_TYPE_UNKNOWN;
195 }
196 
197 nsType rpmnsClassify(const char * s, size_t slen)
198 {
199  const char * se;
200  nsType Type;
201 
202  if (slen == 0) slen = strlen(s);
203  if (*s == '!') {
204  s++;
205  slen--;
206  }
207  if (*s == '/')
208  return RPMNS_TYPE_PATH;
209  se = s + slen;
210  if (s[0] == '%' && s[1] == '{' && se[-1] == '}')
211  return RPMNS_TYPE_FUNCTION;
212  if ((se - s) > 3 && se[-3] == '.' && se[-2] == 's' && se[-1] == 'o')
213  return RPMNS_TYPE_DSO;
214  Type = rpmnsProbe(s, slen);
215  if (Type != RPMNS_TYPE_UNKNOWN)
216  return Type;
217  for (se = s; *se != '\0'; se++) {
218  if (se[0] == '(' || se[--slen] == ')')
219  return RPMNS_TYPE_NAMESPACE;
220  if (se[0] == '.' && se[1] == 's' && se[2] == 'o')
221  return RPMNS_TYPE_DSO;
222  if (se[0] == '.' && xisdigit((int)se[-1]) && xisdigit((int)se[1]))
223  return RPMNS_TYPE_VERSION;
224  if (_rpmns_N_at_A && _rpmns_N_at_A[0]) {
225  if (se[0] == _rpmns_N_at_A[0] && rpmnsArch(se+1))
226  return RPMNS_TYPE_ARCH;
227  }
228 /*@-globstate@*/
229  if (se[0] == '.')
230  return RPMNS_TYPE_COMPOUND;
231  }
232  return RPMNS_TYPE_STRING;
233 /*@=globstate@*/
234 }
235 
236 int rpmnsParse(const char * s, rpmns ns)
237 {
238  char * t = rpmExpand(s, NULL);
239  size_t tlen = strlen(t);
240 
241  ns->Flags = (evrFlags) 0;
242  ns->str = t;
243  ns->Type = rpmnsClassify(t, tlen);
244 
245  switch (ns->Type) {
246  case RPMNS_TYPE_ARCH:
247  ns->NS = NULL;
248  ns->N = ns->str;
249  if (ns->N[0] == '!')
250  ns->N++;
251  if ((t = strrchr(t, _rpmns_N_at_A[0])) != NULL)
252  *t++ = '\0';
253  ns->A = t;
254  break;
255  case RPMNS_TYPE_RPMLIB:
256  case RPMNS_TYPE_CPUINFO:
257  case RPMNS_TYPE_GETCONF:
258  case RPMNS_TYPE_UNAME:
259  case RPMNS_TYPE_SONAME:
260  case RPMNS_TYPE_ACCESS:
261  case RPMNS_TYPE_USER:
262  case RPMNS_TYPE_GROUP:
263  case RPMNS_TYPE_MOUNTED:
265  case RPMNS_TYPE_DIGEST:
266  case RPMNS_TYPE_GNUPG:
267  case RPMNS_TYPE_MACRO:
268  case RPMNS_TYPE_ENVVAR:
269  case RPMNS_TYPE_RUNNING:
270  case RPMNS_TYPE_SANITY:
271  case RPMNS_TYPE_VCHECK:
273  case RPMNS_TYPE_VERIFY:
274  ns->NS = ns->str;
275  if (ns->NS[0] == '!')
276  ns->NS++;
277  if ((t = strchr(t, '(')) != NULL) {
278  *t++ = '\0';
279  ns->N = t;
280  t[strlen(t)-1] = '\0';
281  } else
282  ns->N = NULL;
283  ns->A = NULL;
284  break;
285  case RPMNS_TYPE_UNKNOWN:
286  case RPMNS_TYPE_STRING:
287  case RPMNS_TYPE_PATH:
288  case RPMNS_TYPE_DSO:
289  case RPMNS_TYPE_FUNCTION:
290  case RPMNS_TYPE_VERSION:
291  case RPMNS_TYPE_COMPOUND:
293  case RPMNS_TYPE_TAG:
294  case RPMNS_TYPE_CONFIG:
295  default:
296  ns->NS = NULL;
297  ns->N = ns->str;
298  if (ns->N[0] == '!')
299  ns->N++;
300  ns->A = NULL;
301  break;
302  }
303  return 0;
304 }
305 
311 static inline unsigned char nibble(char c)
312  /*@*/
313 {
314  if (c >= '0' && c <= '9')
315  return (unsigned char)(c - '0');
316  if (c >= 'A' && c <= 'F')
317  return (unsigned char)((int)(c - 'A') + 10);
318  if (c >= 'a' && c <= 'f')
319  return (unsigned char)((int)(c - 'a') + 10);
320  return '\0';
321 }
322 
323 rpmRC rpmnsProbeSignature(void * _ts, const char * fn, const char * sigfn,
324  const char * pubfn, const char * pubid,
325  /*@unused@*/ int flags)
326 {
327  rpmts ts = (rpmts) _ts;
328  pgpDig dig = rpmtsDig(ts);
329  pgpDigParams sigp = pgpGetSignature(dig);
330  pgpDigParams pubp = pgpGetPubkey(dig);
331  rpmuint8_t * sigpkt = NULL;
332  size_t sigpktlen = 0;
333  DIGEST_CTX ctx = NULL;
334  rpmRC rc = RPMRC_FAIL; /* assume failure */
335  int xx;
336 rpmhkp hkp = NULL;
337 pgpPkt pp = (pgpPkt) alloca(sizeof(*pp));
338 size_t pleft;
339 int validate = 1;
340 
341 if (_rpmns_debug)
342 fprintf(stderr, "==> check(%s, %s, %s, %s)\n", fn,
343 (sigfn ? sigfn : "(null)"),
344 (pubfn ? pubfn : "(null)"),
345 (pubid ? pubid : "(null)"));
346 
347  /* Load the signature. Use sigfn if specified, otherwise clearsign. */
348  if (sigfn && *sigfn) {
349  const char * _sigfn = rpmExpand(sigfn, NULL);
350  xx = pgpReadPkts(_sigfn, &sigpkt, &sigpktlen);
351  if (xx != PGPARMOR_SIGNATURE) {
352 if (_rpmns_debug)
353 fprintf(stderr, "==> pgpReadPkts(%s) SIG %p[%u] ret %d\n", _sigfn, sigpkt, (unsigned)sigpktlen, xx);
354  _sigfn = _free(_sigfn);
355  goto exit;
356  }
357  _sigfn = _free(_sigfn);
358  } else {
359  const char * _sigfn = rpmExpand(fn, NULL);
360  xx = pgpReadPkts(_sigfn, &sigpkt, &sigpktlen);
361  if (xx != PGPARMOR_SIGNATURE) {
362 if (_rpmns_debug)
363 fprintf(stderr, "==> pgpReadPkts(%s) SIG %p[%u] ret %d\n", _sigfn, sigpkt, (unsigned)sigpktlen, xx);
364  _sigfn = _free(_sigfn);
365  goto exit;
366  }
367  _sigfn = _free(_sigfn);
368  }
369 
370  pleft = sigpktlen;
371  xx = pgpPktLen(sigpkt, pleft, pp);
372  xx = rpmhkpLoadSignature(NULL, dig, pp);
373  if (xx) goto exit;
374 
375  if (sigp->version != (rpmuint8_t)3 && sigp->version != (rpmuint8_t)4) {
376 if (_rpmns_debug)
377 fprintf(stderr, "==> unverifiable V%u\n", (unsigned)sigp->version);
378  goto exit;
379  }
380 
381  if (ts->hkp == NULL)
382  ts->hkp = rpmhkpNew(NULL, 0);
383  hkp = rpmhkpLink(ts->hkp);
384 
385  /* Load the pubkey. Use pubfn if specified, otherwise rpmdb keyring. */
386  if (pubfn && *pubfn) {
387  const char * _pubfn = rpmExpand(pubfn, NULL);
388 /*@-type@*/
389 hkp->pkt = _free(hkp->pkt); /* XXX memleaks */
390 hkp->pktlen = 0;
391  xx = pgpReadPkts(_pubfn, &hkp->pkt, &hkp->pktlen);
392 /*@=type@*/
393  if (xx != PGPARMOR_PUBKEY) {
394 if (_rpmns_debug)
395 fprintf(stderr, "==> pgpReadPkts(%s) PUB %p[%u] ret %d\n", _pubfn, hkp->pkt, (unsigned)hkp->pktlen, xx);
396  _pubfn = _free(_pubfn);
397  goto exit;
398  }
399  _pubfn = _free(_pubfn);
400 
401  /* Split the result into packet array. */
402 hkp->pkts = _free(hkp->pkts); /* XXX memleaks */
403 hkp->npkts = 0;
404  xx = pgpGrabPkts(hkp->pkt, hkp->pktlen, &hkp->pkts, &hkp->npkts);
405 
406  if (!xx)
407  (void) pgpPubkeyFingerprint(hkp->pkt, hkp->pktlen, hkp->keyid);
408  memcpy(pubp->signid, hkp->keyid, sizeof(pubp->signid));/* XXX useless */
409 
410  /* Validate pubkey self-signatures. */
411  if (validate) {
412  xx = rpmhkpValidate(hkp, NULL);
413  switch (xx) {
414  case RPMRC_OK:
415  break;
416  case RPMRC_NOTFOUND:
417  case RPMRC_FAIL: /* XXX remap to NOTFOUND? */
418  case RPMRC_NOTTRUSTED:
419  case RPMRC_NOKEY:
420  default:
421  rc = (rpmRC)xx;
422  goto exit;
423  }
424  }
425 
426  /* Retrieve parameters from pubkey/subkey packet(s). */
427  xx = rpmhkpFindKey(hkp, dig, sigp->signid, sigp->pubkey_algo);
428  if (xx) goto exit;
429 
430 #ifdef DYING
431 _rpmhkpDumpDig(__FUNCTION__, dig);
432 #endif
433  } else {
434  if ((rc = (rpmRC)pgpFindPubkey(dig)) != RPMRC_OK) {
435 if (_rpmns_debug)
436 fprintf(stderr, "==> pgpFindPubkey ret %d\n", xx);
437  goto exit;
438  }
439  }
440 
441  /* Is this the requested pubkey? */
442  if (pubid && *pubid) {
443  size_t ns = strlen(pubid);
444  const char * s;
445  char * t;
446  size_t i;
447 
448  /* At least 8 hex digits please. */
449  for (i = 0, s = pubid; *s && isxdigit(*s); s++, i++)
450  {};
451  if (!(*s == '\0' && i > 8 && (i%2) == 0))
452  goto exit;
453 
454  /* Truncate to key id size. */
455  s = pubid;
456  if (ns > 16) {
457  s += (ns - 16);
458  ns = 16;
459  }
460  ns >>= 1;
461  t = (char *) memset(alloca(ns), 0, ns);
462  for (i = 0; i < ns; i++)
463  t[i] = (char)((nibble(s[2*i]) << 4) | nibble(s[2*i+1]));
464 
465  /* Compare the pubkey id. */
466  s = (const char *)pubp->signid;
467  xx = memcmp(t, s + (8 - ns), ns);
468 
469  /* XXX HACK: V4 RSA key id's are wonky atm. */
470  if (pubp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_RSA)
471  xx = 0;
472 
473  if (xx) {
474 if (_rpmns_debug)
475 fprintf(stderr, "==> mismatched: pubkey id (%08x %08x) != %s\n",
476 pgpGrab(pubp->signid, 4), pgpGrab(pubp->signid+4, 4), pubid);
477  goto exit;
478  }
479  }
480 
481  /* Do the parameters match the signature? */
482  if (!(sigp->pubkey_algo == pubp->pubkey_algo
483 #ifdef NOTYET
484  && sigp->hash_algo == pubp->hash_algo
485 #endif
486  /* XXX HACK: V4 RSA key id's are wonky atm. */
487  && (pubp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_RSA || !memcmp(sigp->signid, pubp->signid, sizeof(sigp->signid))) ) ) {
488 if (_rpmns_debug) {
489 fprintf(stderr, "==> mismatch between signature and pubkey\n");
490 fprintf(stderr, "\tpubkey_algo: %u %u\n", (unsigned)sigp->pubkey_algo, (unsigned)pubp->pubkey_algo);
491 fprintf(stderr, "\tsignid: %08X %08X %08X %08X\n",
492 pgpGrab(sigp->signid, 4), pgpGrab(sigp->signid+4, 4),
493 pgpGrab(pubp->signid, 4), pgpGrab(pubp->signid+4, 4));
494 }
495  goto exit;
496  }
497 
498  /* Compute the message digest. */
499  ctx = rpmDigestInit((pgpHashAlgo)sigp->hash_algo, RPMDIGEST_NONE);
500 
501  {
502  static const char clrtxt[] = "-----BEGIN PGP SIGNED MESSAGE-----";
503  static const char sigtxt[] = "-----BEGIN PGP SIGNATURE-----";
504  const char * _fn = rpmExpand(fn, NULL);
505  rpmiob iob = NULL;
506  int _rc = rpmiobSlurp(_fn, &iob);
507 
508  if (!(_rc == 0 && iob != NULL)) {
509 if (_rpmns_debug)
510 fprintf(stderr, "==> rpmiobSlurp(%s) MSG ret %d\n", _fn, _rc);
511  iob = rpmiobFree(iob);
512  _fn = _free(_fn);
513  goto exit;
514  }
515  _fn = _free(_fn);
516 
517  /* XXX clearsign sig is PGPSIGTYPE_TEXT not PGPSIGTYPE_BINARY. */
518  if (!strncmp((char *)iob->b, clrtxt, strlen(clrtxt))) {
519  const char * be = (char *) (iob->b + iob->blen);
520  const char * t;
521 
522  /* Skip to '\n\n' start-of-plaintext */
523  t = (char *) iob->b;
524  while (t && t < be && *t != '\n')
525  t = strchr(t, '\n') + 1;
526  if (!(t && t < be))
527  goto exit;
528  t++;
529 
530  /* Clearsign digest rtrims " \t\r\n", inserts "\r\n" inter-lines. */
531  while (t < be) {
532  const char * teol;
533  const char * te;
534  if (strncmp(t, "- ", 2) == 0)
535  t += 2;
536  if ((teol = te = strchr(t, '\n')) == NULL)
537  break;
538  while (te > t && strchr(" \t\r\n", te[-1]))
539  te--;
540  xx = rpmDigestUpdate(ctx, t, (te - t));
541  if (!strncmp((t = teol + 1), sigtxt, strlen(sigtxt)))
542  break;
543  xx = rpmDigestUpdate(ctx, "\r\n", sizeof("\r\n")-1);
544  }
545  } else
546  xx = rpmDigestUpdate(ctx, iob->b, iob->blen);
547 
548  iob = rpmiobFree(iob);
549  }
550 
551  if (sigp->hash != NULL)
552  xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
553 
554  if (sigp->version == (rpmuint8_t)4) {
555  rpmuint8_t trailer[6];
556  trailer[0] = sigp->version;
557  trailer[1] = (rpmuint8_t)0xff;
558  trailer[2] = (sigp->hashlen >> 24) & 0xff;
559  trailer[3] = (sigp->hashlen >> 16) & 0xff;
560  trailer[4] = (sigp->hashlen >> 8) & 0xff;
561  trailer[5] = (sigp->hashlen ) & 0xff;
562  xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
563  }
564 
565  /* Load the message digest. */
566  switch(sigp->pubkey_algo) {
567  default:
568  rc = RPMRC_FAIL;
569  break;
570  case PGPPUBKEYALGO_DSA:
571  rc = (pgpImplSetDSA(ctx, dig, sigp) ? RPMRC_FAIL : RPMRC_OK);
572  break;
573  case PGPPUBKEYALGO_RSA:
574  rc = (pgpImplSetRSA(ctx, dig, sigp) ? RPMRC_FAIL : RPMRC_OK);
575  break;
576  }
577  if (rc != RPMRC_OK) {
578 if (_rpmns_debug)
579 fprintf(stderr, "==> can't load pubkey_algo(%u)\n", (unsigned)sigp->pubkey_algo);
580  goto exit;
581  }
582 
583  /* Verify the signature. */
584  switch(sigp->pubkey_algo) {
585  default:
586  rc = RPMRC_FAIL;
587  break;
588  case PGPPUBKEYALGO_RSA:
589  case PGPPUBKEYALGO_DSA:
590  rc = (pgpImplVerify(dig) ? RPMRC_OK : RPMRC_FAIL);
591  break;
592  }
593 
594 exit:
595  sigpkt = _free(sigpkt);
596  (void) rpmhkpFree(hkp);
597  hkp = NULL;
598 /*@-nullstate@*/
599  rpmtsCleanDig(ts);
600 /*@=nullstate@*/
601 
602 if (_rpmns_debug)
603 fprintf(stderr, "============================ verify: %s\n",
604  (rc == RPMRC_OK ? "OK" :
605  (rc == RPMRC_NOKEY ? "NOKEY" :
606  "FAIL")));
607 
608  return rc;
609 }