rpm/checksig.c

331 lines
7.7 KiB
C

/* checksig.c: verify the signature of an RPM */
#include "system.h"
#include "build/rpmbuild.h"
#include "checksig.h"
#include "rpmlead.h"
#include "signature.h"
int doReSign(int add, char *passPhrase, char **argv)
{
FD_t fd, ofd;
int count;
struct rpmlead lead;
unsigned short sigtype;
char *rpm;
const char *sigtarget;
char tmprpm[1024];
unsigned char buffer[8192];
Header sig;
while (*argv) {
rpm = *argv++;
fprintf(stdout, "%s:\n", rpm);
if (fdFileno(fd = fdOpen(rpm, O_RDONLY, 0644)) < 0) {
fprintf(stderr, _("%s: Open failed\n"), rpm);
exit(EXIT_FAILURE);
}
if (readLead(fd, &lead)) {
fprintf(stderr, _("%s: readLead failed\n"), rpm);
exit(EXIT_FAILURE);
}
if (lead.major == 1) {
fprintf(stderr, _("%s: Can't sign v1.0 RPM\n"), rpm);
exit(EXIT_FAILURE);
}
if (lead.major == 2) {
fprintf(stderr, _("%s: Can't re-sign v2.0 RPM\n"), rpm);
exit(EXIT_FAILURE);
}
if (rpmReadSignature(fd, &sig, lead.signature_type)) {
fprintf(stderr, _("%s: rpmReadSignature failed\n"), rpm);
exit(EXIT_FAILURE);
}
if (add != ADD_SIGNATURE) {
rpmFreeSignature(sig);
}
/* Write the rest to a temp file */
if (makeTempFile(NULL, &sigtarget, &ofd))
exit(EXIT_FAILURE);
while ((count = fdRead(fd, buffer, sizeof(buffer))) > 0) {
if (count == -1) {
perror(_("Couldn't read the header/archive"));
fdClose(ofd);
unlink(sigtarget);
xfree(sigtarget);
exit(EXIT_FAILURE);
}
if (fdWrite(ofd, buffer, count) < 0) {
perror(_("Couldn't write header/archive to temp file"));
fdClose(ofd);
unlink(sigtarget);
xfree(sigtarget);
exit(EXIT_FAILURE);
}
}
fdClose(fd);
fdClose(ofd);
/* Start writing the new RPM */
strcpy(tmprpm, rpm);
strcat(tmprpm, ".XXXXXX");
mktemp(tmprpm);
ofd = fdOpen(tmprpm, O_WRONLY|O_CREAT|O_TRUNC, 0644);
lead.signature_type = RPMSIG_HEADERSIG;
if (writeLead(ofd, &lead)) {
perror("writeLead()");
fdClose(ofd);
unlink(sigtarget);
unlink(tmprpm);
xfree(sigtarget);
exit(EXIT_FAILURE);
}
/* 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)) {
fdClose(ofd);
unlink(sigtarget);
unlink(tmprpm);
xfree(sigtarget);
rpmFreeSignature(sig);
exit(EXIT_FAILURE);
}
rpmFreeSignature(sig);
/* Append the header and archive */
fd = fdOpen(sigtarget, O_RDONLY, 0);
while ((count = fdRead(fd, buffer, sizeof(buffer))) > 0) {
if (count == -1) {
perror(_("Couldn't read sigtarget"));
fdClose(ofd);
fdClose(fd);
unlink(sigtarget);
unlink(tmprpm);
xfree(sigtarget);
exit(EXIT_FAILURE);
}
if (fdWrite(ofd, buffer, count) < 0) {
perror(_("Couldn't write package"));
fdClose(ofd);
fdClose(fd);
unlink(sigtarget);
unlink(tmprpm);
xfree(sigtarget);
exit(EXIT_FAILURE);
}
}
fdClose(fd);
fdClose(ofd);
unlink(sigtarget);
xfree(sigtarget);
/* Move it in to place */
unlink(rpm);
rename(tmprpm, rpm);
}
return 0;
}
int doCheckSig(int flags, char **argv)
{
FD_t fd, ofd;
int res, res2, res3;
struct rpmlead lead;
char *rpm;
char result[1024];
const char * sigtarget;
unsigned char buffer[8192];
unsigned char missingKeys[7164];
char *tempKey;
Header sig;
HeaderIterator sigIter;
int_32 tag, type, count;
void *ptr;
res = 0;
while (*argv) {
rpm = *argv++;
if (fdFileno(fd = fdOpen(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 == NULL) {
fprintf(stderr, _("%s: No signature available\n"), rpm);
res++;
continue;
}
/* Write the rest to a temp file */
if (makeTempFile(NULL, &sigtarget, &ofd))
exit(EXIT_FAILURE);
while ((count = fdRead(fd, buffer, sizeof(buffer))) > 0) {
if (count == -1) {
perror(_("Couldn't read the header/archive"));
fdClose(ofd);
unlink(sigtarget);
xfree(sigtarget);
exit(EXIT_FAILURE);
}
if (fdWrite(ofd, buffer, count) < 0) {
fprintf(stderr, _("Unable to write %s"), sigtarget);
perror("");
fdClose(ofd);
unlink(sigtarget);
xfree(sigtarget);
exit(EXIT_FAILURE);
}
}
fdClose(fd);
fdClose(ofd);
sigIter = headerInitIterator(sig);
res2 = 0;
missingKeys[0] = '\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;
if ((tag == RPMSIGTAG_GPG) && !(flags & CHECKSIG_GPG))
continue;
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 consider this a failure */
strcat(buffer, "(PGP) ");
strcat(missingKeys, " PGP#");
tempKey = strstr(result, "Key ID");
strncat(missingKeys, tempKey+7, 8);
} else {
strcat(buffer, "PGP ");
res2 = 1;
}
break;
case RPMSIGTAG_GPG:
if (res3 == RPMSIG_NOKEY) {
/* Do not consider this a failure */
strcat(buffer, "(GPG) ");
strcat(missingKeys, " GPG#");
tempKey = strstr(result, "key ID");
strncat(missingKeys, tempKey+7, 8);
} else {
strcat(buffer, "GPG ");
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;
case RPMSIGTAG_GPG:
strcat(buffer, "gpg ");
break;
default:
strcat(buffer, "??? ");
}
}
}
}
headerFreeIterator(sigIter);
res += res2;
unlink(sigtarget);
xfree(sigtarget);
if (res2) {
if (rpmIsVerbose()) {
fprintf(stderr, "%s", (char *)buffer);
} else {
fprintf(stderr, "%s%s%s%s%s\n", (char *)buffer, _("NOT OK"),
(missingKeys[0] != '\0') ? _(" (MISSING KEYS:") : "",
(char *)missingKeys,
(missingKeys[0] != '\0') ? _(")") : "");
}
} else {
if (rpmIsVerbose()) {
fprintf(stdout, "%s", (char *)buffer);
} else {
fprintf(stdout, "%s%s%s%s%s\n", (char *)buffer, _("OK"),
(missingKeys[0] != '\0') ? _(" (MISSING KEYS:") : "",
(char *)missingKeys,
(missingKeys[0] != '\0') ? _(")") : "");
}
}
}
return res;
}