tCrawl $KEYRING if no key is provided - sick - sign and check files using ed25519
(HTM) git clone git://z3bra.org/sick
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
(DIR) commit a213aaa860eb78fb708172bbe802cd4a8fff5d07
(DIR) parent ba646b3bb0828dce3e6ae91020556a740489cfcd
(HTM) Author: z3bra <willyatmailoodotorg>
Date: Mon, 16 May 2016 13:32:05 +0200
Crawl $KEYRING if no key is provided
When checking a stream, if the -f flag is not passed, sick(1) will crawl
tthe directory pointed to by the $KEYRING environment variable and check
all files within this directory against the signature, until all files
have been tested, or one of these public keys match the signature.
Diffstat:
M README | 12 ++++++++++++
M sick.1 | 10 +++++++---
M sick.c | 93 ++++++++++++++++++++++++++-----
3 files changed, 97 insertions(+), 18 deletions(-)
---
(DIR) diff --git a/README b/README
t@@ -29,6 +29,8 @@ The whole stream will be dumped to stdout, and the signature will be appended.
Checking streams
----------------
+### Using a file
+
A signed stream can be verified against a public key with the following
command:
t@@ -36,3 +38,13 @@ command:
If the signature can be verified against the public key provided, the content
of the message will be dumped to stdout.
+
+### Using a keyring
+
+In case the `-f` flag is omited, sick(1) will check the signature against all
+the files located in the $KEYRING directory.
+
+ $ export KEYRING="$HOME/.keyring"
+ $ mkdir $KEYRING
+ $ mv alice.pub $KEYRING/
+ $ sick < SIGNED
(DIR) diff --git a/sick.1 b/sick.1
t@@ -15,9 +15,8 @@ generates key pairs, signs, checks and remove signatures for a file or stream.
.Sh OPTIONS
.Bl -tag -width "-g ALIAS"
The default action is to check the signature appended to the message given on
-stdin. A public key must be provided with the
-.Fl f
-flag. If the signature can be verified with the public key, the message will be written to stdout without the signature.
+stdin. If the signature can be verified, the message will be written to stdout
+without the signature.
.It Fl g Ar ALIAS
Generates an ed25519 key pairs: `ALIAS.key` and `ALIAS.pub`
.It Fl f Ar KEY
t@@ -42,6 +41,11 @@ two lines, as follows:
-----END ED25519 SIGNATURE-----
.Ed
.El
+.Sh ENVIRONMENT
+.Bl -tag -width "KEYRING"
+.It Ev KEYRING
+Location of the keyring directory
+.El
.Sh EXAMPLES
.Bd -literal
Generating a key pair:
(DIR) diff --git a/sick.c b/sick.c
t@@ -1,8 +1,10 @@
/* See LICENSE file for copyright and license details. */
+#include <dirent.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
#include "arg.h"
#include "base64.h"
t@@ -18,9 +20,10 @@ enum {
};
enum {
- ERR_NOKEY = 1,
- ERR_NOSIG = 2,
- ERR_NOMSG = 3
+ ERR_NOKEY = 1,
+ ERR_NOSIG = 2,
+ ERR_NOMSG = 3,
+ ERR_NORING = 4
};
static void usage();
t@@ -28,6 +31,7 @@ static size_t bufferize(char **buf, FILE *fp);
static size_t extractmsg(unsigned char *msg[], char *buf);
static size_t extractsig(unsigned char *sig[], char *buf);
static int createkeypair(const char *);
+static int check_keyring(unsigned char *sig, unsigned char *msg, size_t len);
static int sign(FILE *fp, FILE *key);
static int check(FILE *fp, FILE *key);
t@@ -184,6 +188,9 @@ sign(FILE *fp, FILE *key)
char *base64, *buf = NULL;
unsigned char sig[64], priv[64], *msg = NULL;
+ if (key == NULL)
+ return ERR_NOKEY;
+
if (!fread(priv, 1, 64, key))
return ERR_NOKEY;
t@@ -219,6 +226,60 @@ sign(FILE *fp, FILE *key)
}
static int
+check_keyring(unsigned char *sig, unsigned char *msg, size_t len)
+{
+ int ret = 0;
+ size_t n = 0;
+ DIR *dirp = NULL;
+ FILE *key = NULL;
+ struct dirent *dt = NULL;
+ char *keyring = NULL, path[PATH_MAX];
+ unsigned char pub[32];
+
+ keyring = getenv("KEYRING");
+ if (keyring == NULL) {
+ if (verbose)
+ fprintf(stderr, "KEYRING not set\n");
+ return ERR_NORING;
+ }
+
+ dirp = opendir(keyring);
+ if (dirp == NULL) {
+ perror(keyring);
+ return ERR_NORING;
+ }
+
+ while ((dt = readdir(dirp)) != NULL) {
+ if (dt->d_type != DT_REG)
+ continue;
+
+ n = strnlen(keyring, PATH_MAX);
+ memset(path, 0, PATH_MAX);
+ memcpy(path, keyring, n);
+ path[n] = '/';
+ memcpy(path+n+1, dt->d_name, dt->d_reclen);
+ if ((key = fopen(path, "r")) == NULL) {
+ perror(path);
+ continue;
+ }
+ if (fread(pub, 1, 32, key) < 32) {
+ perror(path);
+ fclose(key);
+ continue;
+ }
+ ret += ed25519_verify(sig, msg, len, pub);
+ if (ret) {
+ if (verbose)
+ fprintf(stderr, "Key match: %s\n", path);
+ break;
+ }
+ }
+
+ closedir(dirp);
+ return !ret;
+}
+
+static int
check(FILE *fp, FILE *key)
{
int ret = 0;
t@@ -226,10 +287,6 @@ check(FILE *fp, FILE *key)
char *buf = NULL;
unsigned char *sig, *msg, pub[32];
- if (fread(pub, 1, 32, key) < 32) {
- return ERR_NOKEY;
- }
-
if ((len = bufferize(&buf, fp)) == 0)
return ERR_NOMSG;
t@@ -252,19 +309,27 @@ check(FILE *fp, FILE *key)
if (verbose)
fprintf(stderr, "Verifying stream (%lu bytes)\n", len);
- ret = ed25519_verify(sig, msg, len, pub);
- if (ret)
+ if (key) {
+ if (fread(pub, 1, 32, key) < 32)
+ return ERR_NOKEY;
+
+ ret = !ed25519_verify(sig, msg, len, pub);
+ } else {
+ ret = check_keyring(sig, msg, len);
+ }
+
+ if (ret == 0)
fwrite(msg, 1, len, stdout);
if (verbose)
- fprintf(stderr, "Stream check %s\n", ret ? "OK" : "FAILED");
+ fprintf(stderr, "Stream check %s\n", ret ? "FAILED" : "OK");
free(msg);
free(buf);
free(sig);
- return !ret;
+ return ret;
}
int
t@@ -290,9 +355,6 @@ main(int argc, char *argv[])
usage();
}ARGEND;
- if (key == NULL)
- return ERR_NOKEY;
-
fp = argc ? fopen(*argv, "r") : stdin;
switch (action) {
t@@ -305,7 +367,8 @@ main(int argc, char *argv[])
}
fclose(fp);
- fclose(key);
+ if (key)
+ fclose(key);
return ret;
}