Bug Summary

File:sign/rpmgensig.c
Warning:line 268, column 6
Value stored to 'rc' is never read

Annotated Source Code

1/** \ingroup rpmcli
2 * \file lib/rpmchecksig.c
3 * Verify the signature of a package.
4 */
5
6#include "system.h"
7
8#include <errno(*__errno_location ()).h>
9#include <sys/wait.h>
10#include <popt.h>
11#include <libgen.h>
12
13#include <rpm/rpmlib.h> /* RPMSIGTAG & related */
14#include <rpm/rpmmacro.h>
15#include <rpm/rpmpgp.h>
16#include <rpm/rpmsign.h>
17#include <rpm/rpmfileutil.h> /* rpmMkTemp() */
18#include <rpm/rpmlog.h>
19#include <rpm/rpmstring.h>
20#include <rpmio/rpmio_internal.h>
21
22#include "lib/rpmlead.h"
23#include "lib/signature.h"
24#include "sign/rpmsignfiles.h"
25
26#include "debug.h"
27
28typedef struct sigTarget_s {
29 FD_t fd;
30 const char *fileName;
31 off_t start;
32 rpm_loff_t size;
33} *sigTarget;
34
35/*
36 * There is no function for creating unique temporary fifos so create
37 * unique temporary directory and then create fifo in it.
38 */
39static char *mkTempFifo(void)
40{
41 char *tmppath = NULL((void*)0), *tmpdir = NULL((void*)0), *fifofn = NULL((void*)0);
42 mode_t mode;
43
44 tmppath = rpmExpand("%{_tmppath}", NULL((void*)0));
45 if (rpmioMkpath(tmppath, 0755, (uid_t) -1, (gid_t) -1))
46 goto exit;
47
48
49 tmpdir = rpmGetPath(tmppath, "/rpm-tmp.XXXXXX", NULL((void*)0));
50 mode = umask(0077);
51 tmpdir = mkdtemp(tmpdir);
52 umask(mode);
53 if (tmpdir == NULL((void*)0)) {
54 rpmlog(RPMLOG_ERR, _("error creating temp directory %s: %m\n")dcgettext ("rpm", "error creating temp directory %s: %m\n", 5
)
,
55 tmpdir);
56 tmpdir = _free(tmpdir)rfree((tmpdir));
57 goto exit;
58 }
59
60 fifofn = rpmGetPath(tmpdir, "/fifo", NULL((void*)0));
61 if (mkfifo(fifofn, 0600) == -1) {
62 rpmlog(RPMLOG_ERR, _("error creating fifo %s: %m\n")dcgettext ("rpm", "error creating fifo %s: %m\n", 5), fifofn);
63 fifofn = _free(fifofn)rfree((fifofn));
64 }
65
66exit:
67 if (fifofn == NULL((void*)0) && tmpdir != NULL((void*)0))
68 unlink(tmpdir);
69
70 free(tmppath);
71 free(tmpdir);
72
73 return fifofn;
74}
75
76/* Delete fifo and then temporary directory in which it was located */
77static int rpmRmTempFifo(const char *fn)
78{
79 int rc = 0;
80 char *dfn = NULL((void*)0), *dir = NULL((void*)0);
81
82 if ((rc = unlink(fn)) != 0) {
83 rpmlog(RPMLOG_ERR, _("error delete fifo %s: %m\n")dcgettext ("rpm", "error delete fifo %s: %m\n", 5), fn);
84 return rc;
85 }
86
87 dfn = xstrdup(fn)rstrdup((fn));
88 dir = dirname(dfn);
89
90 if ((rc = rmdir(dir)) != 0)
91 rpmlog(RPMLOG_ERR, _("error delete directory %s: %m\n")dcgettext ("rpm", "error delete directory %s: %m\n", 5), dir);
92 free(dfn);
93
94 return rc;
95}
96
97static int closeFile(FD_t *fdp)
98{
99 if (fdp == NULL((void*)0) || *fdp == NULL((void*)0))
100 return 1;
101
102 /* close and reset *fdp to NULL */
103 (void) Fclose(*fdp);
104 *fdp = NULL((void*)0);
105 return 0;
106}
107
108/**
109 */
110static int manageFile(FD_t *fdp, const char *fn, int flags)
111{
112 FD_t fd;
113 const char *fmode;
114
115 if (fdp == NULL((void*)0) || fn == NULL((void*)0)) /* programmer error */
116 return 1;
117
118 /* open a file and set *fdp */
119 if (*fdp == NULL((void*)0) && fn != NULL((void*)0)) {
120 switch (flags & O_ACCMODE0003) {
121 case O_WRONLY01:
122 fmode = "w.ufdio";
123 break;
124 case O_RDONLY00:
125 fmode = "r.ufdio";
126 break;
127 default:
128 case O_RDWR02:
129 fmode = "r+.ufdio";
130 break;
131 }
132 fd = Fopen(fn, fmode);
133 if (fd == NULL((void*)0) || Ferror(fd)) {
134 rpmlog(RPMLOG_ERR, _("%s: open failed: %s\n")dcgettext ("rpm", "%s: open failed: %s\n", 5), fn,
135 Fstrerror(fd));
136 return 1;
137 }
138 *fdp = fd;
139 return 0;
140 }
141
142 /* no operation */
143 if (*fdp != NULL((void*)0) && fn != NULL((void*)0))
144 return 0;
145
146 /* XXX never reached */
147 return 1;
148}
149
150/**
151 * Copy header+payload, calculating digest(s) on the fly.
152 * @param sfdp source file
153 * @param sfnp source path
154 * @param tfdp destination file
155 * @param tfnp destination path
156 */
157static int copyFile(FD_t *sfdp, const char *sfnp,
158 FD_t *tfdp, const char *tfnp)
159{
160 unsigned char buf[BUFSIZ8192];
161 ssize_t count;
162 int rc = 1;
163
164 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), *sfdp)) > 0)
165 {
166 if (Fwrite(buf, sizeof(buf[0]), count, *tfdp) != count) {
167 rpmlog(RPMLOG_ERR, _("%s: Fwrite failed: %s\n")dcgettext ("rpm", "%s: Fwrite failed: %s\n", 5), tfnp,
168 Fstrerror(*tfdp));
169 goto exit;
170 }
171 }
172 if (count < 0) {
173 rpmlog(RPMLOG_ERR, _("%s: Fread failed: %s\n")dcgettext ("rpm", "%s: Fread failed: %s\n", 5), sfnp, Fstrerror(*sfdp));
174 goto exit;
175 }
176 if (Fflush(*tfdp) != 0) {
177 rpmlog(RPMLOG_ERR, _("%s: Fflush failed: %s\n")dcgettext ("rpm", "%s: Fflush failed: %s\n", 5), tfnp,
178 Fstrerror(*tfdp));
179 }
180
181 rc = 0;
182
183exit:
184 return rc;
185}
186
187/*
188 * Validate generated signature and insert to header if it looks sane.
189 * NSS doesn't support everything GPG does. Basic tests to see if the
190 * generated signature is something we can use.
191 * Return generated signature tag data on success, NULL on failure.
192 */
193static rpmtd makeSigTag(Header sigh, int ishdr, uint8_t *pkt, size_t pktlen)
194{
195 pgpDigParams sigp = NULL((void*)0);
196 rpmTagVal sigtag;
197 rpmtd sigtd = NULL((void*)0);
198 unsigned int hash_algo;
199 unsigned int pubkey_algo;
200
201 if (pgpPrtParams(pkt, pktlen, PGPTAG_SIGNATURE, &sigp)) {
202 rpmlog(RPMLOG_ERR, _("Unsupported PGP signature\n")dcgettext ("rpm", "Unsupported PGP signature\n", 5));
203 goto exit;
204 }
205
206 hash_algo = pgpDigParamsAlgo(sigp, PGPVAL_HASHALGO);
207 if (rpmDigestLength(hash_algo) == 0) {
208 rpmlog(RPMLOG_ERR, _("Unsupported PGP hash algorithm %u\n")dcgettext ("rpm", "Unsupported PGP hash algorithm %u\n", 5), hash_algo);
209 goto exit;
210 }
211
212 pubkey_algo = pgpDigParamsAlgo(sigp, PGPVAL_PUBKEYALGO);
213 switch (pubkey_algo) {
214 case PGPPUBKEYALGO_DSA:
215 sigtag = ishdr ? RPMSIGTAG_DSA : RPMSIGTAG_GPG;
216 break;
217 case PGPPUBKEYALGO_RSA:
218 sigtag = ishdr ? RPMSIGTAG_RSA : RPMSIGTAG_PGP;
219 break;
220 default:
221 rpmlog(RPMLOG_ERR, _("Unsupported PGP pubkey algorithm %u\n")dcgettext ("rpm", "Unsupported PGP pubkey algorithm %u\n", 5),
222 pubkey_algo);
223 goto exit;
224 break;
225 }
226
227 /* Looks sane, create the tag data */
228 sigtd = rpmtdNew();
229 sigtd->count = pktlen;
230 sigtd->data = memcpy(xmalloc(pktlen)rmalloc((pktlen)), pkt, pktlen);;
231 sigtd->type = RPM_BIN_TYPE;
232 sigtd->tag = sigtag;
233 sigtd->flags |= RPMTD_ALLOCED;
234
235exit:
236 pgpDigParamsFree(sigp);
237 return sigtd;
238}
239
240static int runGPG(sigTarget sigt, const char *sigfile)
241{
242 int pid = 0, status;
243 FD_t fnamedPipe = NULL((void*)0);
244 char *namedPipeName = NULL((void*)0);
245 unsigned char buf[BUFSIZ8192];
246 ssize_t count;
247 ssize_t wantCount;
248 rpm_loff_t size;
249 int rc = 1; /* assume failure */
250
251 namedPipeName = mkTempFifo();
252
253 rpmPushMacro(NULL((void*)0), "__plaintext_filename", NULL((void*)0), namedPipeName, -1);
254 rpmPushMacro(NULL((void*)0), "__signature_filename", NULL((void*)0), sigfile, -1);
255
256 if (!(pid = fork())) {
257 char *const *av;
258 char *cmd = NULL((void*)0);
259 const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL((void*)0));
260
261 if (gpg_path && *gpg_path != '\0')
262 (void) setenv("GNUPGHOME", gpg_path, 1);
263
264 unsetenv("MALLOC_CHECK_");
265 cmd = rpmExpand("%{?__gpg_sign_cmd}", NULL((void*)0));
266 rc = poptParseArgvString(cmd, NULL((void*)0), (const char ***)&av);
267 if (!rc)
268 rc = execve(av[0], av+1, environ);
Value stored to 'rc' is never read
269
270 rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n")dcgettext ("rpm", "Could not exec %s: %s\n", 5), "gpg",
271 strerror(errno(*__errno_location ())));
272 _exit(EXIT_FAILURE1);
273 }
274
275 rpmPopMacro(NULL((void*)0), "__plaintext_filename");
276 rpmPopMacro(NULL((void*)0), "__signature_filename");
277
278 fnamedPipe = Fopen(namedPipeName, "w");
279 if (!fnamedPipe) {
280 rpmlog(RPMLOG_ERR, _("Fopen failed\n")dcgettext ("rpm", "Fopen failed\n", 5));
281 goto exit;
282 }
283
284 if (Fseek(sigt->fd, sigt->start, SEEK_SET0) < 0) {
285 rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n")dcgettext ("rpm", "Could not seek in file %s: %s\n", 5),
286 sigt->fileName, Fstrerror(sigt->fd));
287 goto exit;
288 }
289
290 size = sigt->size;
291 wantCount = size < sizeof(buf) ? size : sizeof(buf);
292 while ((count = Fread(buf, sizeof(buf[0]), wantCount, sigt->fd)) > 0) {
293 Fwrite(buf, sizeof(buf[0]), count, fnamedPipe);
294 if (Ferror(fnamedPipe)) {
295 rpmlog(RPMLOG_ERR, _("Could not write to pipe\n")dcgettext ("rpm", "Could not write to pipe\n", 5));
296 goto exit;
297 }
298 size -= count;
299 wantCount = size < sizeof(buf) ? size : sizeof(buf);
300 }
301 if (count < 0) {
302 rpmlog(RPMLOG_ERR, _("Could not read from file %s: %s\n")dcgettext ("rpm", "Could not read from file %s: %s\n", 5),
303 sigt->fileName, Fstrerror(sigt->fd));
304 goto exit;
305 }
306 Fclose(fnamedPipe);
307 fnamedPipe = NULL((void*)0);
308
309 (void) waitpid(pid, &status, 0);
310 pid = 0;
311 if (!WIFEXITED(status)(((status) & 0x7f) == 0) || WEXITSTATUS(status)(((status) & 0xff00) >> 8)) {
312 rpmlog(RPMLOG_ERR, _("gpg exec failed (%d)\n")dcgettext ("rpm", "gpg exec failed (%d)\n", 5), WEXITSTATUS(status)(((status) & 0xff00) >> 8));
313 } else {
314 rc = 0;
315 }
316
317exit:
318
319 if (fnamedPipe)
320 Fclose(fnamedPipe);
321
322 if (pid)
323 waitpid(pid, &status, 0);
324
325 if (namedPipeName) {
326 rpmRmTempFifo(namedPipeName);
327 free(namedPipeName);
328 }
329
330 return rc;
331}
332
333/**
334 * Generate GPG signature(s) for a header+payload file.
335 * @param sigh signature header
336 * @param ishdr header-only signature?
337 * @param sigt signature target
338 * @param passPhrase private key pass phrase
339 * @return generated sigtag on success, 0 on failure
340 */
341static rpmtd makeGPGSignature(Header sigh, int ishdr, sigTarget sigt)
342{
343 char * sigfile = rstrscat(NULL((void*)0), sigt->fileName, ".sig", NULL((void*)0));
344 struct stat st;
345 uint8_t * pkt = NULL((void*)0);
346 size_t pktlen = 0;
347 rpmtd sigtd = NULL((void*)0);
348
349 if (runGPG(sigt, sigfile))
350 goto exit;
351
352 if (stat(sigfile, &st)) {
353 /* GPG failed to write signature */
354 rpmlog(RPMLOG_ERR, _("gpg failed to write signature\n")dcgettext ("rpm", "gpg failed to write signature\n", 5));
355 goto exit;
356 }
357
358 pktlen = st.st_size;
359 rpmlog(RPMLOG_DEBUG, "GPG sig size: %zd\n", pktlen);
360 pkt = xmalloc(pktlen)rmalloc((pktlen));
361
362 { FD_t fd;
363
364 int rc = 0;
365 fd = Fopen(sigfile, "r.ufdio");
366 if (fd != NULL((void*)0) && !Ferror(fd)) {
367 rc = Fread(pkt, sizeof(*pkt), pktlen, fd);
368 (void) Fclose(fd);
369 }
370 if (rc != pktlen) {
371 rpmlog(RPMLOG_ERR, _("unable to read the signature\n")dcgettext ("rpm", "unable to read the signature\n", 5));
372 goto exit;
373 }
374 }
375
376 rpmlog(RPMLOG_DEBUG, "Got %zd bytes of GPG sig\n", pktlen);
377
378 /* Parse the signature, change signature tag as appropriate. */
379 sigtd = makeSigTag(sigh, ishdr, pkt, pktlen);
380exit:
381 (void) unlink(sigfile);
382 free(sigfile);
383 free(pkt);
384
385 return sigtd;
386}
387
388static void deleteSigs(Header sigh)
389{
390 headerDel(sigh, RPMSIGTAG_GPG);
391 headerDel(sigh, RPMSIGTAG_PGP);
392 headerDel(sigh, RPMSIGTAG_DSA);
393 headerDel(sigh, RPMSIGTAG_RSA);
394 headerDel(sigh, RPMSIGTAG_PGP5);
395}
396
397static int haveSignature(rpmtd sigtd, Header h)
398{
399 pgpDigParams sig1 = NULL((void*)0);
400 pgpDigParams sig2 = NULL((void*)0);
401 struct rpmtd_s oldtd;
402 int rc = 0; /* assume no */
403
404 if (!headerGet(h, rpmtdTag(sigtd), &oldtd, HEADERGET_DEFAULT))
405 return rc;
406
407 pgpPrtParams(sigtd->data, sigtd->count, PGPTAG_SIGNATURE, &sig1);
408 while (rpmtdNext(&oldtd) >= 0 && rc == 0) {
409 pgpPrtParams(oldtd.data, oldtd.count, PGPTAG_SIGNATURE, &sig2);
410 if (pgpDigParamsCmp(sig1, sig2) == 0)
411 rc = 1;
412 pgpDigParamsFree(sig2);
413 }
414 pgpDigParamsFree(sig1);
415 rpmtdFreeData(&oldtd);
416
417 return rc;
418}
419
420static int replaceSignature(Header sigh, sigTarget sigt_v3, sigTarget sigt_v4)
421{
422 int rc = -1;
423 rpmtd sigtd = NULL((void*)0);
424
425 /* Make the cheaper v4 signature first */
426 if ((sigtd = makeGPGSignature(sigh, 1, sigt_v4)) == NULL((void*)0))
427 goto exit;
428
429 /* See if we already have a signature by the same key and parameters */
430 if (haveSignature(sigtd, sigh)) {
431 rc = 1;
432 goto exit;
433 }
434 /* Nuke all signature tags */
435 deleteSigs(sigh);
436
437 if (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0)
438 goto exit;
439 rpmtdFree(sigtd);
440
441 /* Assume the same signature test holds for v3 signature too */
442 if ((sigtd = makeGPGSignature(sigh, 0, sigt_v3)) == NULL((void*)0))
443 goto exit;
444
445 if (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0)
446 goto exit;
447
448 rc = 0;
449exit:
450 rpmtdFree(sigtd);
451 return rc;
452}
453
454static void unloadImmutableRegion(Header *hdrp, rpmTagVal tag)
455{
456 struct rpmtd_s td;
457 rpmtd utd = &td;
458 Header nh;
459 Header oh;
460
461 if (headerGet(*hdrp, tag, utd, HEADERGET_DEFAULT)) {
462 oh = headerCopyLoad(utd->data);
463 nh = headerCopy(oh);
464 headerFree(oh);
465 rpmtdFreeData(utd);
466 headerFree(*hdrp);
467 *hdrp = headerLink(nh);
468 headerFree(nh);
469 }
470}
471
472#ifdef WITH_IMAEVM
473static rpmRC replaceSigDigests(FD_t fd, const char *rpm, Header *sigp,
474 off_t sigStart, off_t sigTargetSize,
475 char *SHA256, char *SHA1, uint8_t *MD5)
476{
477 off_t archiveSize;
478 rpmRC rc = RPMRC_OK;
479
480 if (Fseek(fd, sigStart, SEEK_SET0) < 0) {
481 rc = RPMRC_FAIL;
482 rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n")dcgettext ("rpm", "Could not seek in file %s: %s\n", 5),
483 rpm, Fstrerror(fd));
484 goto exit;
485 }
486
487 /* Get payload size from signature tag */
488 archiveSize = headerGetNumber(*sigp, RPMSIGTAG_PAYLOADSIZE);
489 if (!archiveSize) {
490 archiveSize = headerGetNumber(*sigp, RPMSIGTAG_LONGARCHIVESIZE);
491 }
492
493 /* Set reserved space to 0 */
494 rpmPushMacro(NULL((void*)0), "__gpg_reserved_space", NULL((void*)0), 0, RMIL_GLOBAL0);
495
496 /* Replace old digests in sigh */
497 rc = rpmGenerateSignature(SHA256, SHA1, MD5, sigTargetSize, archiveSize, fd);
498 if (rc != RPMRC_OK) {
499 rpmlog(RPMLOG_ERR, _("generateSignature failed\n")dcgettext ("rpm", "generateSignature failed\n", 5));
500 goto exit;
501 }
502
503 if (Fseek(fd, sigStart, SEEK_SET0) < 0) {
504 rc = RPMRC_FAIL;
505 rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n")dcgettext ("rpm", "Could not seek in file %s: %s\n", 5),
506 rpm, Fstrerror(fd));
507 goto exit;
508 }
509
510 headerFree(*sigp);
511 rc = rpmReadSignature(fd, sigp, NULL((void*)0));
512 if (rc != RPMRC_OK) {
513 rpmlog(RPMLOG_ERR, _("rpmReadSignature failed\n")dcgettext ("rpm", "rpmReadSignature failed\n", 5));
514 goto exit;
515 }
516
517exit:
518 return rc;
519}
520#endif
521
522static rpmRC includeFileSignatures(FD_t fd, const char *rpm,
523 Header *sigp, Header *hdrp,
524 off_t sigStart, off_t headerStart)
525{
526#ifdef WITH_IMAEVM
527 FD_t ofd = NULL((void*)0);
528 char *trpm = NULL((void*)0);
529 char *key;
530 char *keypass;
531 char *SHA1 = NULL((void*)0);
532 char *SHA256 = NULL((void*)0);
533 uint8_t *MD5 = NULL((void*)0);
534 off_t sigTargetSize;
535 rpmRC rc = RPMRC_OK;
536 struct rpmtd_s osigtd;
537 char *o_sha1 = NULL((void*)0);
538
539 unloadImmutableRegion(hdrp, RPMTAG_HEADERIMMUTABLE);
540
541 key = rpmExpand("%{?_file_signing_key}", NULL((void*)0));
542
543 keypass = rpmExpand("%{?_file_signing_key_password}", NULL((void*)0));
544 if (rstreq(keypass, "")) {
545 free(keypass);
546 keypass = NULL((void*)0);
547 }
548
549 rc = rpmSignFiles(*hdrp, key, keypass);
550 if (rc != RPMRC_OK) {
551 goto exit;
552 }
553
554 *hdrp = headerReload(*hdrp, RPMTAG_HEADERIMMUTABLE);
555 if (*hdrp == NULL((void*)0)) {
556 rc = RPMRC_FAIL;
557 rpmlog(RPMLOG_ERR, _("headerReload failed\n")dcgettext ("rpm", "headerReload failed\n", 5));
558 goto exit;
559 }
560
561 ofd = rpmMkTempFile(NULL((void*)0), &trpm);
562 if (ofd == NULL((void*)0) || Ferror(ofd)) {
563 rc = RPMRC_FAIL;
564 rpmlog(RPMLOG_ERR, _("rpmMkTemp failed\n")dcgettext ("rpm", "rpmMkTemp failed\n", 5));
565 goto exit;
566 }
567
568 /* Copy archive to temp file */
569 if (copyFile(&fd, rpm, &ofd, trpm)) {
570 rc = RPMRC_FAIL;
571 rpmlog(RPMLOG_ERR, _("copyFile failed\n")dcgettext ("rpm", "copyFile failed\n", 5));
572 goto exit;
573 }
574
575 if (Fseek(fd, headerStart, SEEK_SET0) < 0) {
576 rc = RPMRC_FAIL;
577 rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n")dcgettext ("rpm", "Could not seek in file %s: %s\n", 5),
578 rpm, Fstrerror(fd));
579 goto exit;
580 }
581
582 /* Start MD5 calculation */
583 fdInitDigestID(fd, PGPHASHALGO_MD5, RPMSIGTAG_MD5, 0);
584
585 /* Write header to rpm and recalculate digests */
586 fdInitDigestID(fd, PGPHASHALGO_SHA1, RPMSIGTAG_SHA1, 0);
587 fdInitDigestID(fd, PGPHASHALGO_SHA256, RPMSIGTAG_SHA256, 0);
588 rc = headerWrite(fd, *hdrp, HEADER_MAGIC_YES);
589 if (rc != RPMRC_OK) {
590 rpmlog(RPMLOG_ERR, _("headerWrite failed\n")dcgettext ("rpm", "headerWrite failed\n", 5));
591 goto exit;
592 }
593 fdFiniDigest(fd, RPMSIGTAG_SHA1, (void **)&SHA1, NULL((void*)0), 1);
594 /* Only add SHA256 if it was there to begin with */
595 if (headerIsEntry(*sigp, RPMSIGTAG_SHA256))
596 fdFiniDigest(fd, RPMSIGTAG_SHA256, (void **)&SHA256, NULL((void*)0), 1);
597
598 /* Copy archive from temp file */
599 if (Fseek(ofd, 0, SEEK_SET0) < 0) {
600 rc = RPMRC_FAIL;
601 rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n")dcgettext ("rpm", "Could not seek in file %s: %s\n", 5),
602 rpm, Fstrerror(fd));
603 goto exit;
604 }
605 if (copyFile(&ofd, trpm, &fd, rpm)) {
606 rc = RPMRC_FAIL;
607 rpmlog(RPMLOG_ERR, _("copyFile failed\n")dcgettext ("rpm", "copyFile failed\n", 5));
608 goto exit;
609 }
610 unlink(trpm);
611
612 sigTargetSize = Ftell(fd) - headerStart;
613 fdFiniDigest(fd, RPMSIGTAG_MD5, (void **)&MD5, NULL((void*)0), 0);
614
615 if (headerGet(*sigp, RPMSIGTAG_SHA1, &osigtd, HEADERGET_DEFAULT)) {
616 o_sha1 = xstrdup(osigtd.data)rstrdup((osigtd.data));
617 rpmtdFreeData(&osigtd);
618 }
619
620 if (strcmp(SHA1, o_sha1) == 0)
621 rpmlog(RPMLOG_WARNING,
622 _("%s already contains identical file signatures\n")dcgettext ("rpm", "%s already contains identical file signatures\n"
, 5)
,
623 rpm);
624 else
625 replaceSigDigests(fd, rpm, sigp, sigStart, sigTargetSize, SHA256, SHA1, MD5);
626
627exit:
628 free(trpm);
629 free(MD5);
630 free(SHA1);
631 free(SHA256);
632 free(o_sha1);
633 free(keypass);
634 free(key);
635 if (ofd)
636 (void) closeFile(&ofd);
637 return rc;
638#else
639 rpmlog(RPMLOG_ERR, _("file signing support not built in\n")dcgettext ("rpm", "file signing support not built in\n", 5));
640 return RPMRC_FAIL;
641#endif
642}
643
644/** \ingroup rpmcli
645 * Create/modify elements in signature header.
646 * @param rpm path to package
647 * @param deleting adding or deleting signature?
648 * @param signfiles sign files if non-zero
649 * @return 0 on success, -1 on error
650 */
651static int rpmSign(const char *rpm, int deleting, int signfiles)
652{
653 FD_t fd = NULL((void*)0);
654 FD_t ofd = NULL((void*)0);
655 char *trpm = NULL((void*)0);
656 Header sigh = NULL((void*)0);
657 Header h = NULL((void*)0);
658 char *msg = NULL((void*)0);
659 int res = -1; /* assume failure */
660 rpmRC rc;
661 struct rpmtd_s utd;
662 off_t headerStart;
663 off_t sigStart;
664 struct sigTarget_s sigt_v3;
665 struct sigTarget_s sigt_v4;
666 unsigned int origSigSize;
667 int insSig = 0;
668
669 fprintf(stdoutstdout, "%s:\n", rpm);
670
671 if (manageFile(&fd, rpm, O_RDWR02))
672 goto exit;
673
674 if ((rc = rpmLeadRead(fd, NULL((void*)0), &msg)) != RPMRC_OK) {
675 rpmlog(RPMLOG_ERR, "%s: %s\n", rpm, msg);
676 goto exit;
677 }
678
679 sigStart = Ftell(fd);
680 rc = rpmReadSignature(fd, &sigh, &msg);
681 if (rc != RPMRC_OK) {
682 rpmlog(RPMLOG_ERR, _("%s: rpmReadSignature failed: %s")dcgettext ("rpm", "%s: rpmReadSignature failed: %s", 5), rpm,
683 (msg && *msg ? msg : "\n"));
684 goto exit;
685 }
686
687 headerStart = Ftell(fd);
688 if (rpmReadHeader(NULL((void*)0), fd, &h, &msg) != RPMRC_OK) {
689 rpmlog(RPMLOG_ERR, _("%s: headerRead failed: %s\n")dcgettext ("rpm", "%s: headerRead failed: %s\n", 5), rpm, msg);
690 goto exit;
691 }
692
693 if (!headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) {
694 rpmlog(RPMLOG_ERR, _("Cannot sign RPM v3 packages\n")dcgettext ("rpm", "Cannot sign RPM v3 packages\n", 5));
695 goto exit;
696 }
697
698 if (signfiles) {
699 includeFileSignatures(fd, rpm, &sigh, &h, sigStart, headerStart);
700 }
701
702 unloadImmutableRegion(&sigh, RPMTAG_HEADERSIGNATURES);
703 origSigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
704
705 if (deleting) { /* Nuke all the signature tags. */
706 deleteSigs(sigh);
707 } else {
708 /* Signature target containing header + payload */
709 sigt_v3.fd = fd;
710 sigt_v3.start = headerStart;
711 sigt_v3.fileName = rpm;
712 sigt_v3.size = fdSize(fd) - headerStart;
713
714 /* Signature target containing only header */
715 sigt_v4 = sigt_v3;
716 sigt_v4.size = headerSizeof(h, HEADER_MAGIC_YES);
717
718 res = replaceSignature(sigh, &sigt_v3, &sigt_v4);
719 if (res != 0) {
720 if (res == 1) {
721 rpmlog(RPMLOG_WARNING,
722 _("%s already contains identical signature, skipping\n")dcgettext ("rpm", "%s already contains identical signature, skipping\n"
, 5)
,
723 rpm);
724 /* Identical signature is not an error */
725 res = 0;
726 }
727 goto exit;
728 }
729 res = -1;
730 }
731
732 /* Try to make new signature smaller to have size of original signature */
733 rpmtdReset(&utd);
734 if (headerGet(sigh, RPMSIGTAG_RESERVEDSPACE, &utd, HEADERGET_MINMEM)) {
735 int diff;
736 int count;
737 char *reservedSpace = NULL((void*)0);
738
739 count = utd.count;
740 diff = headerSizeof(sigh, HEADER_MAGIC_YES) - origSigSize;
741
742 if (diff < count) {
743 reservedSpace = xcalloc(count - diff, sizeof(char))rcalloc((count - diff), (sizeof(char)));
744 headerDel(sigh, RPMSIGTAG_RESERVEDSPACE);
745 rpmtdReset(&utd);
746 utd.tag = RPMSIGTAG_RESERVEDSPACE;
747 utd.count = count - diff;
748 utd.type = RPM_BIN_TYPE;
749 utd.data = reservedSpace;
750 headerPut(sigh, &utd, HEADERPUT_DEFAULT);
751 free(reservedSpace);
752 insSig = 1;
753 }
754 }
755
756 /* Reallocate the signature into one contiguous region. */
757 sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES);
758 if (sigh == NULL((void*)0)) /* XXX can't happen */
759 goto exit;
760
761 if (insSig) {
762 /* Insert new signature into original rpm */
763 if (Fseek(fd, sigStart, SEEK_SET0) < 0) {
764 rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n")dcgettext ("rpm", "Could not seek in file %s: %s\n", 5),
765 rpm, Fstrerror(fd));
766 goto exit;
767 }
768
769 if (rpmWriteSignature(fd, sigh)) {
770 rpmlog(RPMLOG_ERR, _("%s: rpmWriteSignature failed: %s\n")dcgettext ("rpm", "%s: rpmWriteSignature failed: %s\n", 5), rpm,
771 Fstrerror(fd));
772 goto exit;
773 }
774 res = 0;
775 } else {
776 /* Replace orignal rpm with new rpm containing new signature */
777 rasprintf(&trpm, "%s.XXXXXX", rpm);
778 ofd = rpmMkTemp(trpm);
779 if (ofd == NULL((void*)0) || Ferror(ofd)) {
780 rpmlog(RPMLOG_ERR, _("rpmMkTemp failed\n")dcgettext ("rpm", "rpmMkTemp failed\n", 5));
781 goto exit;
782 }
783
784 /* Write the lead/signature of the output rpm */
785 rc = rpmLeadWrite(ofd, h);
786 if (rc != RPMRC_OK) {
787 rpmlog(RPMLOG_ERR, _("%s: writeLead failed: %s\n")dcgettext ("rpm", "%s: writeLead failed: %s\n", 5), trpm,
788 Fstrerror(ofd));
789 goto exit;
790 }
791
792 if (rpmWriteSignature(ofd, sigh)) {
793 rpmlog(RPMLOG_ERR, _("%s: rpmWriteSignature failed: %s\n")dcgettext ("rpm", "%s: rpmWriteSignature failed: %s\n", 5), trpm,
794 Fstrerror(ofd));
795 goto exit;
796 }
797
798 if (Fseek(fd, headerStart, SEEK_SET0) < 0) {
799 rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n")dcgettext ("rpm", "Could not seek in file %s: %s\n", 5),
800 rpm, Fstrerror(fd));
801 goto exit;
802 }
803 /* Append the header and archive from the temp file */
804 if (copyFile(&fd, rpm, &ofd, trpm) == 0) {
805 struct stat st;
806
807 /* Move final target into place, restore file permissions. */
808 if (stat(rpm, &st) == 0 && unlink(rpm) == 0 &&
809 rename(trpm, rpm) == 0 && chmod(rpm, st.st_mode) == 0) {
810 res = 0;
811 } else {
812 rpmlog(RPMLOG_ERR, _("replacing %s failed: %s\n")dcgettext ("rpm", "replacing %s failed: %s\n", 5),
813 rpm, strerror(errno(*__errno_location ())));
814 }
815 }
816 }
817
818exit:
819 if (fd) (void) closeFile(&fd);
820 if (ofd) (void) closeFile(&ofd);
821
822 headerFree(sigh);
823 headerFree(h);
824 free(msg);
825
826 /* Clean up intermediate target */
827 if (trpm) {
828 (void) unlink(trpm);
829 free(trpm);
830 }
831
832 return res;
833}
834
835int rpmPkgSign(const char *path, const struct rpmSignArgs * args)
836{
837 int rc;
838
839 if (args) {
840 if (args->hashalgo) {
841 char *algo = NULL((void*)0);
842 rasprintf(&algo, "%d", args->hashalgo);
843 rpmPushMacro(NULL((void*)0), "_gpg_digest_algo", NULL((void*)0), algo, RMIL_GLOBAL0);
844 free(algo);
845 }
846 if (args->keyid) {
847 rpmPushMacro(NULL((void*)0), "_gpg_name", NULL((void*)0), args->keyid, RMIL_GLOBAL0);
848 }
849 }
850
851 rc = rpmSign(path, 0, args ? args->signfiles : 0);
852
853 if (args) {
854 if (args->hashalgo) {
855 rpmPopMacro(NULL((void*)0), "_gpg_digest_algo");
856 }
857 if (args->keyid) {
858 rpmPopMacro(NULL((void*)0), "_gpg_name");
859 }
860 }
861
862 return rc;
863}
864
865int rpmPkgDelSign(const char *path, const struct rpmSignArgs * args)
866{
867 return rpmSign(path, 1, 0);
868}