diff -uNr rpm2html-1.5.orig/Makefile.in rpm2html-1.5/Makefile.in --- rpm2html-1.5.orig/Makefile.in Sun Sep 24 16:34:03 2000 +++ rpm2html-1.5/Makefile.in Sun Nov 5 18:27:16 2000 @@ -5,8 +5,9 @@ #CC = insure SQL_FLAGS=@SQL_FLAGS@ +GPG_FLAGS=@GPG_FLAGS@ -CFLAGS = @CFLAGS@ $(SQL_FLAGS) -Wall +CFLAGS = @CFLAGS@ $(SQL_FLAGS) $(GPG_FLAGS) -Wall #CFLAGS = -Wall -g -DDEBUG #CFLAGS = -Wall -O6 diff -uNr rpm2html-1.5.orig/configure.in rpm2html-1.5/configure.in --- rpm2html-1.5.orig/configure.in Mon Aug 21 20:35:48 2000 +++ rpm2html-1.5/configure.in Sun Nov 5 18:27:16 2000 @@ -132,4 +132,33 @@ AC_SUBST(SQL_PROGS) AC_SUBST(SQL_OBJ) +dnl +dnl Do we plug in the gpg? +dnl + +GPG_FLAGS= +GPG_PROG= +AC_ARG_WITH(gpg, [ --with-gpg Add the GPG support (off)]) +if test "x$with_gpg" != "x" ; then + if test "$with_gpg" = "yes" ; then + AC_PATH_PROG(GPG_PROG, gpg, /usr/bin/gpg) + else + AC_PATH_PROG(GPG_PROG, gpg, "$with_gpg") + fi + + dnl for now, signature resolving code is implemented only with librpmio + dnl so without librpmio it wont work + AC_CHECK_LIB(rpmio, Fopen, + [LIBS="-lrpmio $LIBS"; + AC_DEFINE_UNQUOTED(USE_RPMIO, 1) + AC_SUBST(USE_RPMIO) + ], + AC_MSG_ERROR(*** librpmio not found, use --without-gpg)) + + echo Enabling GPG support + GPG_FLAGS="-DWITH_GPG -DGPG_PROG=\\\"$GPG_PROG\\\"" +fi +AC_SUBST(GPG_FLAGS) +AC_SUBST(GPG_PROG) + AC_OUTPUT(Makefile) diff -uNr rpm2html-1.5.orig/html.c rpm2html-1.5/html.c --- rpm2html-1.5.orig/html.c Sun Sep 24 16:14:39 2000 +++ rpm2html-1.5/html.c Sun Nov 5 18:27:16 2000 @@ -22,6 +22,8 @@ #include #include +#include + #include "rpm2html.h" #include "rpmdata.h" #include "html.h" @@ -359,13 +361,91 @@ } /* + * Generates signature info (extended ASCII charset) + * The string returned is a shared location. + */ +#define X(_x) (unsigned)((_x) & 0xff) + +static unsigned char *sigInfoMD5 = "MD5: "; +#if defined(WITH_GPG) +static unsigned char *sigInfoGPG = "GPG:\n"; +static unsigned char *sigInfoPGP = "PGP:\n"; +#else +static unsigned char *sigInfoGPG = "GPG"; +static unsigned char *sigInfoPGP = "PGP"; +#endif +static unsigned char *sigInfoU = "unknown"; + +static unsigned char *sbuffer = NULL; +static int sbuffer_size = 2000; +static unsigned char *sbuffer2 = NULL; +static int sbuffer2_size = 3; +char *convertSIG(rpmSigPtr sig) { + int n1; + unsigned char *md5sum = sig->sig; + + if (sbuffer == NULL) { + sbuffer = (char *) debugMalloc(sbuffer_size * sizeof(char)); + if (sbuffer == NULL) { + perror("debugMalloc failed"); + exit(1); + } + } + if (sbuffer2 == NULL) { + sbuffer2 = (char *) debugMalloc(sbuffer2_size * sizeof(char)); + if (sbuffer2 == NULL) { + perror("debugMalloc failed"); + exit(1); + } + } + + switch(sig->tag) { + case RPMSIGTAG_MD5: + strncpy(sbuffer, sigInfoMD5, sbuffer_size); + for(n1 = 0; n1 < sig->size; n1++) { + snprintf(sbuffer2, sbuffer2_size, "%02x", X(md5sum[n1])); + strncat(sbuffer, sbuffer2, sbuffer_size); + } + return(sbuffer); + case RPMSIGTAG_GPG: + #if defined(WITH_GPG) + strncpy(sbuffer, sigInfoGPG, sbuffer_size); + if (sig->resolve != NULL) + strncat(sbuffer, sig->resolve, sbuffer_size); + return(sbuffer); + #else + return(sigInfoGPG); + #endif + case RPMSIGTAG_PGP: + #if defined(WITH_GPG) + strncpy(sbuffer, sigInfoPGP, sbuffer_size); + if (sig->resolve != NULL) + strncat(sbuffer, sig->resolve, sbuffer_size); + return(sbuffer); + #else + return(sigInfoPGP); + #endif + default: + return(sigInfoU); + } +} + +/* * Cleanup the global varibales of this module */ void htmlCleanup(void) { if (buffer != NULL) debugFree(buffer); + if (sbuffer != NULL) + debugFree(buffer); + if (sbuffer2 != NULL) + debugFree(buffer); buffer = NULL; buffer_size = 2000; + sbuffer = NULL; + sbuffer_size = 2000; + sbuffer2 = NULL; + sbuffer2_size = 3; } /* @@ -1274,6 +1354,12 @@ fprintf(html, "

