rpm/checksig.c

292 lines
6.6 KiB
C

/* checksig.c: verify the signature of an RPM */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include "checksig.h"
#include "intl.h"
#include "rpmlib.h"
#include "rpmlead.h"
#include "signature.h"
#include "messages.h"
int doReSign(int add, char *passPhrase, char **argv)
{
int fd, ofd, count;
struct rpmlead lead;
unsigned short sigtype;
char *rpm, sigtarget[1024];
char tmprpm[1024];
unsigned char buffer[8192];
Header sig;
while (*argv) {
rpm = *argv++;
printf("%s:\n", rpm);
if ((fd = open(rpm, O_RDONLY, 0644)) < 0) {
fprintf(stderr, _("%s: Open failed\n"), rpm);
exit(1);
}
if (readLead(fd, &lead)) {
fprintf(stderr, _("%s: readLead failed\n"), rpm);
exit(1);
}
if (lead.major == 1) {
fprintf(stderr, _("%s: Can't sign v1.0 RPM\n"), rpm);
exit(1);
}
if (lead.major == 2) {
fprintf(stderr, _("%s: Can't re-sign v2.0 RPM\n"), rpm);
exit(1);
}
if (rpmReadSignature(fd, &sig, lead.signature_type)) {
fprintf(stderr, _("%s: rpmReadSignature failed\n"), rpm);
exit(1);
}
if (add != ADD_SIGNATURE) {
rpmFreeSignature(sig);
}
/* Write the rest to a temp file */
strcpy(sigtarget, tempnam(rpmGetVar(RPMVAR_TMPPATH), "rpmsigtarget"));
ofd = open(sigtarget, O_WRONLY|O_CREAT|O_TRUNC, 0644);
while ((count = read(fd, buffer, sizeof(buffer))) > 0) {
if (count == -1) {
perror(_("Couldn't read the header/archive"));
close(ofd);
unlink(sigtarget);
exit(1);
}
if (write(ofd, buffer, count) < 0) {
perror(_("Couldn't write header/archive to temp file"));
close(ofd);
unlink(sigtarget);
exit(1);
}
}
close(fd);
close(ofd);
/* Start writing the new RPM */
sprintf(tmprpm, "%s.tmp", rpm);
ofd = open(tmprpm, O_WRONLY|O_CREAT|O_TRUNC, 0644);
lead.signature_type = RPMSIG_HEADERSIG;
if (writeLead(ofd, &lead)) {
perror("writeLead()");
close(ofd);
unlink(sigtarget);
unlink(tmprpm);
exit(1);
}
/* Generate the signature */
sigtype = rpmLookupSignatureType();
rpmMessage(RPMMESS_VERBOSE, "Generating signature: %d\n", sigtype);
if (add != ADD_SIGNATURE) {
sig = rpmNewSignature();
rpmAddSignature(sig, sigtarget, RPMSIGTAG_SIZE, passPhrase);
rpmAddSignature(sig, sigtarget, RPMSIGTAG_MD5, passPhrase);
}
if (sigtype>0) {
rpmAddSignature(sig, sigtarget, sigtype, passPhrase);
}
if (rpmWriteSignature(ofd, sig)) {
close(ofd);
unlink(sigtarget);
unlink(tmprpm);
rpmFreeSignature(sig);
exit(1);
}
rpmFreeSignature(sig);
/* Append the header and archive */
fd = open(sigtarget, O_RDONLY);
while ((count = read(fd, buffer, sizeof(buffer))) > 0) {
if (count == -1) {
perror(_("Couldn't read sigtarget"));
close(ofd);
close(fd);
unlink(sigtarget);
unlink(tmprpm);
exit(1);
}
if (write(ofd, buffer, count) < 0) {
perror(_("Couldn't write package"));
close(ofd);
close(fd);
unlink(sigtarget);
unlink(tmprpm);
exit(1);
}
}
close(fd);
close(ofd);
unlink(sigtarget);
/* Move it in to place */
unlink(rpm);
rename(tmprpm, rpm);
}
return 0;
}
int doCheckSig(int flags, char **argv)
{
int fd, ofd, res, res2, res3, missingKeys;
struct rpmlead lead;
char *rpm;
char result[1024], sigtarget[1024];
unsigned char buffer[8192];
Header sig;
HeaderIterator sigIter;
int_32 tag, type, count;
void *ptr;
res = 0;
while (*argv) {
rpm = *argv++;
if ((fd = open(rpm, O_RDONLY, 0644)) < 0) {
fprintf(stderr, _("%s: Open failed\n"), rpm);
res++;
continue;
}
if (readLead(fd, &lead)) {
fprintf(stderr, _("%s: readLead failed\n"), rpm);
res++;
continue;
}
if (lead.major == 1) {
fprintf(stderr, _("%s: No signature available (v1.0 RPM)\n"), rpm);
res++;
continue;
}
if (rpmReadSignature(fd, &sig, lead.signature_type)) {
fprintf(stderr, _("%s: rpmReadSignature failed\n"), rpm);
res++;
continue;
}
if (! sig) {
fprintf(stderr, _("%s: No signature available\n"), rpm);
res++;
continue;
}
/* Write the rest to a temp file */
strcpy(sigtarget, tempnam(rpmGetVar(RPMVAR_TMPPATH), "rpmsigtarget"));
ofd = open(sigtarget, O_WRONLY|O_CREAT|O_TRUNC, 0644);
while ((count = read(fd, buffer, sizeof(buffer))) > 0) {
if (count == -1) {
perror(_("Couldn't read the header/archive"));
close(ofd);
unlink(sigtarget);
exit(1);
}
if (write(ofd, buffer, count) < 0) {
fprintf(stderr, _("Unable to write %s"), sigtarget);
perror("");
close(ofd);
unlink(sigtarget);
exit(1);
}
}
close(fd);
close(ofd);
sigIter = headerInitIterator(sig);
res2 = 0;
missingKeys = 0;
if (rpmIsVerbose()) {
sprintf(buffer, "%s:\n", rpm);
} else {
sprintf(buffer, "%s: ", rpm);
}
while (headerNextIterator(sigIter, &tag, &type, &ptr, &count)) {
if ((tag == RPMSIGTAG_PGP) && !(flags & CHECKSIG_PGP))
continue;
else if ((tag == RPMSIGTAG_MD5 ||
tag == RPMSIGTAG_LEMD5_2 ||
tag == RPMSIGTAG_LEMD5_1)
&& !(flags & CHECKSIG_MD5))
continue;
if ((res3 = rpmVerifySignature(sigtarget, tag, ptr, count,
result))) {
if (rpmIsVerbose()) {
strcat(buffer, result);
res2 = 1;
} else {
switch (tag) {
case RPMSIGTAG_SIZE:
strcat(buffer, "SIZE ");
res2 = 1;
break;
case RPMSIGTAG_MD5:
case RPMSIGTAG_LEMD5_1:
case RPMSIGTAG_LEMD5_2:
strcat(buffer, "MD5 ");
res2 = 1;
break;
case RPMSIGTAG_PGP:
if (res3 == RPMSIG_NOKEY) {
/* Do not consedier this a failure */
strcat(buffer, "(PGP) ");
missingKeys = 1;
} else {
strcat(buffer, "PGP ");
res2 = 1;
}
break;
default:
strcat(buffer, "?UnknownSignatureType? ");
res2 = 1;
}
}
} else {
if (rpmIsVerbose()) {
strcat(buffer, result);
} else {
switch (tag) {
case RPMSIGTAG_SIZE:
strcat(buffer, "size ");
break;
case RPMSIGTAG_MD5:
case RPMSIGTAG_LEMD5_1:
case RPMSIGTAG_LEMD5_2:
strcat(buffer, "md5 ");
break;
case RPMSIGTAG_PGP:
strcat(buffer, "pgp ");
break;
default:
strcat(buffer, "??? ");
}
}
}
}
headerFreeIterator(sigIter);
res += res2;
unlink(sigtarget);
if (res2) {
if (rpmIsVerbose()) {
fprintf(stderr, "%s", buffer);
} else {
fprintf(stderr, "%sNOT OK%s\n", buffer,
missingKeys ? _(" (MISSING KEYS)") : "");
}
} else {
if (rpmIsVerbose()) {
printf("%s", buffer);
} else {
printf("%sOK%s\n", buffer,
missingKeys ? _(" (MISSING KEYS)") : "");
}
}
}
return res;
}