diff options
author | jbj <devnull@localhost> | 2001-10-19 19:51:18 +0000 |
---|---|---|
committer | jbj <devnull@localhost> | 2001-10-19 19:51:18 +0000 |
commit | e2dfa4f2d4f643ff2c47adfc8ae6b4b700c62b8b (patch) | |
tree | 6ce514ea2fc730cfdf1b666dffcb7625772dabf6 /lib/signature.c | |
parent | e2a842407516209b3447997d19879848d074c3d6 (diff) | |
download | librpm-tizen-e2dfa4f2d4f643ff2c47adfc8ae6b4b700c62b8b.tar.gz librpm-tizen-e2dfa4f2d4f643ff2c47adfc8ae6b4b700c62b8b.tar.bz2 librpm-tizen-e2dfa4f2d4f643ff2c47adfc8ae6b4b700c62b8b.zip |
- beecrypt is at least as good as pgp/gpg on verify, pull the plug.
CVS patchset: 5124
CVS date: 2001/10/19 19:51:18
Diffstat (limited to 'lib/signature.c')
-rw-r--r-- | lib/signature.c | 502 |
1 files changed, 139 insertions, 363 deletions
diff --git a/lib/signature.c b/lib/signature.c index e58c9b0d1..651baf858 100644 --- a/lib/signature.c +++ b/lib/signature.c @@ -1,4 +1,3 @@ -/*@-mods@*/ /** \ingroup signature * \file lib/signature.c */ @@ -235,7 +234,8 @@ static int makePGPSignature(const char * file, /*@out@*/ void ** sig, /*@out@*/ int_32 * size, /*@null@*/ const char * passPhrase) /*@globals rpmGlobalMacroContext, fileSystem @*/ - /*@modifies *sig, *size, fileSystem @*/ + /*@modifies *sig, *size, rpmGlobalMacroContext, + fileSystem @*/ { char * sigfile = alloca(1024); int pid, status; @@ -337,7 +337,8 @@ static int makeGPGSignature(const char * file, /*@out@*/ void ** sig, /*@out@*/ int_32 * size, /*@null@*/ const char * passPhrase) /*@globals rpmGlobalMacroContext, fileSystem @*/ - /*@modifies *sig, *size, fileSystem @*/ + /*@modifies *sig, *size, rpmGlobalMacroContext, + fileSystem @*/ { char * sigfile = alloca(1024); int pid, status; @@ -453,355 +454,11 @@ int rpmAddSignature(Header h, const char * file, int_32 sigTag, return ret; } -/*@-globuse@*/ -static rpmVerifySignatureReturn -verifySizeSignature(const char * datafile, int_32 size, /*@out@*/ char * result) - /*@globals fileSystem @*/ - /*@modifies *result, fileSystem @*/ -{ - struct stat st; - - (void) stat(datafile, &st); - if (size != st.st_size) { - sprintf(result, "Header+Archive size mismatch.\n" - "Expected %d, saw %d.\n", - size, (int)st.st_size); - return RPMSIG_BAD; - } - - sprintf(result, "Header+Archive size OK: %d bytes\n", size); - return RPMSIG_OK; -} -/*@=globuse@*/ - -/*@-globuse@*/ -static rpmVerifySignatureReturn -verifyMD5Signature(const char * datafile, const byte * sig, int siglen, - const rpmDigest dig, /*@out@*/ char * result, md5func fn) - /*@globals fileSystem @*/ - /*@modifies *result, fileSystem @*/ -{ - char * t = result; - byte * md5sum = NULL; - size_t md5len = 0; - int res = RPMSIG_BAD; - - /*@-branchstate@*/ - if (dig != NULL) { -/*@-type@*/ - DIGEST_CTX ctx = rpmDigestDup(dig->md5ctx); - (void) rpmDigestFinal(ctx, (void **)&md5sum, &md5len, 0); -/*@=type@*/ - } else { - int xx; - md5len = 16; - md5sum = xcalloc(1, md5len); - xx = fn(datafile, md5sum); - } - /*@=branchstate@*/ - - if (md5len != siglen || memcmp(md5sum, sig, md5len)) { - res = RPMSIG_BAD; - t = stpcpy(t, " Expected: "); - (void) pgpHexCvt(t, sig, siglen); - t += strlen(t); - t = stpcpy(t, " Actual: "); - } else { - res = RPMSIG_OK; - t = stpcpy(t, "MD5 sum OK: "); - } - (void) pgpHexCvt(t, md5sum, md5len); - - md5sum = _free(md5sum); - - return res; -} -/*@=globuse@*/ - -static rpmVerifySignatureReturn -verifyPGPSignature(/*@unused@*/ const char * datafile, - /*@unused@*/ const byte * sig, - /*@unused@*/ int siglen, - const rpmDigest dig, /*@out@*/ char * result) - /*@modifies *result */ -{ - int res, resbc; - - *result = '\0'; - - /*@-type@*/ - if (rsavrfy(&dig->rsa_pk, &dig->rsahm, &dig->c)) { - res = resbc = RPMSIG_OK; - } else { - res = resbc = RPMSIG_BAD; - } - /*@=type@*/ - -#ifdef DYING - { int pid, status, outpipe[2]; -/*@only@*/ /*@null@*/ const char * sigfile = NULL; - byte buf[BUFSIZ]; - FILE *file; - const char *path; - pgpVersion pgpVer; - - /* What version do we have? */ - if ((path = rpmDetectPGPVersion(&pgpVer)) == NULL) { - errno = ENOENT; - rpmError(RPMERR_EXEC, - _("Could not run pgp. Use --nopgp to skip PGP checks.\n")); - _exit(RPMERR_EXEC); - } - - /* - * Sad but true: pgp-5.0 returns exit value of 0 on bad signature. - * Instead we have to use the text output to detect a bad signature. - */ - if (pgpVer == PGP_5) - res = RPMSIG_BAD; - - /* Write out the signature */ -#ifdef DYING - { const char *tmppath = rpmGetPath("%{_tmppath}", NULL); - sigfile = tempnam(tmppath, "rpmsig"); - tmppath = _free(tmppath); - } - sfd = Fopen(sigfile, "w.fdio"); - if (sfd != NULL && !Ferror(sfd)) { - (void) Fwrite(sig, sizeof(char), siglen, sfd); - (void) Fclose(sfd); - } -#else - { FD_t sfd; - if (!makeTempFile(NULL, &sigfile, &sfd)) { - (void) Fwrite(sig, sizeof(*sig), siglen, sfd); - (void) Fclose(sfd); - sfd = NULL; - } - } -#endif - if (sigfile == NULL) - return RPMSIG_BAD; - - /* Now run PGP */ - outpipe[0] = outpipe[1] = 0; - (void) pipe(outpipe); - - if (!(pid = fork())) { - const char *pgp_path = rpmExpand("%{_pgp_path}", NULL); - - (void) close(outpipe[0]); - (void) close(STDOUT_FILENO); /* XXX unnecessary */ - (void) dup2(outpipe[1], STDOUT_FILENO); - - if (pgp_path && *pgp_path != '%') - (void) dosetenv("PGPPATH", pgp_path, 1); - - switch (pgpVer) { - case PGP_5: - /* Some output (in particular "This signature applies to */ - /* another message") is _always_ written to stderr; we */ - /* want to catch that output, so dup stdout to stderr: */ - { int save_stderr = dup(2); - (void) dup2(1, 2); - (void) execlp(path, "pgpv", "+batchmode=on", "+verbose=0", - /* Write "Good signature..." to stdout: */ - "+OutputInformationFD=1", - /* Write "WARNING: ... is not trusted to... to stdout: */ - "+OutputWarningFD=1", - sigfile, "-o", datafile, NULL); - /* Restore stderr so we can print the error message below. */ - (void) dup2(save_stderr, 2); - (void) close(save_stderr); - } break; - case PGP_2: - (void) execlp(path, "pgp", "+batchmode=on", "+verbose=0", - sigfile, datafile, NULL); - break; - case PGP_UNKNOWN: - case PGP_NOTDETECTED: - break; - } - - rpmError(RPMERR_EXEC, - _("Could not run pgp. Use --nopgp to skip PGP checks.\n")); - _exit(RPMERR_EXEC); - } - - (void) close(outpipe[1]); - file = fdopen(outpipe[0], "r"); - result[0] = '\0'; - if (file) { - while (fgets(buf, 1024, file)) { - if (strncmp("File '", buf, 6) && - strncmp("Text is assu", buf, 12) && - strncmp("This signature applies to another message", buf, 41) && - buf[0] != '\n') { - strcat(result, buf); - } - if (!strncmp("WARNING: Can't find the right public key", buf, 40)) - res = RPMSIG_NOKEY; - else if (!strncmp("Signature by unknown keyid:", buf, 27)) - res = RPMSIG_NOKEY; - else if (!strncmp("WARNING: The signing key is not trusted", buf, 39)) - res = RPMSIG_NOTTRUSTED; - else if (!strncmp("Good signature", buf, 14)) - res = RPMSIG_OK; - } - (void) fclose(file); - } - - (void) waitpid(pid, &status, 0); - if (sigfile) (void) unlink(sigfile); - sigfile = _free(sigfile); - if (!res && (!WIFEXITED(status) || WEXITSTATUS(status))) { - res = RPMSIG_BAD; - } - } - - if (res != resbc) { - fprintf(stderr, "=============================== RSA verify %s: rc %d\n", - datafile, resbc); - (void) pgpPrtPkts(sig, siglen, dig, 1); - printf("\t n = "); (void) fflush(stdout); - mp32println(dig->rsa_pk.n.size, dig->rsa_pk.n.modl); - printf("\t e = "); (void) fflush(stdout); - mp32println(dig->rsa_pk.e.size, dig->rsa_pk.e.data); - printf("\t c = "); (void) fflush(stdout); - mp32println(dig->c.size, dig->c.data); - printf("\t m = "); (void)fflush(stdout); - mp32println(dig->rsahm.size, dig->rsahm.data); - } -#endif /* DYING */ - - return res; -} - -static rpmVerifySignatureReturn -verifyGPGSignature(/*@unused@*/ const char * datafile, - /*@unused@*/ const byte * sig, - /*@unused@*/ int siglen, - const rpmDigest dig, /*@out@*/ char * result) - /*@modifies *result @*/ -{ - int res, resbc; - - *result = '\0'; - - /*@-type@*/ - if (dsavrfy(&dig->p, &dig->q, &dig->g, &dig->hm, &dig->y, &dig->r, &dig->s)) - res = resbc = RPMSIG_OK; - else - res = resbc = RPMSIG_BAD; - /*@=type@*/ - -#ifdef DYING - { - int pid, status, outpipe[2]; -/*@only@*/ /*@null@*/ const char * sigfile = NULL; - byte buf[BUFSIZ]; - FILE *file; - int res = RPMSIG_OK; - -/*@-type@*/ -/*@=type@*/ - - /* Write out the signature */ -#ifdef DYING - { const char *tmppath = rpmGetPath("%{_tmppath}", NULL); - sigfile = tempnam(tmppath, "rpmsig"); - tmppath = _free(tmppath); - } - sfd = Fopen(sigfile, "w.fdio"); - if (sfd != NULL && !Ferror(sfd)) { - (void) Fwrite(sig, sizeof(char), siglen, sfd); - (void) Fclose(sfd); - } -#else - { FD_t sfd; - if (!makeTempFile(NULL, &sigfile, &sfd)) { - (void) Fwrite(sig, sizeof(*sig), siglen, sfd); - (void) Fclose(sfd); - sfd = NULL; - } - } -#endif - if (sigfile == NULL) - return RPMSIG_BAD; - - /* Now run GPG */ - outpipe[0] = outpipe[1] = 0; - (void) pipe(outpipe); - - if (!(pid = fork())) { - const char *gpg_path = rpmExpand("%{_gpg_path}", NULL); - - (void) close(outpipe[0]); - /* gpg version 0.9 sends its output to stderr. */ - (void) dup2(outpipe[1], STDERR_FILENO); - - if (gpg_path && *gpg_path != '%') - (void) dosetenv("GNUPGHOME", gpg_path, 1); - - (void) execlp("gpg", "gpg", - "--batch", "--no-verbose", - "--verify", sigfile, datafile, - NULL); - rpmError(RPMERR_EXEC, - _("Could not run gpg. Use --nogpg to skip GPG checks.\n")); - _exit(RPMERR_EXEC); - } - - (void) close(outpipe[1]); - file = fdopen(outpipe[0], "r"); - result[0] = '\0'; - if (file) { - while (fgets(buf, 1024, file)) { - strcat(result, buf); - if (!xstrncasecmp("gpg: Can't check signature: Public key not found", buf, 48)) { - res = RPMSIG_NOKEY; - } - } - (void) fclose(file); - } - - (void) waitpid(pid, &status, 0); - if (sigfile) (void) unlink(sigfile); - sigfile = _free(sigfile); - if (!res && (!WIFEXITED(status) || WEXITSTATUS(status))) { - res = RPMSIG_BAD; - } - - } - - if (res != resbc) { - fprintf(stderr, "=============================== DSA verify %s: rc %d\n", - datafile, resbc); - (void) pgpPrtPkts(sig, siglen, dig, 1); - printf("\t p = "); (void) fflush(stdout); - mp32println(dig->p.size, dig->p.modl); - printf("\t q = "); (void) fflush(stdout); - mp32println(dig->q.size, dig->q.modl); - printf("\t g = "); (void) fflush(stdout); - mp32println(dig->g.size, dig->g.data); - printf("\t y = "); (void) fflush(stdout); - mp32println(dig->y.size, dig->y.data); - printf("\t r = "); (void) fflush(stdout); - mp32println(dig->r.size, dig->r.data); - printf("\t s = "); (void) fflush(stdout); - mp32println(dig->s.size, dig->s.data); - printf("\thm = "); (void) fflush(stdout); - mp32println(dig->hm.size, dig->hm.data); - } -#endif - - return res; -} - static int checkPassPhrase(const char * passPhrase, const int sigTag) /*@globals rpmGlobalMacroContext, fileSystem @*/ - /*@modifies fileSystem @*/ + /*@modifies rpmGlobalMacroContext, + fileSystem @*/ { int passPhrasePipe[2]; int pid, status; @@ -937,31 +594,150 @@ char * rpmGetPassPhrase(const char * prompt, const int sigTag) return pass; } +static rpmVerifySignatureReturn +verifySizeSignature(/*@unused@*/ const char * fn, + const byte * sig, + /*@unused@*/ int siglen, + const rpmDigest dig, /*@out@*/ char * result) + /*@modifies *result @*/ +{ + char * t = result; + int_32 size = *(int_32 *)sig; + int res; + + *t = '\0'; + t = stpcpy(t, "Header+Payload size: "); + + /*@-type@*/ + if (size != dig->nbytes) { + res = RPMSIG_BAD; + sprintf(t, "BAD Expected(%d) != (%d)\n", size, dig->nbytes); + } else { + res = RPMSIG_OK; + sprintf(t, "OK (%d)\n", dig->nbytes); + } + /*@=type@*/ + + return res; +} + +static rpmVerifySignatureReturn +verifyMD5Signature(/*@unused@*/ const char * fn, const byte * sig, int siglen, + const rpmDigest dig, /*@out@*/ char * result) + /*@modifies *result @*/ +{ + char * t = result; + byte * md5sum = NULL; + size_t md5len = 0; + int res; + + /*@-type@*/ + (void) rpmDigestFinal(rpmDigestDup(dig->md5ctx), + (void **)&md5sum, &md5len, 0); + /*@=type@*/ + + *t = '\0'; + t = stpcpy(t, "MD5 digest: "); + + if (md5len != siglen || memcmp(md5sum, sig, md5len)) { + res = RPMSIG_BAD; + t = stpcpy(t, "BAD Expected("); + (void) pgpHexCvt(t, sig, siglen); + t += strlen(t); + t = stpcpy(t, ") != ("); + } else { + res = RPMSIG_OK; + t = stpcpy(t, "OK ("); + } + (void) pgpHexCvt(t, md5sum, md5len); + t += strlen(t); + t = stpcpy(t, ")\n"); + + md5sum = _free(md5sum); + + return res; +} + +static rpmVerifySignatureReturn +verifyPGPSignature(/*@unused@*/ const char * fn, + /*@unused@*/ const byte * sig, + /*@unused@*/ int siglen, + const rpmDigest dig, /*@out@*/ char * result) + /*@modifies *result */ +{ + char * t = result; + int res; + + *t = '\0'; + t = stpcpy(t, "V3 RSA/MD5 signature: "); + + /*@-type@*/ + if (!rsavrfy(&dig->rsa_pk, &dig->rsahm, &dig->c)) { + res = RPMSIG_BAD; + t = stpcpy(t, "BAD\n"); + } else { + res = RPMSIG_OK; + t = stpcpy(t, "OK\n"); + } + /*@=type@*/ + + return res; +} + +static rpmVerifySignatureReturn +verifyGPGSignature(/*@unused@*/ const char * fn, + /*@unused@*/ const byte * sig, + /*@unused@*/ int siglen, + const rpmDigest dig, /*@out@*/ char * result) + /*@modifies *result @*/ +{ + char * t = result; + int res; + + *t = '\0'; + t = stpcpy(t, "V3 DSA signature: "); + + /*@-type@*/ + if (!dsavrfy(&dig->p, &dig->q, &dig->g, &dig->hm, &dig->y, &dig->r, &dig->s)) { + res = RPMSIG_BAD; + t = stpcpy(t, "BAD\n"); + } else { + res = RPMSIG_OK; + t = stpcpy(t, "OK\n"); + } + /*@=type@*/ + + return res; +} + rpmVerifySignatureReturn -rpmVerifySignature(const char * file, int_32 sigTag, const void * sig, +rpmVerifySignature(const char * fn, int_32 sigTag, const void * sig, int siglen, const rpmDigest dig, char * result) { + int res; switch (sigTag) { case RPMSIGTAG_SIZE: - return verifySizeSignature(file, *(int_32 *)sig, result); - /*@notreached@*/ break; + res = verifySizeSignature(fn, sig, siglen, dig, result); + break; case RPMSIGTAG_MD5: - return verifyMD5Signature(file, sig, siglen, dig, result, mdbinfile); - /*@notreached@*/ break; + res = verifyMD5Signature(fn, sig, siglen, dig, result); + break; case RPMSIGTAG_PGP5: /* XXX legacy */ case RPMSIGTAG_PGP: - return verifyPGPSignature(file, sig, siglen, dig, result); - /*@notreached@*/ break; + res = verifyPGPSignature(fn, sig, siglen, dig, result); + break; case RPMSIGTAG_GPG: - return verifyGPGSignature(file, sig, siglen, dig, result); - /*@notreached@*/ break; + res = verifyGPGSignature(fn, sig, siglen, dig, result); + break; case RPMSIGTAG_LEMD5_1: case RPMSIGTAG_LEMD5_2: + sprintf(result, "Broken MD5 digest: UNSUPPORTED\n"); + res = RPMSIG_UNKNOWN; + break; default: - sprintf(result, "Do not know how to verify sig type %d\n", sigTag); - return RPMSIG_UNKNOWN; + sprintf(result, "Signature: UNKNOWN(%d)\n", sigTag); + res = RPMSIG_UNKNOWN; + break; } - /*@notreached@*/ - return RPMSIG_OK; + return res; } -/*@=mods@*/ |