%s

\n", localizedStrings[LANG_COPYRIGHT]); fprintf(html, "
%s\n
\n", convertHTML(rpm->extra->copyright)); + } + if (rpm->extra->sigs != NULL) { + fprintf(html, "

%s

\n", + localizedStrings[LANG_SIGNATURES]); + for(i = 0; i < rpm->extra->nb_sigs; i++) + fprintf(html, "
%s\n
\n", convertHTML(convertSIG(rpm->extra->sigs[i]))); } if (rpm->extra->changelog) { fprintf(html, "

%s

\n", diff -uNr rpm2html-1.5.orig/language.c rpm2html-1.5/language.c --- rpm2html-1.5.orig/language.c Sun Sep 24 16:14:40 2000 +++ rpm2html-1.5/language.c Sun Nov 5 18:27:06 2000 @@ -127,7 +127,8 @@ "
\n\ \n\ \n\ -
\n" + \n", + "Signatures" }; #define NB_STRINGS (sizeof(localizedStrings)/sizeof(char *)) diff -uNr rpm2html-1.5.orig/language.h rpm2html-1.5/language.h --- rpm2html-1.5.orig/language.h Sat Sep 9 21:29:03 2000 +++ rpm2html-1.5/language.h Sun Nov 5 18:27:06 2000 @@ -91,6 +91,7 @@ #define LANG_TREE_HTML 79 #define LANG_BROWSE_TREE 80 #define LANG_SEARCH_FORM 81 +#define LANG_SIGNATURES 82 /* * Array containing the localized language strings. diff -uNr rpm2html-1.5.orig/rpmdata.h rpm2html-1.5/rpmdata.h --- rpm2html-1.5.orig/rpmdata.h Sat Sep 9 14:06:59 2000 +++ rpm2html-1.5/rpmdata.h Sun Nov 5 18:27:16 2000 @@ -148,6 +148,9 @@ int max_requires; /* #of resources slot allocated */ struct rpm_resource **requires;/* list of them */ char *filelist; /* the filelist */ + int nb_sigs; /* #of signatures required */ + int max_sigs; /* #of signatures slot allocated */ + struct rpm_sig **sigs; /* list of them */ } rpmExtraData, *rpmExtraDataPtr; /* @@ -165,6 +168,18 @@ struct rpm_data **provider; /* list of them */ } rpmRess, *rpmRessPtr; +/* + * structure associated with signature + */ +typedef struct rpm_sig { + int size; /* size of signature */ + int tag; /* signature tag */ + int type; /* signature type */ + int *sig; /* signature */ + #if defined(WITH_GPG) + char *resolve; /* resolved signature */ + #endif +} rpmSig, *rpmSigPtr; /* * Variables. diff -uNr rpm2html-1.5.orig/rpmopen.c rpm2html-1.5/rpmopen.c --- rpm2html-1.5.orig/rpmopen.c Sat Sep 9 21:29:03 2000 +++ rpm2html-1.5/rpmopen.c Sun Nov 5 18:27:16 2000 @@ -3,7 +3,7 @@ * * See Copyright for the status of this software. * - * $Id: rpmopen.c,v 1.82 2000/09/09 19:29:02 veillard Exp $ + * $Id: rpmopen.c,v 1.84 2000/10/25 08:47:19 daniel Exp $ */ #include @@ -24,6 +24,16 @@ #include #include /* Added by A. Gibert */ +//#include - not included in rpm-devel package +// XXX hack - I hope that readLead IS in librpm.o even when .h is missing +int readLead(FD_t fd, /*@out@*/struct rpmlead *lead); +//#include - not included in rpm-devel package +// XXX hack - I hope that int rpmReadSignature IS in librpm.o even when .h is missing +int rpmReadSignature(FD_t fd, /*@out@*/ Header *header, short sig_type); + +#if defined(WITH_GPG) +#include +#endif #include "rpm2html.h" #include "rpmdata.h" @@ -57,6 +67,7 @@ void rpmFreeExtraData(rpmDataPtr rpm) { rpmExtraDataPtr extra; + int n1; if ((rpm == NULL) || (rpm->extra == NULL)) return; extra = rpm->extra; @@ -69,6 +80,17 @@ if (extra->resources != NULL) debugFree(extra->resources); if (extra->requires != NULL) debugFree(extra->requires); if (extra->filelist != NULL) debugFree(extra->filelist); + if (extra->sigs != NULL) { + for (n1 = 0; n1 < extra->nb_sigs; n1++) + if (extra->sigs[n1] != NULL) { + if (extra->sigs[n1]->sig != NULL) + debugFree(extra->sigs[n1]->sig); + if (extra->sigs[n1]->resolve != NULL) + debugFree(extra->sigs[n1]->resolve); + debugFree(extra->sigs[n1]); + } + debugFree(extra->sigs); + } debugFree(extra); } @@ -173,6 +195,115 @@ return(1); } +#if defined(WITH_GPG) +/* + * rpmResolveGPGPSignatures : resolve GPG and PGP signatures found in package + * code based on rpm-4.0-0.45 + */ +void rpmResolveGPGPSignature(const char *nameRpm, const char *sigtarget, + const char *sigfile, rpmDataPtr rpm, int sign) { + int pid, status, outpipe[2]; + FILE *file; + int rsize = 128, crsize; + unsigned char buf[8192]; + + /* Now run GPG */ + outpipe[0] = outpipe[1] = 0; + pipe(outpipe); + + if (!(pid = fork())) { + close(outpipe[0]); + /* gpg version 0.9 sends its output to stderr. */ + dup2(outpipe[1], STDERR_FILENO); + + execlp(GPG_PROG, GPG_PROG, + "--batch", "--no-verbose", + "--verify", sigfile, sigtarget, + NULL); + fprintf(stderr, "%s exec failed!\n", GPG_PROG); + exit(1); + } + + close(outpipe[1]); + file = fdopen(outpipe[0], "r"); + rpm->extra->sigs[sign]->resolve = debugMalloc(sizeof(char) * rsize); + rpm->extra->sigs[sign]->resolve[0] = '\0'; + while (fgets(buf, 1024, file)) { + crsize = strlen(buf) + strlen(rpm->extra->sigs[sign]->resolve); + if (crsize >= rsize) { + rsize = crsize * 2; + rpm->extra->sigs[sign]->resolve = debugRealloc(rpm->extra->sigs[sign]->resolve, + sizeof(char) * rsize); + if (rpm->extra->sigs[sign]->resolve == NULL) { + fprintf(stderr, "cannot re-allocate %d bytes: %s\n", + rsize, strerror(errno)); + exit (1); + } + } + + strcat(rpm->extra->sigs[sign]->resolve, buf); + } + fclose(file); + + (void)waitpid(pid, &status, 0); +} + +/* + * rpmResolveMD5Signatures : resolve MD5 signatures found in package + * code based on rpm-4.0-0.45 + * for now, we are not checking whether MD5 sums are OK + */ +/*void rpmResolveMD5Signature(const char *nameRpm, const char *sigtarget, + const char *sigfile, rpmDataPtr rpm, int sign) { +}*/ + +/* + * rpmResolveSignatures : resolve signatures found in package + * code based on rpm-4.0-0.45 + */ +void rpmResolveSignatures(const char *path, const char *nameRpm, + const char *sigtarget, rpmDataPtr rpm) { + int sign = 0; + + if (rpm == NULL || rpm->extra->nb_sigs == 0 || sigtarget == NULL) return; + + for (sign = 0; sign < rpm->extra->nb_sigs; sign++) { + FD_t sfd; + char *sigfile = NULL; + + if (rpm->extra->sigs[sign]->tag != RPMSIGTAG_PGP + && rpm->extra->sigs[sign]->tag != RPMSIGTAG_GPG) + continue; + + /* Write out the signature */ + sigfile = debugMalloc(30); + strcpy(sigfile, "/tmp/rpm2html.sig.XXXXXX"); + sigfile = mktemp(sigfile); + sfd = Fopen(sigfile, "w.fdio"); + (void)Fwrite(rpm->extra->sigs[sign]->sig, sizeof(char), + rpm->extra->sigs[sign]->size, sfd); + Fclose(sfd); + + switch(rpm->extra->sigs[sign]->tag) { + case RPMSIGTAG_PGP: + case RPMSIGTAG_GPG: + rpmResolveGPGPSignature(nameRpm, sigtarget, sigfile, rpm, sign); + break; + /*case RPMSIGTAG_MD5: + rpmResolveMD5Signature(nameRpm, sigtarget, sigfile, rpm, sign); + break;*/ + default: + break; + } + + if (sigfile != NULL) { + unlink(sigfile); + debugFree(sigfile); + } + } +} +#endif + /* * rpmAnalyze : analyze an RPM record, read and parse the header and * fill the informations in the database. @@ -184,8 +315,9 @@ static char *buffer = NULL; static int buffer_size = 50 * 1024 * sizeof(char); -rpmDataPtr rpmAnalyze(char *path, char *nameRpm, Header h, rpmDirPtr dir, - rpmSubdirPtr tree, time_t stamp, int isSource) { +rpmDataPtr rpmAnalyze(char *path, char *nameRpm, const char *sigtarget, + Header h, Header s, rpmDirPtr dir, rpmSubdirPtr tree, + time_t stamp, int isSource) { int installed = dir->installbase; char * name = NULL, * version = NULL, * release = NULL; int_32 count, type; @@ -196,6 +328,7 @@ #ifdef WITH_SQL int id; #endif + HeaderIterator sIter; if (buffer == NULL) { buffer = (char *) debugMalloc(buffer_size); @@ -510,6 +643,46 @@ else rpm->vendor = debugStrdup(localizedStrings[LANG_UNKNOWN]); } + if (s == NULL) + rpm->extra->sigs = NULL; + else { + int tag, type; + + rpm->extra->max_sigs = 1; + rpm->extra->sigs = (rpmSigPtr *) debugMalloc(sizeof(rpmSigPtr) * + rpm->extra->max_sigs); + rpm->extra->sigs[0] = NULL; + rpm->extra->nb_sigs = 0; + + for (sIter = headerInitIterator(s); + headerNextIterator(sIter, &tag, &type, &p, &count); + ) + { + if ((tag != RPMSIGTAG_MD5) && (tag != RPMSIGTAG_PGP) && (tag != RPMSIGTAG_GPG)) + continue; + if (rpm->extra->nb_sigs >= rpm->extra->max_sigs) { + rpm->extra->max_sigs *= 2; + rpm->extra->sigs = (rpmSigPtr *) debugRealloc(rpm->extra->sigs, + sizeof(rpmSigPtr) * rpm->extra->max_sigs); + if (rpm->extra->sigs == NULL) { + fprintf(stderr, "cannot re-allocate %d bytes: %s\n", + rpm->extra->max_sigs, strerror(errno)); + exit(1); + } + } + + rpm->extra->sigs[rpm->extra->nb_sigs] = (rpmSigPtr) debugMalloc(sizeof(rpmSig)); + rpm->extra->sigs[rpm->extra->nb_sigs]->tag = tag; + rpm->extra->sigs[rpm->extra->nb_sigs]->type = type; + rpm->extra->sigs[rpm->extra->nb_sigs]->size = count; + rpm->extra->sigs[rpm->extra->nb_sigs]->sig = debugMalloc(count); + memcpy(rpm->extra->sigs[rpm->extra->nb_sigs]->sig, p, count); + rpm->extra->sigs[rpm->extra->nb_sigs]->resolve = NULL; + rpm->extra->nb_sigs++; + ENTRY_CLEANUP(p); + } + } + rpm->filename = debugStrdup(nameRpm); /* package-xxx.rpm provides at least the resource "package" */ @@ -628,6 +801,10 @@ } ENTRY_CLEANUP(p); + #ifdef WITH_GPG + rpmResolveSignatures(path, nameRpm, sigtarget, rpm); + #endif WITH_GPG + #ifdef WITH_SQL id = sql_add_package(path, rpm->name, rpm->version, rpm->release, rpm->arch, dir->no, rpm->url, rpm->extra->srcrpm, @@ -719,9 +896,17 @@ #endif int rc; Header h = NULL; + Header s = NULL; + struct rpmlead lead; int isSource; char buffer[500]; struct stat buf; +#if defined(WITH_GPG) + FD_t ofd = NULL; + char *sigtarget = NULL; + ssize_t count; + unsigned char stbuffer[8192]; +#endif /* open the file for reading */ if (tree->htmlpath[0] != '\0') @@ -778,16 +963,107 @@ return(NULL); } - cur = rpmAnalyze(buffer, nameRpm, h, dir, tree, buf.st_mtime, isSource); - /* free the header and close the descriptor */ - headerFree(h); + /* close the descriptor */ +#if defined(USE_RPMIO) + Fclose(fd); +#else + fdClose(fd); +#endif + + /* XXX I do not know whether it is necessary to open the file twice */ + /* open the file for reading */ +#if defined(USE_RPMIO) + fd = Fopen(buffer, "r.fdio"); + if (fd == NULL || Ferror(fd)) { + fprintf(stderr, "Fopen of %s failed: %s\n", buffer, + Fstrerror(fd)); + return(NULL); + } +#else + if ((fd = fdOpen(buffer, O_RDONLY, 0)) < 0) { + fprintf(stderr, "open of %s failed: %s\n", buffer, + strerror(errno)); + return(NULL); + } +#endif + + /* read the RPM signature */ + if (readLead(fd, &lead)) { + fprintf(stderr, "readLead failed\n"); + fdClose(fd); + return(NULL); + } + switch (lead.major) { + case 1: + fprintf(stderr, "no signature available (v1.0 RPM) in %s\n", nameRpm); + break; + default: + if (rpmReadSignature(fd, &s, lead.signature_type)) { + fprintf(stderr, "rpmReadSignature failed\n"); + fdClose(fd); + return(NULL); + } + if (!s) { + fprintf(stderr, "no signature available in %s\n", nameRpm); + fdClose(fd); + return(NULL); + } +#if defined(WITH_GPG) + /* open temp file for writing */ + sigtarget = debugMalloc(30); + strcpy(sigtarget, "/tmp/rpm2html.date.XXXXXX"); + sigtarget = mktemp(sigtarget); + ofd = Fopen(sigtarget, "w.ufdio"); + if (ofd == NULL || Ferror(ofd)) { + fprintf(stderr, "Fopen of %s failed: %s\n", sigtarget, + Fstrerror(ofd)); + debugFree(sigtarget); + sigtarget = NULL; + } + + /* write the header and archive to a temp file */ + while ((count = Fread(stbuffer, sizeof(stbuffer[0]), sizeof(stbuffer), fd)) > 0) { + if (Fwrite(stbuffer, sizeof(stbuffer[0]), count, ofd) < 0) { + fprintf(stderr, "%s: Fwrite failed: %s\n", sigtarget, + Fstrerror(ofd)); + debugFree(sigtarget); + sigtarget = NULL; + } + } + if (count < 0) { + fprintf(stderr, "%s: Fread failed: %s\n", buffer, Fstrerror(fd)); + debugFree(sigtarget); + sigtarget = NULL; + } + + Fclose(ofd); +#endif + break; + } + + /* close the descriptor */ #if defined(USE_RPMIO) Fclose(fd); #else fdClose(fd); #endif +#if defined(WITH_GPG) + cur = rpmAnalyze(buffer, nameRpm, sigtarget, h, s, dir, tree, buf.st_mtime, isSource); +#else + cur = rpmAnalyze(buffer, nameRpm, NULL, h, s, dir, tree, buf.st_mtime, isSource); +#endif + + /* free the header */ + headerFree(h); + headerFree(s); + + if (sigtarget) { + unlink(sigtarget); + debugFree(sigtarget); + } + return(cur); } @@ -995,7 +1271,7 @@ { rpmdbMatchIterator mi; mi = rpmdbInitIterator(db, RPMDBI_PACKAGES, NULL, 0); while ((h = rpmdbNextIterator(mi)) != NULL) { - cur = rpmAnalyze(NULL, NULL, h, dir, NULL, 0, 0); + cur = rpmAnalyze(NULL, NULL, NULL, h, NULL, dir, NULL, 0, 0); if (cur != NULL) ret = rpmAddList(ret, cur); } rpmdbFreeIterator(mi);