src/lib/libkeynote/keynote-verify.c

420 lines
8.1 KiB
C

/* $OpenBSD: keynote-verify.c,v 1.20 2021/10/24 21:24:20 deraadt Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@dsl.cis.upenn.edu)
*
* This code was written by Angelos D. Keromytis in Philadelphia, PA, USA,
* in April-May 1998
*
* Copyright (C) 1998, 1999 by Angelos D. Keromytis.
*
* Permission to use, copy, and modify this software with or without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, THE AUTHORS MAKES NO
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <fcntl.h>
#include <getopt.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "header.h"
#include "keynote.h"
int sessid;
void verifyusage(void);
void
verifyusage(void)
{
fprintf(stderr, "Arguments:\n");
fprintf(stderr, "\t-h: This message\n");
fprintf(stderr,
"\t-r <valuelist>: Comma separated, ordered return-value list\n");
fprintf(stderr, "\t-e <filename>: Environment settings\n");
fprintf(stderr, "\t-l <filename>: Trusted (local) assertion\n");
fprintf(stderr, "\t-k <filename>: File containing key\n");
fprintf(stderr, "Followed by a list of:\n");
fprintf(stderr, "\t<filename>: Non-local assertion\n");
}
void
keynote_verify(int argc, char *argv[])
{
int fd, i, ch, se = 0, cl = 8192, sk = 0, sl = 0, p, ac = argc;
char *buf, **av = argv, **retv, **foov, *ptr;
int numretv = 16, numret = 0, sn;
struct stat sb;
if (argc == 1)
{
verifyusage();
exit(1);
}
if ((buf = calloc(cl, sizeof(char))) == NULL)
{
perror("calloc()");
exit(1);
}
if ((retv = calloc(numretv, sizeof(char *))) == NULL)
{
perror("calloc()");
exit(1);
}
/* "ac" and "av" are used for stress-testing, ignore otherwise */
argv = av;
argc = ac;
sn = 0;
opterr = 0;
sessid = kn_init();
if (sessid == -1)
{
fprintf(stderr, "kn_init() failed (errno %d).\n", keynote_errno);
exit(keynote_errno);
}
while ((ch = getopt(argc, argv, "hqistl:e:k:r:")) != -1)
{
switch (ch)
{
case 'e':
if (read_environment(optarg) == -1)
exit(1);
se = 1;
break;
case 'k':
sk = 1;
if ((fd = open(optarg, O_RDONLY)) == -1)
{
perror(optarg);
exit(1);
}
if (fstat(fd, &sb) == -1)
{
perror("fstat()");
exit(1);
}
if (sb.st_size > cl - 1)
{
free(buf);
cl = sb.st_size + 1;
buf = calloc(cl, sizeof(char));
if (buf == NULL)
{
perror("calloc()");
exit(1);
}
}
i = read(fd, buf, sb.st_size);
if (i == -1)
{
perror("read()");
exit(1);
}
close(fd);
parse_key(buf);
switch (keynote_errno)
{
case 0: /* No errors */
break;
case ERROR_SYNTAX:
fprintf(stderr, "Syntax error adding authorizer "
"%s\n", optarg);
exit(1);
case ERROR_MEMORY:
perror("Out of memory.\n");
exit(1);
default:
fprintf(stderr, "Unknown error (%d).\n",
keynote_errno);
}
break;
case 'h':
verifyusage();
exit(0);
case 'r':
if (sn != 0)
{
fprintf(stderr,
"Do not define two sets of return values.\n");
exit(1);
}
sn = 1;
for (numret = 0;
(ptr = strchr(optarg, ',')) != NULL;
numret++)
{
/* Running out of memory */
if (numret > numretv - 3)
{
numretv *= 2;
foov = calloc(numretv, sizeof(char **));
if (foov == NULL)
{
/*
* If this were a real program, we 'd be freeing
* retv here. Since we're exiting, we can be a
* little sloppy.
*/
perror("calloc()");
exit(1);
}
memcpy(foov, retv, numretv * sizeof(char **));
free(retv);
retv = foov;
}
retv[numret] = calloc((ptr - optarg) + 1,
sizeof(char));
if (retv[numret] == NULL)
{
/* Comment from above applies here as well */
perror("calloc()");
exit(1);
}
/* Copy */
memcpy(retv[numret], optarg, ptr - optarg);
optarg = ptr + 1;
}
/* Last component */
retv[numret] = strdup(optarg);
if (retv[numret] == NULL)
{
perror("calloc()");
exit(1);
}
numret++;
break;
case 'l':
if ((fd = open(optarg, O_RDONLY)) == -1)
{
perror(optarg);
exit(1);
}
if (fstat(fd, &sb) == -1)
{
perror("fstat()");
exit(1);
}
if (sb.st_size > cl - 1)
{
free(buf);
cl = sb.st_size + 1;
buf = calloc(cl, sizeof(char));
if (buf == NULL)
{
perror("calloc()");
exit(1);
}
}
i = read(fd, buf, sb.st_size);
if (i == -1)
{
perror("read()");
exit(1);
}
close(fd);
p = kn_add_assertion(sessid, buf, i, ASSERT_FLAG_LOCAL);
if (p == -1)
{
fprintf(stderr,
"Error for assertion in file <%s>, errno %d.\n",
optarg, keynote_errno);
keynote_errno = 0;
}
memset(buf, 0, sb.st_size);
sl = 1;
break;
case '?':
default:
verifyusage();
exit(1);
}
}
argc -= optind;
argv += optind;
optind = 1;
if (sn == 0)
{
fprintf(stderr,
"Should set return values before evaluations begin.\n");
exit(1);
}
if (se == 0)
{
fprintf(stderr, "Should set environment before evaluations begin.\n");
exit(1);
}
if (sk == 0)
{
fprintf(stderr, "Should specify at least one action authorizer.\n");
exit(1);
}
if (sl == 0)
{
fprintf(stderr,
"Should specify at least one trusted assertion (POLICY).\n");
exit(1);
}
while (argc--)
{
if ((fd = open(argv[argc], O_RDONLY)) == -1)
{
perror(argv[argc]);
exit(1);
}
if (fstat(fd, &sb) == -1)
{
perror("fstat()");
exit(1);
}
if (sb.st_size > cl - 1)
{
free(buf);
cl = sb.st_size + 1;
buf = calloc(cl, sizeof(char));
if (buf == NULL)
{
perror("calloc()");
exit(1);
}
}
i = read(fd, buf, sb.st_size);
if (i == -1)
{
perror("read()");
exit(1);
}
close(fd);
p = kn_add_assertion(sessid, buf, i, 0);
if (p == -1)
{
fprintf(stderr, "Error for assertion in file <%s>, errno %d.\n",
argv[argc], keynote_errno);
keynote_errno = 0;
}
memset(buf, 0, sb.st_size);
}
p = kn_do_query(sessid, retv, numret); /* Evaluation time */
printf("Query result = ");
switch (keynote_errno)
{
case ERROR_MEMORY:
printf("<out of memory>\n");
exit(1);
case ERROR_SYNTAX:
printf("<uninitialized authorizers or all POLICY "
"assertions are malformed!>\n");
exit(1);
case ERROR_NOTFOUND:
printf("<session or other information not found!>\n");
exit(1);
case 0: /* No errors */
break;
default:
printf("<should never happen (%d)!>\n", keynote_errno);
exit(1);
}
printf("%s\n", retv[p]);
keynote_errno = 0;
while ((i = kn_get_failed(sessid, KEYNOTE_ERROR_MEMORY, 0)) != -1)
{
printf("Failed assertion %d due to memory error.\n", i);
kn_remove_assertion(sessid, i);
}
while ((i = kn_get_failed(sessid, KEYNOTE_ERROR_SYNTAX, 0)) != -1)
{
printf("Failed assertion %d due to syntax or semantic error.\n", i);
kn_remove_assertion(sessid, i);
}
while ((i = kn_get_failed(sessid, KEYNOTE_ERROR_SIGNATURE, 0)) != -1)
{
printf("Failed assertion %d due to signature verification failure.\n",
i);
kn_remove_assertion(sessid, i);
}
while ((i = kn_get_failed(sessid, KEYNOTE_ERROR_ANY, 0)) != -1)
{
printf("Failed assertion %d due to unspecified error.\n", i);
kn_remove_assertion(sessid, i);
}
kn_close(sessid);
/* This is a reminder that return values are not free'ed by KeyNote */
for (sn = 0; sn < numret; sn++)
free(retv[sn]);
free(retv);
retv = NULL;
exit(0);
}