/*
* UTIL/PGPVERIFY.C
*
* pgpverify < control-news-article
*
* Extract X-PGP-Sig header from news article, construct
* PGP text file, and pipe into pgp -f
*
* (c)Copyright 1998, Matthew Dillon, All Rights Reserved. Refer to
* the COPYRIGHT file in the base directory of this distribution
* for specific rights granted.
*/
#include "defs.h"
typedef struct Header {
struct Header *he_Next; /* next header */
char *he_Name; /* name of header & body, incl of newlines */
int he_Flagged;
} Header;
char *FindHeader(const char *name, char *def);
Header *HBase = NULL;
Header **PHe = &HBase;
char *argv[10] = { PGP_PATH, PGP_ARG0, "-f", NULL };
void
Usage(void)
{
printf("Usage: pgpverify [-d] [pgp_path] [pgp_args]\n");
exit(1);
}
int
main(int ac, char **av)
{
char buf[8192];
Header *he = NULL;
int nl = 1;
int r = 2;
char *sig;
char *version = NULL;
char *sheaders = NULL;
char *signature = NULL;
pid_t pid = 0;
int fds[3] = { -1, -1, -1 };
int i;
int argcount = 0;
int argend = 0;
for (i = 1; i < ac; ++i) {
char *ptr = av[i];
if (*ptr != '-' || argend) {
argend = 1;
if (argcount > 8)
break;
argv[argcount++] = ptr;
if (argcount == 0) {
if (strrchr(ptr, '/') == NULL)
argv[argcount++] = ptr;
else
argv[argcount++] = strrchr(ptr, '/') + 1;
}
argv[argcount] = NULL;
continue;
}
ptr += 2;
switch(ptr[-1]) {
case '-':
argend = 1;
break;
case 'd':
if (*ptr)
DebugOpt = strtol(ptr, NULL, 0);
else
DebugOpt = 1;
break;
default:
fprintf(stderr, "illegal option: %s\n", ptr - 2);
Usage();
}
}
/*
* Scan headers in message
*/
while (fgets(buf, sizeof(buf), stdin) != NULL) {
int l;
if ((l = strlen(buf)) == 1) /* blank line, end of headers */
break;
/*
* check for end of previous header
*/
if (he && nl && buf[0] != ' ' && buf[0] != '\t') {
he = NULL;
}
/*
* create new header if necessary
*/
if (he == NULL) { /* new header */
he = malloc(sizeof(Header));
nl = 1;
*PHe = he;
PHe = &he->he_Next;
he->he_Next = NULL;
he->he_Name = malloc(1);
he->he_Name[0] = 0;
}
/*
* append data buffer to header
*/
{
int r = strlen(he->he_Name);
he->he_Name = realloc(he->he_Name, r + l + 1);
strcpy(he->he_Name + r, buf);
}
/*
* handle headers longer then our buffer size
*/
if (buf[l-1] != '\n')
nl = 0;
else
nl = 1;
}
/*
* Extract X-PGP-Sig: header
*/
if ((sig = FindHeader("X-PGP-Sig", NULL)) == NULL)
exit(1);
/*
* Extract version and list of signed headers
*/
version = strtok(sig, " \n");
sheaders = strtok(NULL, " \n");
signature = strtok(NULL, "");
if (version == NULL || sheaders == NULL || signature == NULL)
exit(2);
/*
* Start pgp -f
*/
{
char nhtmp[PATH_MAX];
char *env[2];
env[0] = nhtmp;
env[1] = NULL;
snprintf(nhtmp, sizeof(nhtmp), "HOME=%s", NewsHome);
pid = RunProgramPipe(fds, RPF_STDOUT|RPF_STDERR, argv, env);
if (pid <= 0)
exit(2);
}
/*
* output PGP text
*/
{
FILE *fo = fdopen(fds[1], "w");
char *name;
fprintf(fo, "-----BEGIN PGP SIGNED MESSAGE-----\n");
fprintf(fo, "\n");
fprintf(fo, "X-Signed-Headers: %s\n", sheaders);
/*
* extract requested headers
*/
for (name = strtok(sheaders, ","); name; name = strtok(NULL, ",")) {
fprintf(fo, "%s:%s", name, FindHeader(name, "\n"));
}
/*
* blank line, then article body
*/
fprintf(fo, "\n");
while (fgets(buf, sizeof(buf), stdin) != NULL) {
if (buf[0] == '-')
fputs("- ", fo);
fputs(buf, fo);
}
/*
* blank line, then PGP signature
*/
fprintf(fo, "\n");
fprintf(fo, "-----BEGIN PGP SIGNATURE-----\n");
fprintf(fo, "Version: %s\n", version);
fprintf(fo, "\n");
for (name = signature; *name; ++name) {
if (*name == ' ' || *name == '\t')
continue;
fputc(*name, fo);
}
fprintf(fo, "-----END PGP SIGNATURE-----\n");
fclose(fo);
}
/*
* input results
*/
{
FILE *fi = fdopen(fds[2], "r");
while (fgets(buf, sizeof(buf), fi) != NULL) {
char *good;
if (DebugOpt)
printf(">> %s", buf);
if (strstr(buf, "Bad signature")) {
r= 3;
break;
}
if ((good=strstr(buf, "Good signature from"))) {
char *tok;
good = strchr(good + 19, '"');
if (good == NULL)
break;
tok = strtok(good + 1, " \"\n");
if (tok[0]) {
r = 0;
printf("%s\n", tok);
}
break;
}
}
while (fgets(buf, sizeof(buf), fi) != NULL) {
if (DebugOpt)
printf(">> %s", buf);
}
fclose(fi);
}
if (pid > 0)
waitpid(pid, NULL, 0);
exit(r);
}
char *
FindHeader(const char *name, char *def)
{
Header *he;
int l = strlen(name);
for (he = HBase; he; he = he->he_Next) {
if (strncmp(he->he_Name, name, l) == 0 && he->he_Name[l] == ':')
break;
}
if (he)
return(he->he_Name + l + 1);
return(def);
}
syntax highlighted by Code2HTML, v. 0.9.1