+ When using ssh keys, use the first key as the default userid, unless

specified.

+ The internal variable "sshetcdir" has been renamed to "sshkeydir"

+ When matching the text fields in the username, use an ICASE, NOSUB, EXTENDED
regular expression. This allows more advanced ways of searching, such as:

% netpgpkeys --list-keys '\.de\>'

to find all the keys in the default keyring which have an email address
in Germany. This is actually surprisingly useful.
This commit is contained in:
agc 2009-12-07 16:17:17 +00:00
parent 0ff1ef75c2
commit 183e04eb84
5 changed files with 177 additions and 126 deletions

View File

@ -57,13 +57,14 @@
#if defined(__NetBSD__)
__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
__RCSID("$NetBSD: keyring.c,v 1.23 2009/12/05 07:08:18 agc Exp $");
__RCSID("$NetBSD: keyring.c,v 1.24 2009/12/07 16:17:17 agc Exp $");
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#include <regex.h>
#include <stdlib.h>
#include <string.h>
@ -764,11 +765,9 @@ __ops_keyring_free(__ops_keyring_t *keyring)
*/
const __ops_key_t *
__ops_getkeybyid(__ops_io_t *io, const __ops_keyring_t *keyring,
const unsigned char keyid[OPS_KEY_ID_SIZE])
const unsigned char *keyid, unsigned *from)
{
unsigned n;
for (n = 0; keyring && n < keyring->keyc; n++) {
for ( ; keyring && *from < keyring->keyc; *from += 1) {
if (__ops_get_debug_level(__FILE__)) {
int i;
@ -776,7 +775,7 @@ __ops_getkeybyid(__ops_io_t *io, const __ops_keyring_t *keyring,
"__ops_getkeybyid: keyring keyid ");
for (i = 0 ; i < OPS_KEY_ID_SIZE ; i++) {
(void) fprintf(io->errs, "%02x",
keyring->keys[n].key_id[i]);
keyring->keys[*from].key_id[i]);
}
(void) fprintf(io->errs, ", keyid ");
for (i = 0 ; i < OPS_KEY_ID_SIZE ; i++) {
@ -784,13 +783,13 @@ __ops_getkeybyid(__ops_io_t *io, const __ops_keyring_t *keyring,
}
(void) fprintf(io->errs, "\n");
}
if (memcmp(keyring->keys[n].key_id, keyid,
if (memcmp(keyring->keys[*from].key_id, keyid,
OPS_KEY_ID_SIZE) == 0) {
return &keyring->keys[n];
return &keyring->keys[*from];
}
if (memcmp(&keyring->keys[n].key_id[OPS_KEY_ID_SIZE / 2],
if (memcmp(&keyring->keys[*from].key_id[OPS_KEY_ID_SIZE / 2],
keyid, OPS_KEY_ID_SIZE / 2) == 0) {
return &keyring->keys[n];
return &keyring->keys[*from];
}
}
return NULL;
@ -831,6 +830,70 @@ str2keyid(const char *userid, unsigned char *keyid, size_t len)
keyid[j] = 0x0;
}
/* return the next key which matches, starting searching at *from */
static const __ops_key_t *
getkeybyname(__ops_io_t *io,
const __ops_keyring_t *keyring,
const char *name,
unsigned *from)
{
const __ops_key_t *kp;
__ops_key_t *keyp;
__ops_userid_t *uidp;
unsigned char keyid[OPS_KEY_ID_SIZE + 1];
unsigned int i = 0;
unsigned savedstart;
regex_t r;
size_t len;
if (!keyring) {
return NULL;
}
len = strlen(name);
if (__ops_get_debug_level(__FILE__)) {
(void) fprintf(io->outs, "[%u] name '%s', len %u\n",
*from, name, len);
}
/* first try name as a keyid */
(void) memset(keyid, 0x0, sizeof(keyid));
str2keyid(name, keyid, sizeof(keyid));
if (__ops_get_debug_level(__FILE__)) {
(void) fprintf(io->outs,
"name \"%s\", keyid %02x%02x%02x%02x\n",
name,
keyid[0], keyid[1], keyid[2], keyid[3]);
}
savedstart = *from;
if ((kp = __ops_getkeybyid(io, keyring, keyid, from)) != NULL) {
return kp;
}
*from = savedstart;
if (__ops_get_debug_level(__FILE__)) {
(void) fprintf(io->outs, "regex match '%s' from %u\n",
name, *from);
}
/* match on full name or email address as a NOSUB, ICASE regexp */
(void) regcomp(&r, name, REG_EXTENDED | REG_ICASE);
for (keyp = &keyring->keys[*from]; *from < keyring->keyc; *from += 1, keyp++) {
uidp = keyp->uids;
for (i = 0 ; i < keyp->uidc; i++, uidp++) {
if (__ops_get_debug_level(__FILE__)) {
(void) fprintf(io->outs,
"keyid \"%s\" len %"
PRIsize "u, keyid[len] '%c'\n",
(char *) uidp->userid,
len, uidp->userid[len]);
}
if (regexec(&r, (char *)uidp->userid, 0, NULL, 0) == 0) {
regfree(&r);
return keyp;
}
}
}
regfree(&r);
return NULL;
}
/**
\ingroup HighLevel_KeyringFind
@ -850,95 +913,19 @@ __ops_getkeybyname(__ops_io_t *io,
const __ops_keyring_t *keyring,
const char *name)
{
const __ops_key_t *kp;
__ops_key_t *keyp;
__ops_userid_t *uidp;
unsigned char keyid[OPS_KEY_ID_SIZE + 1];
unsigned int i = 0;
size_t len;
char *cp;
unsigned n;
unsigned from;
if (!keyring) {
return NULL;
}
len = strlen(name);
n = 0;
for (keyp = &keyring->keys[n]; n < keyring->keyc; ++n, keyp++) {
for (i = 0, uidp = keyp->uids; i < keyp->uidc; i++, uidp++) {
if (__ops_get_debug_level(__FILE__)) {
(void) fprintf(io->outs,
"[%u][%u] name %s, last '%d'\n",
n, i, uidp->userid,
uidp->userid[len]);
}
if (strncmp((char *) uidp->userid, name, len) == 0 &&
uidp->userid[len] == ' ') {
return keyp;
}
}
}
from = 0;
return getkeybyname(io, keyring, name, &from);
}
if (strchr(name, '@') == NULL) {
/* no '@' sign */
/* first try name as a keyid */
(void) memset(keyid, 0x0, sizeof(keyid));
str2keyid(name, keyid, sizeof(keyid));
if (__ops_get_debug_level(__FILE__)) {
(void) fprintf(io->outs,
"name \"%s\", keyid %02x%02x%02x%02x\n",
name,
keyid[0], keyid[1], keyid[2], keyid[3]);
}
if ((kp = __ops_getkeybyid(io, keyring, keyid)) != NULL) {
return kp;
}
/* match on full name */
keyp = keyring->keys;
for (n = 0; n < keyring->keyc; ++n, keyp++) {
uidp = keyp->uids;
for (i = 0 ; i < keyp->uidc; i++, uidp++) {
if (__ops_get_debug_level(__FILE__)) {
(void) fprintf(io->outs,
"keyid \"%s\" len %"
PRIsize "u, keyid[len] '%c'\n",
(char *) uidp->userid,
len, uidp->userid[len]);
}
if (strncasecmp((char *) uidp->userid, name,
len) == 0 && uidp->userid[len] == ' ') {
return keyp;
}
}
}
}
/* match on <email@address> */
keyp = keyring->keys;
for (n = 0; n < keyring->keyc; ++n, keyp++) {
for (i = 0, uidp = keyp->uids; i < keyp->uidc; i++, uidp++) {
/*
* look for the rightmost '<', in case there is one
* in the comment field
*/
cp = strrchr((char *) uidp->userid, '<');
if (cp != NULL) {
if (__ops_get_debug_level(__FILE__)) {
(void) fprintf(io->errs,
"cp ,%s, name ,%s, len %"
PRIsize "u ,%c,\n",
cp + 1,
name,
len,
*(cp + len + 1));
}
if (strncasecmp(cp + 1, name, len) == 0 &&
*(cp + len + 1) == '>') {
return keyp;
}
}
}
}
return NULL;
const __ops_key_t *
__ops_getnextkeybyname(__ops_io_t *io,
const __ops_keyring_t *keyring,
const char *name,
unsigned *n)
{
return getkeybyname(io, keyring, name, n);
}
/**

View File

@ -72,10 +72,15 @@ typedef struct __ops_keyring_t {
const __ops_key_t *__ops_getkeybyid(__ops_io_t *,
const __ops_keyring_t *,
const unsigned char *);
const unsigned char *,
unsigned *);
const __ops_key_t *__ops_getkeybyname(__ops_io_t *,
const __ops_keyring_t *,
const char *);
const __ops_key_t *__ops_getnextkeybyname(__ops_io_t *,
const __ops_keyring_t *,
const char *,
unsigned *);
void __ops_keydata_free(__ops_key_t *);
void __ops_keyring_free(__ops_keyring_t *);
void __ops_dump_keyring(const __ops_keyring_t *);

View File

@ -34,7 +34,7 @@
#if defined(__NetBSD__)
__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
__RCSID("$NetBSD: netpgp.c,v 1.31 2009/12/05 07:08:19 agc Exp $");
__RCSID("$NetBSD: netpgp.c,v 1.32 2009/12/07 16:17:17 agc Exp $");
#endif
#include <sys/types.h>
@ -138,6 +138,7 @@ resultp(__ops_io_t *io,
__ops_keyring_t *ring)
{
const __ops_key_t *pubkey;
unsigned from;
unsigned i;
char id[MAX_ID_LENGTH + 1];
@ -148,8 +149,10 @@ resultp(__ops_io_t *io,
ctime(&res->valid_sigs[i].birthtime),
__ops_show_pka(res->valid_sigs[i].key_alg),
userid_to_id(res->valid_sigs[i].signer_id, id));
from = 0;
pubkey = __ops_getkeybyid(io, ring,
(const unsigned char *) res->valid_sigs[i].signer_id);
(const unsigned char *) res->valid_sigs[i].signer_id,
&from);
__ops_print_keydata(io, pubkey, "pub", &pubkey->key.pubkey);
}
}
@ -230,7 +233,7 @@ readkeyring(netpgp_t *netpgp, const char *name)
return keyring;
}
/* read keys from ssh host key files */
/* read keys from ssh key files */
static int
readsshkeys(netpgp_t *netpgp, const char *pubname, const char *secname)
{
@ -241,7 +244,7 @@ readsshkeys(netpgp_t *netpgp, const char *pubname, const char *secname)
char *etcdir;
__OPS_USED(secname);
etcdir = netpgp_getvar(netpgp, "sshetcdir");
etcdir = netpgp_getvar(netpgp, "sshkeydir");
if ((filename = netpgp_getvar(netpgp, pubname)) == NULL) {
(void) snprintf(f, sizeof(f), "%s/ssh_host_rsa_key.pub", etcdir);
filename = f;
@ -336,23 +339,23 @@ netpgp_init(netpgp_t *netpgp)
(void) fprintf(io->errs, "netpgp: bad homedir\n");
return 0;
}
if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) {
(void) memset(id, 0x0, sizeof(id));
(void) conffile(netpgp, homedir, id, sizeof(id));
if (id[0] != 0x0) {
netpgp_setvar(netpgp, "userid", userid = id);
}
}
if (userid == NULL) {
if (netpgp_getvar(netpgp, "need userid") != NULL) {
(void) fprintf(io->errs, "Cannot find user id\n");
return 0;
}
} else {
(void) netpgp_setvar(netpgp, "userid", userid);
}
/* read from either gpg files or ssh host keys */
/* read from either gpg files or ssh keys */
if (netpgp_getvar(netpgp, "ssh keys") == NULL) {
if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) {
(void) memset(id, 0x0, sizeof(id));
(void) conffile(netpgp, homedir, id, sizeof(id));
if (id[0] != 0x0) {
netpgp_setvar(netpgp, "userid", userid = id);
}
}
if (userid == NULL) {
if (netpgp_getvar(netpgp, "need userid") != NULL) {
(void) fprintf(io->errs, "Cannot find user id\n");
return 0;
}
} else {
(void) netpgp_setvar(netpgp, "userid", userid);
}
if ((netpgp->pubring = readkeyring(netpgp, "pubring")) == NULL) {
(void) fprintf(io->errs, "Can't read pub keyring\n");
return 0;
@ -363,9 +366,33 @@ netpgp_init(netpgp_t *netpgp)
}
} else {
if (!readsshkeys(netpgp, "ssh pub key", "ssh sec file")) {
(void) fprintf(io->errs, "Can't read ssh host pub key\n");
(void) fprintf(io->errs, "Can't read ssh pub key\n");
return 0;
}
if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) {
/* set ssh uid to first one in ring */
__ops_keyring_t *pubring;
unsigned char *src;
int i;
int n;
pubring = netpgp->pubring;
(void) memset(id, 0x0, sizeof(id));
src = pubring->keys[0].key_id;
for (i = 0, n = 0 ; i < OPS_KEY_ID_SIZE ; i += 2) {
n += snprintf(&id[n], sizeof(id) - n, "%02x%02x", src[i], src[i + 1]);
}
id[n] = 0x0;
netpgp_setvar(netpgp, "userid", userid = id);
}
if (userid == NULL) {
if (netpgp_getvar(netpgp, "need userid") != NULL) {
(void) fprintf(io->errs, "Cannot find user id\n");
return 0;
}
} else {
(void) netpgp_setvar(netpgp, "userid", userid);
}
}
if ((passfd = netpgp_getvar(netpgp, "pass-fd")) != NULL &&
(netpgp->passfp = fdopen(atoi(passfd), "r")) == NULL) {
@ -413,6 +440,29 @@ netpgp_list_keys(netpgp_t *netpgp)
return __ops_keyring_list(netpgp->io, netpgp->pubring);
}
/* find and list some keys in a keyring */
int
netpgp_match_list_keys(netpgp_t *netpgp, char *name)
{
const __ops_key_t *key;
unsigned found;
unsigned k;
char *data;
found = k = 0;
do {
if ((key = __ops_getnextkeybyname(netpgp->io, netpgp->pubring, name, &k)) != NULL) {
__ops_sprint_keydata(key, &data, "pub", &key->key.pubkey);
printf("%s\n", data);
free(data);
found += 1;
k += 1;
}
} while (key != NULL);
printf("Found %u key%s\n", found, (found == 1) ? "" : "s");
return (found > 0);
}
/* find a key in a keyring */
int
netpgp_find_key(netpgp_t *netpgp, char *id)

View File

@ -54,7 +54,7 @@
#if defined(__NetBSD__)
__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
__RCSID("$NetBSD: reader.c,v 1.26 2009/12/05 07:08:19 agc Exp $");
__RCSID("$NetBSD: reader.c,v 1.27 2009/12/07 16:17:17 agc Exp $");
#endif
#include <sys/types.h>
@ -2162,6 +2162,7 @@ __ops_cb_ret_t
pk_sesskey_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
{
const __ops_contents_t *content = &pkt->u;
unsigned from;
__ops_io_t *io;
io = cbinfo->io;
@ -2179,9 +2180,10 @@ pk_sesskey_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
"pk_sesskey_cb: bad keyring\n");
return (__ops_cb_ret_t)0;
}
from = 0;
cbinfo->cryptinfo.keydata =
__ops_getkeybyid(io, cbinfo->cryptinfo.keyring,
content->pk_sesskey.key_id);
content->pk_sesskey.key_id, &from);
if (!cbinfo->cryptinfo.keydata) {
break;
}
@ -2214,6 +2216,7 @@ get_seckey_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
const __ops_contents_t *content = &pkt->u;
const __ops_seckey_t *secret;
const __ops_key_t *keypair;
unsigned from;
__ops_io_t *io;
io = cbinfo->io;
@ -2222,9 +2225,11 @@ get_seckey_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
}
switch (pkt->tag) {
case OPS_GET_SECKEY:
from = 0;
cbinfo->cryptinfo.keydata =
__ops_getkeybyid(io, cbinfo->cryptinfo.keyring,
content->get_seckey.pk_sesskey->key_id);
content->get_seckey.pk_sesskey->key_id,
&from);
if (!cbinfo->cryptinfo.keydata ||
!__ops_is_key_secret(cbinfo->cryptinfo.keydata)) {
return (__ops_cb_ret_t)0;

View File

@ -54,7 +54,7 @@
#if defined(__NetBSD__)
__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
__RCSID("$NetBSD: validate.c,v 1.23 2009/11/20 07:17:07 agc Exp $");
__RCSID("$NetBSD: validate.c,v 1.24 2009/12/07 16:17:17 agc Exp $");
#endif
#include <sys/types.h>
@ -228,6 +228,7 @@ __ops_validate_key_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
validate_key_cb_t *key;
__ops_error_t **errors;
__ops_io_t *io;
unsigned from;
unsigned valid = 0;
io = cbinfo->io;
@ -284,9 +285,10 @@ __ops_validate_key_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
case OPS_PTAG_CT_SIGNATURE: /* V3 sigs */
case OPS_PTAG_CT_SIGNATURE_FOOTER: /* V4 sigs */
from = 0;
signer = __ops_getkeybyid(io, key->keyring,
content->sig.info.signer_id);
content->sig.info.signer_id,
&from);
if (!signer) {
if (!add_sig_to_list(&content->sig.info,
&key->result->unknown_sigs,
@ -401,6 +403,7 @@ validate_data_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
validate_data_cb_t *data;
__ops_error_t **errors;
__ops_io_t *io;
unsigned from;
unsigned valid = 0;
io = cbinfo->io;
@ -453,8 +456,9 @@ validate_data_cb(const __ops_packet_t *pkt, __ops_cbdata_t *cbinfo)
sizeof(content->sig.info.signer_id), "");
(void) fprintf(io->outs, "\n");
}
from = 0;
signer = __ops_getkeybyid(io, data->keyring,
content->sig.info.signer_id);
content->sig.info.signer_id, &from);
if (!signer) {
OPS_ERROR(errors, OPS_E_V_UNKNOWN_SIGNER,
"Unknown Signer");