rpm  5.4.14
signature.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include <rpmio.h>
8 #include <rpmurl.h>
9 #include <rpmcb.h> /* XXX rpmIsVerbose() */
10 #define _RPMPGP_INTERNAL
11 #include <rpmpgp.h>
12 #include <rpmmacro.h> /* XXX for rpmGetPath() */
13 #include <rpmhkp.h>
14 #include <rpmku.h>
15 
16 #include <rpmtag.h>
17 #include "rpmdb.h"
18 #include <pkgio.h> /* XXX expects <rpmts.h> */
19 #include "legacy.h" /* XXX for dodogest() */
20 #include "signature.h"
21 
22 #include "debug.h"
23 
24 /*@access FD_t@*/ /* XXX ufdio->read arg1 is void ptr */
25 /*@access Header@*/ /* XXX compared with NULL */
26 /*@access DIGEST_CTX@*/ /* XXX compared with NULL */
27 /*@access pgpDig@*/
28 /*@access pgpDigParams@*/
29 
30 int rpmTempFile(const char * prefix, const char ** fnptr, void * fdptr)
31 {
32  const char * tpmacro = "%{?_tmppath}%{!?_tmppath:/var/tmp/}";
33  const char * tempfn = NULL;
34  const char * tfn = NULL;
35  static int _initialized = 0;
36  int temput;
37  FD_t fd = NULL;
38  unsigned int ran;
39 
40  if (!prefix) prefix = "";
41 
42  /* Create the temp directory if it doesn't already exist. */
43  if (!_initialized) {
44  _initialized = 1;
45  tempfn = rpmGenPath(prefix, tpmacro, NULL);
46  if (rpmioMkpath(tempfn, 0755, (uid_t) -1, (gid_t) -1))
47  goto errxit;
48  }
49 
50  /* XXX should probably use mkstemp here */
51  ran = (unsigned) time(NULL);
52  srand(ran);
53  ran = rand() % 100000;
54 
55  /* maybe this should use link/stat? */
56 
57  do {
58  char tfnbuf[64];
59 #ifndef NOTYET
60  sprintf(tfnbuf, "rpm-tmp.%u", ran++);
61  tempfn = _free(tempfn);
62  tempfn = rpmGenPath(prefix, tpmacro, tfnbuf);
63 #else
64  strcpy(tfnbuf, "rpm-tmp.XXXXXX");
65  tempfn = _free(tempfn);
66  tempfn = rpmGenPath(prefix, tpmacro, mktemp(tfnbuf));
67 #endif
68 
69  temput = urlPath(tempfn, &tfn);
70  if (*tfn == '\0') goto errxit;
71 
72  switch (temput) {
73  case URL_IS_DASH:
74  case URL_IS_HKP:
75  case URL_IS_MONGO: /* XXX FIXME */
76  goto errxit;
77  /*@notreached@*/ /*@switchbreak@*/ break;
78  case URL_IS_HTTPS:
79  case URL_IS_HTTP:
80  case URL_IS_FTP:
81  default:
82  /*@switchbreak@*/ break;
83  }
84 
85  fd = Fopen(tempfn, "w+x.fdio");
86  /* XXX FIXME: errno may not be correct for ufdio */
87  } while ((fd == NULL || Ferror(fd)) && errno == EEXIST);
88 
89  if (fd == NULL || Ferror(fd)) {
90  rpmlog(RPMLOG_ERR, _("error creating temporary file %s\n"), tempfn);
91  goto errxit;
92  }
93 
94  switch(temput) {
95  case URL_IS_PATH:
96  case URL_IS_UNKNOWN:
97  { struct stat sb, sb2;
98  if (!stat(tfn, &sb) && S_ISLNK(sb.st_mode)) {
99  rpmlog(RPMLOG_ERR, _("error creating temporary file %s\n"), tfn);
100  goto errxit;
101  }
102 
103  if (sb.st_nlink != 1) {
104  rpmlog(RPMLOG_ERR, _("error creating temporary file %s\n"), tfn);
105  goto errxit;
106  }
107 
108  if (fstat(Fileno(fd), &sb2) == 0) {
109  if (sb2.st_ino != sb.st_ino || sb2.st_dev != sb.st_dev) {
110  rpmlog(RPMLOG_ERR, _("error creating temporary file %s\n"), tfn);
111  goto errxit;
112  }
113  }
114  } break;
115  default:
116  break;
117  }
118 
119  if (fnptr)
120  *fnptr = tempfn;
121  else
122  tempfn = _free(tempfn);
123  if (fdptr)
124  *(FD_t *)fdptr = fd;
125 
126  return 0;
127 
128 errxit:
129  tempfn = _free(tempfn);
130  if (fnptr)
131  *fnptr = NULL;
132  /*@-usereleased@*/
133  if (fd != NULL) (void) Fclose(fd);
134  /*@=usereleased@*/
135  return 1;
136 }
137 
138 
148 static int makeGPGSignature(const char * file, rpmSigTag * sigTagp,
149  /*@out@*/ rpmuint8_t ** pktp, /*@out@*/ rpmuint32_t * pktlenp,
150  /*@null@*/ const char * passPhrase)
151  /*@globals rpmGlobalMacroContext, h_errno,
152  fileSystem, internalState @*/
153  /*@modifies *pktp, *pktlenp, *sigTagp, rpmGlobalMacroContext,
154  fileSystem, internalState @*/
155 {
156  char * sigfile = (char *) alloca(strlen(file)+sizeof(".sig"));
157  pid_t pid;
158  int status;
159  int inpipe[2];
160  FILE * fpipe;
161  struct stat st;
162  const char * cmd;
163  char *const *av;
164  pgpDig dig = NULL;
166  const char * pw = NULL;
167  int rc;
168 
169  (void) stpcpy( stpcpy(sigfile, file), ".sig");
170 
171  addMacro(NULL, "__plaintext_filename", NULL, file, -1);
172  addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
173 
174  inpipe[0] = inpipe[1] = 0;
175  if (pipe(inpipe) < 0) {
176  rpmlog(RPMLOG_ERR, _("Couldn't create pipe for signing: %m"));
177  return 1;
178  }
179 
180  if (!(pid = fork())) {
181  const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
182 
183  (void) dup2(inpipe[0], 3);
184  (void) close(inpipe[1]);
185 
186  if (gpg_path && *gpg_path != '\0')
187  (void) setenv("GNUPGHOME", gpg_path, 1);
188 
189  unsetenv("MALLOC_CHECK_");
190  cmd = rpmExpand("%{?__gpg_sign_cmd}", NULL);
191  rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
192  if (!rc)
193  rc = execve(av[0], av+1, environ);
194 
195  rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "gpg",
196  strerror(errno));
197  _exit(EXIT_FAILURE);
198  }
199 
200  delMacro(NULL, "__plaintext_filename");
201  delMacro(NULL, "__signature_filename");
202 
203  pw = rpmkuPassPhrase(passPhrase);
204  if (pw == NULL) {
205  rpmlog(RPMLOG_ERR, _("Failed rpmkuPassPhrase(passPhrase): %s\n"),
206  strerror(errno));
207  return 1;
208  }
209 
210  fpipe = fdopen(inpipe[1], "w");
211  (void) close(inpipe[0]);
212  if (fpipe) {
213  fprintf(fpipe, "%s\n", (pw ? pw : ""));
214  (void) fclose(fpipe);
215  }
216 
217  if (pw != NULL) {
218  (void) memset((void *)pw, 0, strlen(pw));
219  pw = _free(pw);
220  }
221 
222 /*@+longunsignedintegral@*/
223  (void) waitpid(pid, &status, 0);
224 /*@=longunsignedintegral@*/
225  if (!WIFEXITED(status) || WEXITSTATUS(status)) {
226  rpmlog(RPMLOG_ERR, _("gpg exec failed (%d)\n"), WEXITSTATUS(status));
227  return 1;
228  }
229 
230  if (Stat(sigfile, &st)) {
231  /* GPG failed to write signature */
232  if (sigfile) (void) Unlink(sigfile); /* Just in case */
233  rpmlog(RPMLOG_ERR, _("gpg failed to write signature\n"));
234  return 1;
235  }
236 
237  *pktlenp = (rpmuint32_t)st.st_size;
238  rpmlog(RPMLOG_DEBUG, D_("GPG sig size: %u\n"), (unsigned)*pktlenp);
239  *pktp = (rpmuint8_t *) xmalloc(*pktlenp);
240 
241  { FD_t fd;
242 
243  rc = 0;
244  fd = Fopen(sigfile, "r.ufdio");
245  if (fd != NULL && !Ferror(fd)) {
246  rc = (int) Fread(*pktp, sizeof((*pktp)[0]), *pktlenp, fd);
247  if (sigfile) (void) Unlink(sigfile);
248  (void) Fclose(fd);
249  }
250  if ((rpmuint32_t)rc != *pktlenp) {
251  *pktp = _free(*pktp);
252  rpmlog(RPMLOG_ERR, _("unable to read the signature\n"));
253  return 1;
254  }
255  }
256 
257  rpmlog(RPMLOG_DEBUG, D_("Got %u bytes of GPG sig\n"), (unsigned)*pktlenp);
258 
259  /* Parse the signature, change signature tag as appropriate. */
261 
262  (void) pgpPrtPkts(*pktp, *pktlenp, dig, 0);
263  sigp = pgpGetSignature(dig);
264 
265  /* Identify the type of signature being returned. */
266  switch (*sigTagp) {
267  default:
268 assert(0); /* XXX never happens. */
269  /*@notreached@*/ break;
270  case RPMSIGTAG_SIZE:
271  case RPMSIGTAG_MD5:
272  case RPMSIGTAG_SHA1:
273  break;
274  case RPMSIGTAG_DSA:
275  /* XXX check hash algorithm too? */
276  if (sigp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_RSA)
277  *sigTagp = RPMSIGTAG_RSA;
278  break;
279  case RPMSIGTAG_RSA:
280  if (sigp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_DSA)
281  *sigTagp = RPMSIGTAG_DSA;
282  break;
283  }
284 
285  dig = pgpDigFree(dig);
286 
287  return 0;
288 }
289 
298 /*@-mustmod@*/ /* sigh is modified */
299 static int makeHDRSignature(Header sigh, const char * file, rpmSigTag sigTag,
300  /*@null@*/ const char * passPhrase)
301  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
302  /*@modifies sigh, sigTag, rpmGlobalMacroContext, fileSystem, internalState @*/
303 {
304  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
305  Header h = NULL;
306  FD_t fd = NULL;
307  rpmuint8_t * pkt;
309  const char * fn = NULL;
310  const char * msg;
311  rpmRC rc;
312  int ret = -1; /* assume failure. */
313  int xx;
314 
315  switch (sigTag) {
316  default:
317 assert(0); /* XXX never happens. */
318  /*@notreached@*/ break;
319  case RPMSIGTAG_SIZE:
320  case RPMSIGTAG_MD5:
321  case RPMSIGTAG_PGP5: /* XXX legacy */
322  case RPMSIGTAG_PGP:
323  case RPMSIGTAG_GPG:
324  goto exit;
325  /*@notreached@*/ break;
326  case RPMSIGTAG_SHA1:
327  { const char * SHA1 = NULL;
328  fd = Fopen(file, "r.fdio");
329  if (fd == NULL || Ferror(fd))
330  goto exit;
331  { const char item[] = "Header";
332  msg = NULL;
333  rc = rpmpkgRead(item, fd, &h, &msg);
334  if (rc != RPMRC_OK) {
335  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
336  msg = _free(msg);
337  goto exit;
338  }
339  msg = _free(msg);
340  }
341  (void) Fclose(fd); fd = NULL;
342 
344  unsigned char * hmagic = NULL;
345  size_t nmagic = 0;
346  DIGEST_CTX ctx;
347 
349  if (!headerGet(h, he, 0) || he->p.ptr == NULL)
350  {
351  (void)headerFree(h);
352  h = NULL;
353  goto exit;
354  }
355  (void) headerGetMagic(NULL, &hmagic, &nmagic);
357  if (hmagic && nmagic > 0)
358  (void) rpmDigestUpdate(ctx, hmagic, nmagic);
359  (void) rpmDigestUpdate(ctx, he->p.ptr, he->c);
360  (void) rpmDigestFinal(ctx, &SHA1, NULL, 1);
361  he->p.ptr = _free(he->p.ptr);
362  }
363  (void)headerFree(h);
364  h = NULL;
365 
366  if (SHA1 == NULL)
367  goto exit;
368  he->tag = (rpmTag) RPMSIGTAG_SHA1;
369  he->t = RPM_STRING_TYPE;
370  he->p.str = SHA1;
371  he->c = 1;
372  xx = headerPut(sigh, he, 0);
373  SHA1 = _free(SHA1);
374  if (!xx)
375  goto exit;
376  ret = 0;
377  } break;
378  case RPMSIGTAG_DSA:
379  fd = Fopen(file, "r.fdio");
380  if (fd == NULL || Ferror(fd))
381  goto exit;
382  { const char item[] = "Header";
383  msg = NULL;
384  rc = rpmpkgRead(item, fd, &h, &msg);
385  if (rc != RPMRC_OK) {
386  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
387  msg = _free(msg);
388  goto exit;
389  }
390  msg = _free(msg);
391  }
392  (void) Fclose(fd); fd = NULL;
393 
394  if (rpmTempFile(NULL, &fn, &fd))
395  goto exit;
396  { const char item[] = "Header";
397  msg = NULL;
398  rc = rpmpkgWrite(item, fd, h, &msg);
399  if (rc != RPMRC_OK) {
400  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
401  msg = _free(msg);
402  goto exit;
403  }
404  msg = _free(msg);
405  }
406  (void) Fclose(fd); fd = NULL;
407 
408  if (makeGPGSignature(fn, &sigTag, &pkt, &pktlen, passPhrase))
409  goto exit;
410  he->tag = (rpmTag) sigTag;
411  he->t = RPM_BIN_TYPE;
412  he->p.ptr = pkt;
413  he->c = pktlen;
414  xx = headerPut(sigh, he, 0);
415  if (!xx)
416  goto exit;
417  ret = 0;
418  break;
419  }
420 
421 exit:
422  if (fn) {
423  (void) Unlink(fn);
424  fn = _free(fn);
425  }
426  (void)headerFree(h);
427  h = NULL;
428  if (fd != NULL) (void) Fclose(fd);
429  return ret;
430 }
431 /*@=mustmod@*/
432 
433 int rpmAddSignature(Header sigh, const char * file, rpmSigTag sigTag,
434  const char * passPhrase)
435 {
436  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
437  struct stat st;
438  rpmuint8_t * pkt;
440  int ret = -1; /* assume failure. */
441  int xx;
442 
443  switch (sigTag) {
444  default:
445 assert(0); /* XXX never happens. */
446  /*@notreached@*/ break;
447  case RPMSIGTAG_SIZE:
448  if (Stat(file, &st) != 0)
449  break;
450  pktlen = (rpmuint32_t)st.st_size;
451  he->tag = (rpmTag) sigTag;
452  he->t = RPM_UINT32_TYPE;
453  he->p.ui32p = &pktlen;
454  he->c = 1;
455 /*@-compmempass@*/
456  xx = headerPut(sigh, he, 0);
457 /*@=compmempass@*/
458  if (!xx)
459  break;
460  ret = 0;
461  break;
462  case RPMSIGTAG_MD5:
463  pktlen = 128/8;
464  pkt = (rpmuint8_t *) memset(alloca(pktlen), 0, pktlen);
465  if (dodigest(PGPHASHALGO_MD5, file, (unsigned char *)pkt, 0, NULL))
466  break;
467  he->tag = (rpmTag) sigTag;
468  he->t = RPM_BIN_TYPE;
469  he->p.ptr = pkt;
470  he->c = pktlen;
471  xx = headerPut(sigh, he, 0);
472  if (!xx)
473  break;
474  ret = 0;
475  break;
476  case RPMSIGTAG_GPG:
477  ret = makeHDRSignature(sigh, file, RPMSIGTAG_DSA, passPhrase);
478  break;
479  case RPMSIGTAG_RSA:
480  case RPMSIGTAG_DSA:
481  case RPMSIGTAG_SHA1:
482  ret = makeHDRSignature(sigh, file, sigTag, passPhrase);
483  break;
484  }
485 
486  return ret;
487 }
488 
490 {
491  const char *pw;
492  int p[2];
493  pid_t pid;
494  int status;
495  int rc;
496  int xx;
497 
498  if (!(passPhrase && passPhrase[0]))
499  return 0;
500 
501  p[0] = p[1] = 0;
502  xx = pipe(p);
503 
504  if (!(pid = fork())) {
505  const char * cmd;
506  char *const *av;
507  int fdno;
508 
509  xx = close(STDIN_FILENO);
510  xx = close(STDOUT_FILENO);
511  xx = close(p[1]);
512  if (!rpmIsVerbose())
513  xx = close(STDERR_FILENO);
514  if ((fdno = open("/dev/null", O_RDONLY)) != STDIN_FILENO) {
515  xx = dup2(fdno, STDIN_FILENO);
516  xx = close(fdno);
517  }
518  if ((fdno = open("/dev/null", O_WRONLY)) != STDOUT_FILENO) {
519  xx = dup2(fdno, STDOUT_FILENO);
520  xx = close(fdno);
521  }
522  xx = dup2(p[0], 3);
523 
524  unsetenv("MALLOC_CHECK_");
525  { const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
526 
527  if (gpg_path && *gpg_path != '\0')
528  (void) setenv("GNUPGHOME", gpg_path, 1);
529 
530  cmd = rpmExpand("%{?__gpg_check_password_cmd}", NULL);
531  rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
532  if (!rc)
533  rc = execve(av[0], av+1, environ);
534 
535  rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "gpg",
536  strerror(errno));
537  }
538  }
539 
540  pw = rpmkuPassPhrase(passPhrase);
541  if (pw == NULL) {
542  rpmlog(RPMLOG_ERR, _("Failed rpmkuPassPhrase(passPhrase): %s\n"),
543  strerror(errno));
544  return 1;
545  }
546 
547  xx = close(p[0]);
548  xx = (int) write(p[1], pw, strlen(pw));
549  xx = (int) write(p[1], "\n", 1);
550  xx = close(p[1]);
551 
552  if (pw != NULL) {
553  (void) memset((void *)pw, 0, strlen(pw));
554  pw = _free(pw);
555  }
556 
557 /*@+longunsignedintegral@*/
558  (void) waitpid(pid, &status, 0);
559 /*@=longunsignedintegral@*/
560 
561  return ((!WIFEXITED(status) || WEXITSTATUS(status)) ? 1 : 0);
562 }
563 
564 static /*@observer@*/ const char * rpmSigString(rpmRC res)
565  /*@*/
566 {
567  const char * str;
568  switch (res) {
569  case RPMRC_OK: str = "OK"; break;
570  case RPMRC_FAIL: str = "BAD"; break;
571  case RPMRC_NOKEY: str = "NOKEY"; break;
572  case RPMRC_NOTTRUSTED: str = "NOTRUSTED"; break;
573  default:
574  case RPMRC_NOTFOUND: str = "UNKNOWN"; break;
575  }
576  return str;
577 }
578 
579 static rpmRC
580 verifySize(const pgpDig dig, /*@out@*/ char * t)
581  /*@modifies *t @*/
582 {
583  const void * sig = pgpGetSig(dig);
585  rpmuint32_t size = 0xffffffff;
586 
587  *t = '\0';
588  t = stpcpy(t, _("Header+Payload size: "));
589 
590  if (sig == NULL || dig == NULL || dig->nbytes == 0) {
591  res = RPMRC_NOKEY;
592  t = stpcpy(t, rpmSigString(res));
593  goto exit;
594  }
595 
596  memcpy(&size, sig, sizeof(size));
597 
598  if (size !=(rpmuint32_t) dig->nbytes) {
599  res = RPMRC_FAIL;
600  t = stpcpy(t, rpmSigString(res));
601  sprintf(t, " Expected(%u) != (%u)\n", (unsigned)size, (unsigned)dig->nbytes);
602  } else {
603  res = RPMRC_OK;
604  t = stpcpy(t, rpmSigString(res));
605  sprintf(t, " (%u)", (unsigned)dig->nbytes);
606  }
607 
608 exit:
609  return res;
610 }
611 
612 static rpmRC
613 verifyMD5(pgpDig dig, /*@out@*/ char * t, /*@null@*/ DIGEST_CTX md5ctx)
614  /*@globals internalState @*/
615  /*@modifies *t, internalState @*/
616 {
617  const void * sig = pgpGetSig(dig);
619  rpmRC res;
621  size_t md5len = 0;
622 
623 assert(dig != NULL);
624 assert(md5ctx != NULL);
625 assert(sig != NULL);
626 
627  *t = '\0';
628 
629  /* Identify the hash. */
630  t = stpcpy(t, rpmDigestName(md5ctx));
631  t = stpcpy(t, _(" digest: "));
632 
633  if (sig == NULL) { /* XXX can't happen, DYING */
634  res = RPMRC_NOKEY;
635  t = stpcpy(t, rpmSigString(res));
636  goto exit;
637  }
638 
639  { rpmop op = (rpmop)pgpStatsAccumulator(dig, 10); /* RPMTS_OP_DIGEST */
640  (void) rpmswEnter(op, 0);
641  (void) rpmDigestFinal(rpmDigestDup(md5ctx), &md5sum, &md5len, 0);
642  (void) rpmswExit(op, 0);
643  if (op != NULL) op->count--; /* XXX one too many */
644  }
645 
646  if (md5len != siglen || memcmp(md5sum, sig, md5len)) {
647  res = RPMRC_FAIL;
648  t = stpcpy(t, rpmSigString(res));
649  t = stpcpy(t, " Expected(");
650  (void) pgpHexCvt(t, (rpmuint8_t *)sig, siglen);
651  t += strlen(t);
652  t = stpcpy(t, ") != (");
653  } else {
654  res = RPMRC_OK;
655  t = stpcpy(t, rpmSigString(res));
656  t = stpcpy(t, " (");
657  }
658  (void) pgpHexCvt(t, md5sum, md5len);
659  t += strlen(t);
660  t = stpcpy(t, ")");
661 
662 exit:
663  md5sum = _free(md5sum);
664  return res;
665 }
666 
674 static rpmRC
675 verifySHA1(pgpDig dig, /*@out@*/ char * t, /*@null@*/ DIGEST_CTX shactx)
676  /*@globals internalState @*/
677  /*@modifies *t, internalState @*/
678 {
679  const void * sig = pgpGetSig(dig);
680 #ifdef NOTYET
681  rpmuint32_t siglen = pgpGetSiglen(dig);
682 #endif
683  rpmRC res;
684  const char * SHA1 = NULL;
685 
686 assert(dig != NULL);
687 assert(shactx != NULL);
688 assert(sig != NULL);
689 
690  *t = '\0';
691  t = stpcpy(t, _("Header "));
692 
693  /* Identify the hash. */
694  t = stpcpy(t, rpmDigestName(shactx));
695  t = stpcpy(t, _(" digest: "));
696 
697  if (sig == NULL) { /* XXX can't happen, DYING */
698  res = RPMRC_NOKEY;
699  t = stpcpy(t, rpmSigString(res));
700  goto exit;
701  }
702 
703  { rpmop op = (rpmop)pgpStatsAccumulator(dig, 10); /* RPMTS_OP_DIGEST */
704  (void) rpmswEnter(op, 0);
705  (void) rpmDigestFinal(rpmDigestDup(shactx), &SHA1, NULL, 1);
706  (void) rpmswExit(op, 0);
707  }
708 
709  if (SHA1 == NULL
710  || strlen(SHA1) != strlen((char *)sig)
711  || strcmp(SHA1, (char *)sig))
712  {
713  res = RPMRC_FAIL;
714  t = stpcpy(t, rpmSigString(res));
715  t = stpcpy(t, " Expected(");
716  t = stpcpy(t, (char *)sig);
717  t = stpcpy(t, ") != (");
718  } else {
719  res = RPMRC_OK;
720  t = stpcpy(t, rpmSigString(res));
721  t = stpcpy(t, " (");
722  }
723  if (SHA1)
724  t = stpcpy(t, SHA1);
725  t = stpcpy(t, ")");
726 
727 exit:
728  SHA1 = _free(SHA1);
729  return res;
730 }
731 
739 static rpmRC
740 verifyRSA(pgpDig dig, /*@out@*/ char * t, /*@null@*/ DIGEST_CTX rsactx)
741  /*@globals internalState @*/
742  /*@modifies dig, *t, internalState */
743 {
744  const void * sig = pgpGetSig(dig);
745 #ifdef NOTYET
746  rpmuint32_t siglen = pgpGetSiglen(dig);
747 #endif
749  rpmRC res = RPMRC_OK;
750  int xx;
751 
752 if (_rpmhkp_debug)
753 fprintf(stderr, "--> %s(%p,%p,%p) sig %p sigp %p\n", __FUNCTION__, dig, t, rsactx, sig, sigp);
754 
755 assert(dig != NULL);
756 assert(rsactx != NULL);
757 assert(sigp != NULL);
758 assert(sigp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_RSA);
759 assert(sigp->hash_algo == (rpmuint8_t)rpmDigestAlgo(rsactx));
761 assert(sig != NULL);
762 
763  *t = '\0';
764  if (dig->hdrctx == rsactx)
765  t = stpcpy(t, _("Header "));
766 
767  /* Identify the signature version. */
768  *t++ = 'V';
769  switch (sigp->version) {
770  case 3: *t++ = '3'; break;
771  case 4: *t++ = '4'; break;
772  }
773 
774  /* Identify the RSA/hash. */
775  { const char * hashname = rpmDigestName(rsactx);
776  t = stpcpy(t, " RSA");
777  if (strcmp(hashname, "UNKNOWN")) {
778  *t++ = '/';
779  t = stpcpy(t, hashname);
780  }
781  }
782  t = stpcpy(t, _(" signature: "));
783 
784  { rpmop op = (rpmop)pgpStatsAccumulator(dig, 10); /* RPMTS_OP_DIGEST */
786 
787  (void) rpmswEnter(op, 0);
788  if (sigp->hash != NULL)
789  xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
790 
791  if (sigp->version == (rpmuint8_t) 4) {
792  rpmuint8_t trailer[6];
793  trailer[0] = sigp->version;
794  trailer[1] = (rpmuint8_t)0xff;
795  trailer[2] = (sigp->hashlen >> 24);
796  trailer[3] = (sigp->hashlen >> 16);
797  trailer[4] = (sigp->hashlen >> 8);
798  trailer[5] = (sigp->hashlen );
799  xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
800  }
801  (void) rpmswExit(op, sigp->hashlen);
802  if (op != NULL) op->count--; /* XXX one too many */
803 
804  if ((xx = pgpImplSetRSA(ctx, dig, sigp)) != 0) {
805  res = RPMRC_FAIL;
806  goto exit;
807  }
808  }
809 
810  /* Retrieve the matching public key. */
811  res = (rpmRC) pgpFindPubkey(dig);
812  if (res != RPMRC_OK)
813  goto exit;
814 
815  /* Verify the RSA signature. */
816  { rpmop op = (rpmop)pgpStatsAccumulator(dig, 11); /* RPMTS_OP_SIGNATURE */
817  (void) rpmswEnter(op, 0);
818  xx = pgpImplVerify(dig);
819  (void) rpmswExit(op, 0);
820  res = (xx ? RPMRC_OK : RPMRC_FAIL);
821  }
822 
823 exit:
824  /* Identify the pubkey fingerprint. */
825  t = stpcpy(t, rpmSigString(res));
826  if (sigp != NULL) {
827  t = stpcpy(t, ", key ID ");
828  (void) pgpHexCvt(t, sigp->signid+4, sizeof(sigp->signid)-4);
829  t += strlen(t);
830  }
831  return res;
832 }
833 
841 static rpmRC
842 verifyDSA(pgpDig dig, /*@out@*/ char * t, /*@null@*/ DIGEST_CTX dsactx)
843  /*@globals internalState @*/
844  /*@modifies dig, *t, internalState */
845 {
846  const void * sig = pgpGetSig(dig);
847 #ifdef NOTYET
848  rpmuint32_t siglen = pgpGetSiglen(dig);
849 #endif
850  pgpDigParams sigp = pgpGetSignature(dig);
851  rpmRC res;
852  int xx;
853 
854 if (_rpmhkp_debug)
855 fprintf(stderr, "--> %s(%p,%p,%p) sig %p sigp %p\n", __FUNCTION__, dig, t, dsactx, sig, sigp);
856 
857 assert(dig != NULL);
858 assert(dsactx != NULL);
859 assert(sigp != NULL);
860 assert(sigp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_DSA);
861 assert(sigp->hash_algo == (rpmuint8_t)rpmDigestAlgo(dsactx));
863 assert(sig != NULL);
864 
865  *t = '\0';
866  if (dig != NULL && dig->hdrsha1ctx == dsactx)
867  t = stpcpy(t, _("Header "));
868 
869  /* Identify the signature version. */
870  *t++ = 'V';
871  switch (sigp->version) {
872  case 3: *t++ = '3'; break;
873  case 4: *t++ = '4'; break;
874  }
875 
876  /* Identify the DSA/hash. */
877  { const char * hashname = rpmDigestName(dsactx);
878  t = stpcpy(t, " DSA");
879  if (strcmp(hashname, "UNKNOWN") && strcmp(hashname, "SHA1")) {
880  *t++ = '/';
881  t = stpcpy(t, hashname);
882  }
883  }
884  t = stpcpy(t, _(" signature: "));
885 
886  { rpmop op = (rpmop)pgpStatsAccumulator(dig, 10); /* RPMTS_OP_DIGEST */
887  DIGEST_CTX ctx = rpmDigestDup(dsactx);
888 
889  (void) rpmswEnter(op, 0);
890  if (sigp->hash != NULL)
891  xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
892 
893  if (sigp->version == (rpmuint8_t) 4) {
894  rpmuint8_t trailer[6];
895  trailer[0] = sigp->version;
896  trailer[1] = (rpmuint8_t)0xff;
897  trailer[2] = (sigp->hashlen >> 24);
898  trailer[3] = (sigp->hashlen >> 16);
899  trailer[4] = (sigp->hashlen >> 8);
900  trailer[5] = (sigp->hashlen );
901  xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
902  }
903  (void) rpmswExit(op, sigp->hashlen);
904  if (op != NULL) op->count--; /* XXX one too many */
905 
906  if (pgpImplSetDSA(ctx, dig, sigp)) {
907  res = RPMRC_FAIL;
908  goto exit;
909  }
910  }
911 
912  /* Retrieve the matching public key. */
913  res = (rpmRC) pgpFindPubkey(dig);
914  if (res != RPMRC_OK)
915  goto exit;
916 
917  /* Verify the DSA signature. */
918  { rpmop op = (rpmop)pgpStatsAccumulator(dig, 11); /* RPMTS_OP_SIGNATURE */
919  (void) rpmswEnter(op, 0);
920  xx = pgpImplVerify(dig);
921  res = (xx ? RPMRC_OK : RPMRC_FAIL);
922  (void) rpmswExit(op, 0);
923  }
924 
925 exit:
926  /* Identify the pubkey fingerprint. */
927  t = stpcpy(t, rpmSigString(res));
928  if (sigp != NULL) {
929  t = stpcpy(t, ", key ID ");
930  (void) pgpHexCvt(t, sigp->signid+4, sizeof(sigp->signid)-4);
931  t += strlen(t);
932  }
933 
934 if (_rpmhkp_debug)
935 fprintf(stderr, "<-- %s(%p,%p,%p) res %d %s\n", __FUNCTION__, dig, t, dsactx, res, t);
936 
937  return res;
938 }
939 
940 rpmRC
941 rpmVerifySignature(void * _dig, char * result)
942 {
943  pgpDig dig = (pgpDig) _dig;
944  const void * sig = pgpGetSig(dig);
945  rpmuint32_t siglen = pgpGetSiglen(dig);
946  rpmSigTag sigtag = (rpmSigTag) pgpGetSigtag(dig);
947  rpmRC res;
948 
949 if (_rpmhkp_debug)
950 fprintf(stderr, "--> %s(%p,%p) sig %p[%u]\n", __FUNCTION__, _dig, result, sig, siglen);
951 
952  if (dig == NULL || sig == NULL || siglen == 0) {
953  sprintf(result, _("Verify signature: BAD PARAMETERS\n"));
954  res = RPMRC_NOTFOUND;
955  goto exit;
956  }
957 
958  switch (sigtag) {
959  case RPMSIGTAG_SIZE:
960  res = verifySize(dig, result);
961  break;
962  case RPMSIGTAG_MD5:
963  res = verifyMD5(dig, result, dig->md5ctx);
964  break;
965  case RPMSIGTAG_SHA1:
966  res = verifySHA1(dig, result, dig->hdrsha1ctx);
967  break;
968  case RPMSIGTAG_RSA:
969  res = verifyRSA(dig, result, dig->hdrctx);
970  break;
971  case RPMSIGTAG_DSA:
972  res = verifyDSA(dig, result, dig->hdrsha1ctx);
973  break;
974  default:
975  sprintf(result, _("Signature: UNKNOWN (%u)\n"), (unsigned)sigtag);
976  res = RPMRC_NOTFOUND;
977  break;
978  }
979 
980 exit:
981 if (_rpmhkp_debug)
982 fprintf(stderr, "<-- %s(%p,%p) res %d %s\n", __FUNCTION__, _dig, result, res, result);
983 
984  return res;
985 }
rpmTagType t
Definition: rpmtag.h:502
rpmuint32_t siglen
Definition: signature.c:618
void pgpHexCvt(t, md5sum, md5len)
const char * str
Definition: rpmtag.h:73
int xx
Definition: spec.c:744
rpmTag tag
Definition: rpmtag.h:501
static int makeGPGSignature(const char *file, rpmSigTag *sigTagp, rpmuint8_t **pktp, rpmuint32_t *pktlenp, const char *passPhrase)
Generate GPG signature(s) for a header+payload file.
Definition: signature.c:148
enum pgpPubkeyAlgo_e pgpPubkeyAlgo
9.1.
DIGEST_CTX ctx
Definition: signature.c:785
#define headerFree(_h)
Definition: rpmtag.h:870
rpmlog(RPMLOG_ERR,"%s\n", buf)
OpenPGP constants and structures from RFC-2440.
rpmRC rpmpkgWrite(const char *fn, FD_t fd, void *ptr, const char **msg)
Write item onto file descriptor.
Definition: pkgio.c:1665
#define EXIT_FAILURE
int rpmCheckPassPhrase(const char *passPhrase)
Check for valid pass phrase by invoking a helper.
Definition: signature.c:489
rpmuint32_t * ui32p
Definition: rpmtag.h:70
FD_t Fopen(const char *path, const char *_fmode)
fopen(3) clone.
Definition: rpmio.c:2831
int rc
Definition: poptALL.c:670
The Header data structure.
int rpmioMkpath(const char *path, mode_t mode, uid_t uid, gid_t gid)
Insure that directories in path exist, creating as needed.
Definition: rpmio.c:3015
int setenv(const char *name, const char *value, int replace)
int Stat(const char *path, struct stat *st)
stat(2) clone.
Definition: rpmrpc.c:1361
int pgpFindPubkey(pgpDig dig)
Call find pubkey vector.
Definition: rpmpgp.c:1298
#define S_ISLNK(mode)
Definition: system.h:651
pid_t pid
Definition: rpmsq.c:736
enum rpmTag_e rpmTag
Definition: rpmtag.h:468
char ** environ
int errno
void addMacro(MacroContext mc, const char *n, const char *o, const char *b, int level)
Add macro to context.
Definition: macro.c:2722
int dodigest(int dalgo, const char *fn, unsigned char *digest, unsigned dflags, size_t *fsizep)
Return digest and size of a file.
Definition: legacy.c:178
Header h
Definition: spec.c:739
pid_t result
Definition: rpmsq.c:737
struct pgpDig_s * pgpDig
Definition: rpmiotypes.h:86
static int pgpImplSetDSA(DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
Definition: rpmpgp.h:1768
unsigned char rpmuint8_t
Private int typedefs to avoid C99 portability issues.
Definition: rpmiotypes.h:26
sprintf(t," (%u)",(unsigned) dig->nbytes)
ret
Definition: macro.c:387
char * passPhrase
Definition: rpmts-py.c:1340
enum rpmSigTag_e rpmSigTag
Definition: rpmtag.h:472
delMacro(mc, n)
rpmRC res
Definition: signature.c:584
char * alloca()
pgpDig pgpDigNew(pgpVSFlags vsflags, pgpPubkeyAlgo pubkey_algo)
Create a container for parsed OpenPGP packates.
Definition: rpmpgp.c:1205
enum rpmRC_e rpmRC
RPM return codes.
Definition: signature.c:616
goto exit
Definition: db3.c:1903
memset(_r, 0, sizeof(*_r))
unsigned int rpmuint32_t
Definition: rpmiotypes.h:28
assert(key->size==sizeof(hdrNum))
goto errxit
Definition: rpmgrep.c:1527
void * ptr
Definition: rpmtag.h:67
int count
Definition: rpmsw.h:41
char * p
Definition: macro.c:413
int headerGetMagic(Header h, unsigned char **magicp, size_t *nmagicp)
Return header magic.
Definition: header.c:1162
int rpmAddSignature(Header sigh, const char *file, rpmSigTag sigTag, const char *passPhrase)
Generate signature(s) from a header+payload file, save in signature header.
Definition: signature.c:433
rpmuint8_t * md5sum
Definition: signature.c:620
rpmuint32_t size
Definition: signature.c:585
int headerIsEntry(Header h, rpmTag tag)
Check if tag is in header.
Definition: header.c:1438
fprintf(stderr,"--> %s(%p,%p,%p) sig %p sigp %p\n", __FUNCTION__, dig, t, rsactx, sig, sigp)
static int makeHDRSignature(Header sigh, const char *file, rpmSigTag sigTag, const char *passPhrase)
Generate header only signature(s) from a header+payload file.
Definition: signature.c:299
int rpmTempFile(const char *prefix, const char **fnptr, void *fdptr)
Return file handle for a temporaray file.
Definition: signature.c:30
void * pgpStatsAccumulator(pgpDig dig, int opx)
Return pgpDig container accumulator structure.
Definition: rpmpgp.c:1270
const char * rpmDigestName(DIGEST_CTX ctx)
Return digest name.
Definition: digest.c:198
rpmTagData p
Definition: rpmtag.h:504
DIGEST_CTX rpmDigestDup(DIGEST_CTX octx)
Duplicate a digest context.
Definition: digest.c:209
int rpmDigestUpdate(DIGEST_CTX ctx, const void *data, size_t len)
Update context with next plain text buffer.
Definition: digest.c:907
void rpmswExit(op, 0)
static const char * file
Definition: parseFiles.c:20
pgpDigParams pgpGetSignature(pgpDig dig)
Return OpenPGP signature parameters.
Definition: rpmpgp.c:1226
struct _HE_s * HE_t
Destroy an extension cache.
Definition: rpmtag.h:59
Digest private data.
Definition: digest.c:127
unsigned int pktlen
Definition: rpmts-py.c:1092
int headerGet(Header h, HE_t he, unsigned int flags)
Retrieve extension or tag value from a header.
Definition: header.c:2230
pgpHashAlgo rpmDigestAlgo(DIGEST_CTX ctx)
Return digest algorithm identifier.
Definition: digest.c:188
int pgpPrtPkts(const rpmuint8_t *pkts, size_t pktlen, pgpDig dig, int printing)
Print/parse a OpenPGP packet(s).
Definition: rpmpgp.c:1352
The FD_t File Handle data structure.
int headerPut(Header h, HE_t he, unsigned int flags)
Add or append tag container to header.
Definition: header.c:2293
pgpDig pgpDigFree(pgpDig dig)
Destroy a container for parsed OpenPGP packates.
const char * rpmGenPath(const char *urlroot, const char *urlmdir, const char *urlfile)
Merge 3 args into path, any or all of which may be a url.
Definition: macro.c:3417
rpmTagCount c
Definition: rpmtag.h:505
Generate and verify rpm package signatures.
DIGEST_CTX rpmDigestInit(pgpHashAlgo hashalgo, rpmDigestFlags flags)
Initialize digest.
Definition: digest.c:244
char * rpmExpand(const char *arg,...)
Return (malloc&#39;ed) concatenated macro expansion(s).
Definition: macro.c:3178
size_t Fread(void *buf, size_t size, size_t nmemb, FD_t fd)
fread(3) clone.
Definition: rpmio.c:2410
static unsigned
Definition: rpmmtree.c:386
void unsetenv(const char *name)
* op
Definition: rpmps-py.c:266
static const char * rpmSigString(rpmRC res)
Definition: signature.c:564
node fd
Definition: rpmfd-py.c:124
int Fclose(FD_t fd)
fclose(3) clone.
Definition: rpmio.c:2532
Cumulative statistics for an operation.
Definition: rpmsw.h:39
rpmuint32_t pgpGetSigtag(pgpDig dig)
Get signature tag.
Definition: rpmpgp.c:1236
static int pgpImplSetRSA(DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
Definition: rpmpgp.h:1759
int Ferror(FD_t fd)
ferror(3) clone.
Definition: rpmio.c:2942
Definition: rpmtag.h:500
return strcmp(ame->name, bme->name)
size_t md5len
Definition: signature.c:621
char * t
Definition: rpmds.c:2716
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
Definition: url.c:430
static const char * prefix[]
Tables for prefixing and suffixing patterns, according to the -w, -x, and -F options.
Definition: rpmgrep.c:183
Methods to handle package elements.
char * stpcpy(char *dest, const char *src)
const char * SHA1
Definition: signature.c:684
const void * pgpGetSig(pgpDig dig)
Get signature tag data, i.e.
Definition: rpmpgp.c:1246
static int pgpImplVerify(pgpDig dig)
Definition: rpmpgp.h:1839
const char * msg
Definition: rpmts-py.c:976
struct pgpDigParams_s * pgpDigParams
Definition: rpmiotypes.h:90
#define rpmIsVerbose()
Definition: rpmcb.h:21
return NULL
Definition: poptALL.c:613
int Fileno(FD_t fd)
fileno(3) clone.
Definition: rpmio.c:2989
static void
Print copy of spec file, filling in Group/Description/Summary from specspo.
Definition: spec.c:737
rpmuint32_t pgpGetSiglen(pgpDig dig)
Get signature tag data length, i.e.
Definition: rpmpgp.c:1251
static PyObject *unsigned char * pkt
Definition: rpmts-py.c:1089
#define _(Text)
Definition: system.h:29
int
Save source and expand field into target.
Definition: rpmds.c:2709
status
Definition: rpmsq.c:792
#define xmalloc
Definition: system.h:32
void rpmDigestFinal(rpmDigestDup(md5ctx),&md5sum,&md5len, 0)
rpmRC rpmpkgRead(const char *fn, FD_t fd, void *ptr, const char **msg)
Read item from file descriptor.
Definition: pkgio.c:1647
Access RPM indices using Berkeley DB interface(s).
void rpmswEnter(op, 0)
struct rpmop_s * rpmop
Definition: rpmsw.h:24
#define D_(Text)
Definition: system.h:526
int fdno
Definition: rpmts-py.c:923
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
pgpDigParams sigp
Definition: signature.c:748
const char * rpmkuPassPhrase(const char *passPhrase)
Return pass phrase from keyutils keyring.
Definition: rpmku.c:227
pgpDig dig
Definition: rpmts-py.c:979
rpmRC rpmVerifySignature(void *_dig, char *result)
Verify a signature from a package.
Definition: signature.c:941
const char ** av
Definition: rpmts-py.c:788
size_t fn
Definition: macro.c:1698
int Unlink(const char *path)
unlink(2) clone.
Definition: rpmrpc.c:397