Merge branch 'naf5' into development

This commit is contained in:
Jeremy Lakeman 2013-11-13 12:32:55 +10:30
commit 21b123212c
20 changed files with 720 additions and 266 deletions

View File

@ -45,6 +45,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "cli.h"
#include "overlay_address.h"
#include "overlay_buffer.h"
#include "keyring.h"
extern struct cli_schema command_line_options[];
@ -1944,6 +1945,47 @@ int app_keyring_list(const struct cli_parsed *parsed, struct cli_context *contex
return 0;
}
static void cli_output_identity(struct cli_context *context, const keyring_identity *id)
{
int i;
for (i=0;i<id->keypair_count;i++){
keypair *kp=id->keypairs[i];
switch(kp->type){
case KEYTYPE_CRYPTOBOX:
cli_field_name(context, "sid", ":");
cli_put_string(context, alloca_tohex(kp->public_key, kp->public_key_len), "\n");
break;
case KEYTYPE_DID:
{
char *str = (char*)kp->private_key;
int l = strlen(str);
if (l){
cli_field_name(context, "did", ":");
cli_put_string(context, str, "\n");
}
str = (char*)kp->public_key;
l=strlen(str);
if (l){
cli_field_name(context, "name", ":");
cli_put_string(context, str, "\n");
}
}
break;
case KEYTYPE_PUBLIC_TAG:
{
const char *name;
const unsigned char *value;
size_t length;
if (keyring_unpack_tag(kp->public_key, kp->public_key_len, &name, &value, &length)==0){
cli_field_name(context, name, ":");
cli_put_string(context, alloca_toprint_quoted(-1, value, length, NULL), "\n");
}
}
break;
}
}
}
int app_keyring_add(const struct cli_parsed *parsed, struct cli_context *context)
{
if (config.debug.verbose)
@ -1971,16 +2013,7 @@ int app_keyring_add(const struct cli_parsed *parsed, struct cli_context *context
keyring_free(k);
return WHY("Could not write new identity");
}
cli_field_name(context, "sid", ":");
cli_put_string(context, alloca_tohex_sid_t(*sidp), "\n");
if (did) {
cli_field_name(context, "did", ":");
cli_put_string(context, did, "\n");
}
if (name) {
cli_field_name(context, "name", ":");
cli_put_string(context, name, "\n");
}
cli_output_identity(context, id);
keyring_free(k);
return 0;
}
@ -1990,48 +2023,104 @@ int app_keyring_set_did(const struct cli_parsed *parsed, struct cli_context *con
if (config.debug.verbose)
DEBUG_cli_parsed(parsed);
const char *sidhex, *did, *name;
cli_arg(parsed, "sid", &sidhex, str_is_subscriber_id, "");
cli_arg(parsed, "did", &did, cli_optional_did, "");
cli_arg(parsed, "name", &name, NULL, "");
if (strlen(name)>63) return WHY("Name too long (31 char max)");
if (!(keyring = keyring_open_instance_cli(parsed)))
if (cli_arg(parsed, "sid", &sidhex, str_is_subscriber_id, "") == -1 ||
cli_arg(parsed, "did", &did, cli_optional_did, "") == -1 ||
cli_arg(parsed, "name", &name, NULL, "") == -1)
return -1;
if (strlen(name)>63)
return WHY("Name too long (31 char max)");
sid_t sid;
if (str_to_sid_t(&sid, sidhex) == -1){
keyring_free(keyring);
return WHY("str_to_sid_t() failed");
}
int cn=0,in=0,kp=0;
int r=keyring_find_sid(keyring, &cn, &in, &kp, &sid);
if (!r) return WHY("No matching SID");
if (keyring_set_did(keyring->contexts[cn]->identities[in], did, name))
return WHY("Could not set DID");
if (keyring_commit(keyring))
return WHY("Could not write updated keyring record");
if (!(keyring = keyring_open_instance_cli(parsed)))
return -1;
cli_field_name(context, "sid", ":");
cli_put_string(context, alloca_tohex_sid_t(sid), "\n");
if (did) {
cli_field_name(context, "did", ":");
cli_put_string(context, did, "\n");
int cn=0,in=0,kp=0;
int r=0;
if (!keyring_find_sid(keyring, &cn, &in, &kp, &sid))
r=WHY("No matching SID");
else{
if (keyring_set_did(keyring->contexts[cn]->identities[in], did, name))
r=WHY("Could not set DID");
else{
if (keyring_commit(keyring))
r=WHY("Could not write updated keyring record");
else{
cli_output_identity(context, keyring->contexts[cn]->identities[in]);
}
if (name) {
cli_field_name(context, "name", ":");
cli_put_string(context, name, "\n");
}
}
keyring_free(keyring);
return 0;
return r;
}
static int app_keyring_set_tag(const struct cli_parsed *parsed, struct cli_context *context)
{
const char *sidhex, *tag, *value;
if (cli_arg(parsed, "sid", &sidhex, str_is_subscriber_id, "") == -1 ||
cli_arg(parsed, "tag", &tag, NULL, "") == -1 ||
cli_arg(parsed, "value", &value, NULL, "") == -1 )
return -1;
if (!(keyring = keyring_open_instance_cli(parsed)))
return -1;
sid_t sid;
if (str_to_sid_t(&sid, sidhex) == -1)
return WHY("str_to_sid_t() failed");
int cn=0,in=0,kp=0;
int r=0;
if (!keyring_find_sid(keyring, &cn, &in, &kp, &sid))
r=WHY("No matching SID");
else{
int length = strlen(value);
if (keyring_set_public_tag(keyring->contexts[cn]->identities[in], tag, (const unsigned char*)value, length))
r=WHY("Could not set tag value");
else{
if (keyring_commit(keyring))
r=WHY("Could not write updated keyring record");
else{
cli_output_identity(context, keyring->contexts[cn]->identities[in]);
}
}
}
keyring_free(keyring);
return r;
}
ssize_t mdp_poll_recv(int mdp_sock, time_ms_t timeout, struct mdp_header *rev_header, unsigned char *payload, size_t buffer_size)
{
time_ms_t now = gettime_ms();
if (now>timeout)
return -2;
int p=mdp_poll(mdp_sock, timeout - now);
if (p<0)
return WHY_perror("mdp_poll");
if (p==0)
return -2;
ssize_t len = mdp_recv(mdp_sock, rev_header, payload, buffer_size);
if (len<0)
return WHY_perror("mdp_recv");
if (rev_header->flags & MDP_FLAG_ERROR)
return WHY("Operation failed, check the log for more information");
return len;
}
static int handle_pins(const struct cli_parsed *parsed, struct cli_context *context, int revoke)
{
const char *pin, *sid_hex;
cli_arg(parsed, "entry-pin", &pin, NULL, "");
cli_arg(parsed, "sid", &sid_hex, str_is_subscriber_id, "");
if (cli_arg(parsed, "entry-pin", &pin, NULL, "") == -1 ||
cli_arg(parsed, "sid", &sid_hex, str_is_subscriber_id, "") == -1)
return -1;
int ret=1;
struct mdp_header header={
@ -2040,8 +2129,8 @@ static int handle_pins(const struct cli_parsed *parsed, struct cli_context *cont
int mdp_sock = mdp_socket();
set_nonblock(mdp_sock);
unsigned char payload[1200];
struct mdp_identity_request *request = (struct mdp_identity_request *)payload;
unsigned char request_payload[1200];
struct mdp_identity_request *request = (struct mdp_identity_request *)request_payload;
if (revoke){
request->action=ACTION_LOCK;
@ -2053,51 +2142,40 @@ static int handle_pins(const struct cli_parsed *parsed, struct cli_context *cont
if (pin && *pin){
request->type=TYPE_PIN;
int pin_len = strlen(pin)+1;
if (pin_len+len > sizeof(payload))
if (pin_len+len > sizeof(request_payload))
return WHY("Supplied pin is too long");
bcopy(pin, &payload[len], pin_len);
bcopy(pin, &request_payload[len], pin_len);
len+=pin_len;
}else if(sid_hex && *sid_hex){
request->type=TYPE_SID;
sid_t sid;
if (str_to_sid_t(&sid, sid_hex) == -1)
return WHY("str_to_sid_t() failed");
bcopy(sid.binary, &payload[len], sizeof(sid));
bcopy(sid.binary, &request_payload[len], sizeof(sid));
len+=sizeof(sid);
}
if (!mdp_send(mdp_sock, &header, payload, len)){
if (!mdp_send(mdp_sock, &header, request_payload, len)){
WHY_perror("mdp_send");
goto end;
}
time_ms_t timeout=gettime_ms()+500;
while(1){
time_ms_t now = gettime_ms();
if (now>timeout)
struct mdp_header rev_header;
unsigned char response_payload[1600];
ssize_t len = mdp_poll_recv(mdp_sock, timeout, &rev_header, response_payload, sizeof(response_payload));
if (len==-1)
break;
int p=mdp_poll(mdp_sock, timeout - now);
if (p<0){
WHY_perror("mdp_poll");
break;
}
if (p==0){
if (len==-2){
WHYF("Timeout while waiting for response");
break;
}
struct mdp_header rev_header;
unsigned char payload[1600];
ssize_t len = mdp_recv(mdp_sock, &rev_header, payload, sizeof(payload));
if (len<0){
WHY_perror("mdp_recv");
continue;
}
if (rev_header.flags & MDP_FLAG_OK)
if (rev_header.flags & MDP_FLAG_OK){
ret=0;
if (rev_header.flags & MDP_FLAG_ERROR)
WHY("Operation failed, check the log for more information");
break;
}
}
end:
mdp_close(mdp_sock);
return ret;
@ -2113,6 +2191,68 @@ int app_id_pin(const struct cli_parsed *parsed, struct cli_context *context)
return handle_pins(parsed, context, 0);
}
int app_id_list(const struct cli_parsed *parsed, struct cli_context *context)
{
const char *tag, *value;
if (cli_arg(parsed, "tag", &tag, NULL, "") == -1 ||
cli_arg(parsed, "value", &value, NULL, "") == -1 )
return -1;
int ret=-1;
struct mdp_header header={
.remote.port=MDP_SEARCH_IDS,
};
int mdp_sock = mdp_socket();
set_nonblock(mdp_sock);
unsigned char request_payload[1200];
size_t len=0;
if (tag && *tag){
size_t value_len=0;
if (value && *value)
value_len = strlen(value);
len = sizeof(request_payload);
if (keyring_pack_tag(request_payload, &len, tag, (unsigned char*)value, value_len))
goto end;
}
if (!mdp_send(mdp_sock, &header, request_payload, len)){
WHY_perror("mdp_send");
goto end;
}
time_ms_t timeout=gettime_ms()+500;
while(1){
struct mdp_header rev_header;
unsigned char response_payload[1600];
ssize_t len = mdp_poll_recv(mdp_sock, timeout, &rev_header, response_payload, sizeof(response_payload));
DEBUGF("mdp_poll_recv = %zd", len);
if (len==-1)
break;
if (len==-2){
WHYF("Timeout while waiting for response");
break;
}
if (len>=SID_SIZE){
sid_t *id = (sid_t*)response_payload;
cli_field_name(context, "sid", ":");
cli_put_hexvalue(context, id->binary, sizeof(sid_t), "\n");
// TODO receive and decode other details about this identity
}
if (rev_header.flags & MDP_FLAG_OK){
ret=0;
break;
}
}
end:
mdp_close(mdp_sock);
return ret;
}
int app_id_self(const struct cli_parsed *parsed, struct cli_context *context)
{
int mdp_sockfd;
@ -2666,6 +2806,10 @@ struct cli_schema command_line_options[]={
"Create a new identity in the keyring protected by the supplied PIN (empty PIN if not given)"},
{app_keyring_set_did,{"keyring", "set","did" KEYRING_PIN_OPTIONS,"<sid>","<did>","<name>",NULL}, 0,
"Set the DID for the specified SID (must supply PIN to unlock the SID record in the keyring)"},
{app_keyring_set_tag,{"keyring", "set","tag" KEYRING_PIN_OPTIONS,"<sid>","<tag>","<value>",NULL}, 0,
"Set a named tag for the specified SID (must supply PIN to unlock the SID record in the keyring)"},
{app_id_list, {"id", "list", "[<tag>]", "[<value>]", NULL}, 0,
"Search unlocked identities based on an optional tag and value"},
{app_id_self,{"id","self|peers|allpeers",NULL}, 0,
"Return identity(s) as URIs of own node, or of known routable peers, or all known peers"},
{app_id_pin, {"id", "enter", "pin", "<entry-pin>", NULL}, 0,

View File

@ -3,6 +3,7 @@
#include "serval.h"
#include "overlay_address.h"
#include "crypto.h"
#include "keyring.h"
// verify a signature against a public sas key.
int crypto_verify_signature(unsigned char *sas_key,

View File

@ -16,6 +16,7 @@
#include "str.h"
#include "overlay_address.h"
#include "conf.h"
#include "keyring.h"
struct subscriber *directory_service;

View File

@ -5,6 +5,7 @@ HDRS= fifo.h \
overlay_packet.h \
rhizome.h \
serval.h \
keyring.h \
cli.h \
str.h \
rotbuf.h \

234
keyring.c
View File

@ -29,6 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "overlay_address.h"
#include "crypto.h"
#include "overlay_packet.h"
#include "keyring.h"
static void keyring_free_keypair(keypair *kp);
static void keyring_free_context(keyring_context *c);
@ -429,6 +430,7 @@ static const char *keytype_str(unsigned ktype, const char *unknown)
case KEYTYPE_CRYPTOSIGN: return "CRYPTOSIGN";
case KEYTYPE_RHIZOME: return "RHIZOME";
case KEYTYPE_DID: return "DID";
case KEYTYPE_PUBLIC_TAG: return "PUBLIC_TAG";
default: return unknown;
}
}
@ -439,7 +441,7 @@ struct keytype {
size_t packed_size;
void (*creator)(keypair *);
int (*packer)(const keypair *, struct rotbuf *);
int (*unpacker)(keypair *, struct rotbuf *);
int (*unpacker)(keypair *, struct rotbuf *, int);
void (*dumper)(const keypair *, XPRINTF, int);
int (*loader)(keypair *, const char *);
};
@ -485,6 +487,12 @@ static int pack_private_only(const keypair *kp, struct rotbuf *rb)
return 0;
}
static int pack_public_only(const keypair *kp, struct rotbuf *rb)
{
rotbuf_putbuf(rb, kp->public_key, kp->public_key_len);
return 0;
}
static int pack_private_public(const keypair *kp, struct rotbuf *rb)
{
rotbuf_putbuf(rb, kp->private_key, kp->private_key_len);
@ -619,20 +627,36 @@ static int load_unknown(keypair *kp, const char *text)
return 0;
}
static int unpack_private_public(keypair *kp, struct rotbuf *rb)
static int unpack_private_public(keypair *kp, struct rotbuf *rb, int key_length)
{
rotbuf_getbuf(rb, kp->private_key, kp->private_key_len);
rotbuf_getbuf(rb, kp->public_key, kp->public_key_len);
return 0;
}
static int unpack_private_only(keypair *kp, struct rotbuf *rb)
static int unpack_private_only(keypair *kp, struct rotbuf *rb, int key_length)
{
if (!kp->private_key){
kp->private_key_len = key_length;
if ((kp->private_key = emalloc(kp->private_key_len))==NULL)
return -1;
}
rotbuf_getbuf(rb, kp->private_key, kp->private_key_len);
return 0;
}
static int unpack_cryptobox(keypair *kp, struct rotbuf *rb)
static int unpack_public_only(keypair *kp, struct rotbuf *rb, int key_length)
{
if (!kp->public_key){
kp->public_key_len = key_length;
if ((kp->public_key = emalloc(kp->public_key_len))==NULL)
return -1;
}
rotbuf_getbuf(rb, kp->public_key, kp->public_key_len);
return 0;
}
static int unpack_cryptobox(keypair *kp, struct rotbuf *rb, int key_length)
{
rotbuf_getbuf(rb, kp->private_key, kp->private_key_len);
if (!rb->wrap)
@ -648,9 +672,9 @@ static int pack_did_name(const keypair *kp, struct rotbuf *rb)
return pack_private_public(kp, rb);
}
static int unpack_did_name(keypair *kp, struct rotbuf *rb)
static int unpack_did_name(keypair *kp, struct rotbuf *rb, int key_length)
{
if (unpack_private_public(kp, rb) == -1)
if (unpack_private_public(kp, rb, key_length) == -1)
return -1;
// Fail if name is not nul terminated.
return strnchr((const char *)kp->public_key, kp->public_key_len, '\0') == NULL ? -1 : 0;
@ -763,6 +787,16 @@ const struct keytype keytypes[] = {
.unpacker = unpack_did_name,
.dumper = dump_did_name,
.loader = load_did_name
},
[KEYTYPE_PUBLIC_TAG] = {
.private_key_size = 0,
.public_key_size = 0, // size is derived from the stored key length
.packed_size = 0,
.creator = NULL, // not included in a newly created identity
.packer = pack_public_only,
.unpacker = unpack_public_only,
.dumper = dump_private_public,
.loader = load_unknown
}
// ADD MORE KEY TYPES HERE
};
@ -837,13 +871,16 @@ static int keyring_pack_identity(const keyring_identity *id, unsigned char packe
unsigned ktype = id->keypairs[kp]->type;
const char *kts = keytype_str(ktype, "unknown");
int (*packer)(const keypair *, struct rotbuf *) = NULL;
size_t keypair_len;
size_t keypair_len=0;
const struct keytype *kt = &keytypes[ktype];
if (ktype == 0x00)
FATALF("ktype=0 in keypair kp=%u", kp);
if (ktype < NELS(keytypes)) {
packer = kt->packer;
keypair_len = kt->packed_size;
if (keypair_len==0){
keypair_len = id->keypairs[kp]->private_key_len + id->keypairs[kp]->public_key_len;
}
} else {
packer = pack_private_only;
keypair_len = id->keypairs[kp]->private_key_len;
@ -916,16 +953,24 @@ static int cmp_keypair(const keypair *a, const keypair *b)
{
int c = a->type < b->type ? -1 : a->type > b->type ? 1 : 0;
if (c == 0 && a->public_key_len) {
assert(a->public_key_len == b->public_key_len);
assert(a->public_key != NULL);
assert(b->public_key != NULL);
c = memcmp(a->public_key, b->public_key, a->public_key_len);
int len=a->public_key_len;
if (len>b->public_key_len)
len=b->public_key_len;
c = memcmp(a->public_key, b->public_key, len);
if (c==0 && a->public_key_len!=b->public_key_len)
c = a->public_key_len - b->public_key_len;
}
if (c == 0 && a->private_key_len) {
assert(a->private_key_len == b->private_key_len);
assert(a->private_key != NULL);
assert(b->private_key != NULL);
c = memcmp(a->private_key, b->private_key, a->private_key_len);
int len=a->private_key_len;
if (len>b->private_key_len)
len=b->private_key_len;
c = memcmp(a->private_key, b->private_key, len);
if (c==0 && a->private_key_len!=b->private_key_len)
c = a->private_key_len - b->private_key_len;
}
return c;
}
@ -1009,7 +1054,7 @@ static keyring_identity *keyring_unpack_identity(unsigned char *slot, const char
if (ktype < NELS(keytypes) && kt->unpacker) {
if (config.debug.keyring)
DEBUGF("unpack key type = 0x%02x(%s) at offset %u", ktype, keytype_str(ktype, "unknown"), (int)rotbuf_position(&rbo));
if (kt->unpacker(kp, &rbuf) != 0) {
if (kt->unpacker(kp, &rbuf, keypair_len) != 0) {
// If there is an error, it is probably an empty slot.
if (config.debug.keyring)
DEBUGF("key type 0x%02x does not unpack", ktype);
@ -1415,10 +1460,14 @@ int keyring_set_did(keyring_identity *id, const char *did, const char *name)
}
/* Store DID unpacked for ease of searching */
int len=strlen(did); if (len>31) len=31;
int len=strlen(did);
if (len>31)
len=31;
bcopy(did,&id->keypairs[i]->private_key[0],len);
bzero(&id->keypairs[i]->private_key[len],32-len);
len=strlen(name); if (len>63) len=63;
len=strlen(name);
if (len>63)
len=63;
bcopy(name,&id->keypairs[i]->public_key[0],len);
bzero(&id->keypairs[i]->public_key[len],64-len);
@ -1429,10 +1478,9 @@ int keyring_set_did(keyring_identity *id, const char *did, const char *name)
return 0;
}
int keyring_find_did(const keyring_file *k,int *cn,int *in,int *kp,char *did)
int keyring_find_did(const keyring_file *k, int *cn, int *in, int *kp, const char *did)
{
for (; keyring_sanitise_position(k,cn,in,kp) == 0; ++*kp) {
if (k->contexts[*cn]->identities[*in]->keypairs[*kp]->type==KEYTYPE_DID) {
for(;keyring_next_keytype(k,cn,in,kp,KEYTYPE_DID);++(*kp)) {
/* Compare DIDs */
if ((!did[0])
||(did[0]=='*'&&did[1]==0)
@ -1442,6 +1490,105 @@ int keyring_find_did(const keyring_file *k,int *cn,int *in,int *kp,char *did)
return 1; // match
}
}
return 0;
}
int keyring_unpack_tag(const unsigned char *packed, size_t packed_len, const char **name, const unsigned char **value, size_t *length)
{
size_t i;
for (i=0;i<packed_len;i++){
if (packed[i]==0){
*name = (const char*)packed;
if (value)
*value = &packed[i+1];
if (length)
*length = packed_len - (i+1);
return 0;
}
}
return WHY("Did not find NULL values in tag");
}
int keyring_pack_tag(unsigned char *packed, size_t *packed_len, const char *name, const unsigned char *value, size_t length)
{
size_t name_len=strlen(name)+1;
if (packed && *packed_len <name_len+length)
return -1;
*packed_len=name_len+length;
if (packed){
bcopy(name, packed, name_len);
bcopy(value, &packed[name_len], length);
}
return 0;
}
int keyring_set_public_tag(keyring_identity *id, const char *name, const unsigned char *value, size_t length)
{
int i;
for(i=0;i<id->keypair_count;i++){
const char *tag_name;
const unsigned char *tag_value;
size_t tag_length;
if (id->keypairs[i]->type==KEYTYPE_PUBLIC_TAG &&
keyring_unpack_tag(id->keypairs[i]->public_key, id->keypairs[i]->public_key_len,
&tag_name, &tag_value, &tag_length)==0 &&
strcmp(tag_name, name)==0) {
if (config.debug.keyring)
DEBUG("Found existing public tag");
break;
}
}
if (i >= PKR_MAX_KEYPAIRS)
return WHY("Too many key pairs");
/* allocate if needed */
if (i >= id->keypair_count) {
if (config.debug.keyring)
DEBUGF("Creating new public tag @%d", i);
if ((id->keypairs[i] = keyring_alloc_keypair(KEYTYPE_PUBLIC_TAG, 0)) == NULL)
return -1;
++id->keypair_count;
}
if (id->keypairs[i]->public_key)
free(id->keypairs[i]->public_key);
if (keyring_pack_tag(NULL, &id->keypairs[i]->public_key_len, name, value, length))
return -1;
id->keypairs[i]->public_key = emalloc(id->keypairs[i]->public_key_len);
if (!id->keypairs[i]->public_key)
return -1;
if (keyring_pack_tag(id->keypairs[i]->public_key, &id->keypairs[i]->public_key_len, name, value, length))
return -1;
if (config.debug.keyring)
dump("New tag", id->keypairs[i]->public_key, id->keypairs[i]->public_key_len);
return 0;
}
int keyring_find_public_tag(const keyring_file *k, int *cn, int *in, int *kp, const char *name, const unsigned char **value, size_t *length)
{
for(;keyring_next_keytype(k,cn,in,kp,KEYTYPE_PUBLIC_TAG);++(*kp)) {
keypair *keypair=k->contexts[*cn]->identities[*in]->keypairs[*kp];
const char *tag_name;
if (!keyring_unpack_tag(keypair->public_key, keypair->public_key_len, &tag_name, value, length) &&
strcmp(name, tag_name)==0){
return 1;
}
}
if (value)
*value=NULL;
return 0;
}
int keyring_find_public_tag_value(const keyring_file *k, int *cn, int *in, int *kp, const char *name, const unsigned char *value, size_t length)
{
const unsigned char *stored_value;
size_t stored_length;
for(;keyring_find_public_tag(k, cn, in, kp, name, &stored_value, &stored_length);++(*kp)) {
if (stored_length == length && memcmp(value, stored_value, length)==0)
return 1;
}
return 0;
}
@ -1470,44 +1617,46 @@ int keyring_next_identity(const keyring_file *k, int *cn, int *in, int *kp)
int keyring_sanitise_position(const keyring_file *k,int *cn,int *in,int *kp)
{
if (!k) return 1;
if (!k)
return 1;
/* Sanity check passed in position */
if ((*cn)>=k->context_count) return 1;
if ((*in)>=k->contexts[*cn]->identity_count)
{
(*in)=0; (*cn)++;
if ((*cn)>=k->context_count) return 1;
}
if ((*kp)>=k->contexts[*cn]->identities[*in]->keypair_count)
{
*kp=0; (*in)++;
if ((*in)>=k->contexts[*cn]->identity_count)
{
(*in)=0; (*cn)++;
if ((*cn)>=k->context_count) return 1;
while(1){
if ((*cn)>=k->context_count)
return 1;
if ((*in)>=k->contexts[*cn]->identity_count){
(*in)=(*kp)=0;
(*cn)++;
continue;
}
if ((*kp)>=k->contexts[*cn]->identities[*in]->keypair_count){
*kp=0;
(*in)++;
continue;
}
return 0;
}
}
unsigned char *keyring_find_sas_private(keyring_file *k, const sid_t *sidp, unsigned char **sas_public_out)
{
IN();
int cn=0,in=0,kp=0;
if (!keyring_find_sid(k,&cn,&in,&kp,sidp)) {
if (!keyring_find_sid(k,&cn,&in,&kp,sidp))
RETURNNULL(WHYNULL("Could not find SID in keyring, so can't find SAS"));
}
for(kp=0;kp<k->contexts[cn]->identities[in]->keypair_count;kp++)
if (k->contexts[cn]->identities[in]->keypairs[kp]->type==KEYTYPE_CRYPTOSIGN)
{
kp = keyring_identity_find_keytype(k, cn, in, KEYTYPE_CRYPTOSIGN);
if (kp==-1)
RETURNNULL(WHYNULL("Identity lacks SAS"));
unsigned char *sas_private=
k->contexts[cn]->identities[in]->keypairs[kp]->private_key;
unsigned char *sas_public=
k->contexts[cn]->identities[in]->keypairs[kp]->public_key;
if (!rhizome_verify_bundle_privatekey(sas_private, sas_public))
{
if (!rhizome_verify_bundle_privatekey(sas_private,sas_public)){
/* SAS key is invalid (perhaps because it was a pre 0.90 format one),
so replace it */
WARN("SAS key is invalid -- regenerating.");
@ -1518,9 +1667,6 @@ unsigned char *keyring_find_sas_private(keyring_file *k, const sid_t *sidp, unsi
DEBUGF("Found SAS entry for %s*", alloca_tohex(sidp->binary, 7));
if (sas_public_out) *sas_public_out=sas_public;
RETURN(sas_private);
}
RETURNNULL(WHYNULL("Identity lacks SAS"));
OUT();
}
@ -1790,10 +1936,10 @@ int keyring_send_sas_request(struct subscriber *subscriber){
int keyring_find_sid(const keyring_file *k, int *cn, int *in, int *kp, const sid_t *sidp)
{
for (; keyring_sanitise_position(k, cn, in, kp) == 0; ++*kp)
if (k->contexts[*cn]->identities[*in]->keypairs[*kp]->type == KEYTYPE_CRYPTOBOX
&& memcmp(sidp->binary, k->contexts[*cn]->identities[*in]->keypairs[*kp]->public_key, SID_SIZE) == 0)
for(; keyring_next_keytype(k,cn,in,kp,KEYTYPE_CRYPTOBOX); ++(*kp)) {
if (memcmp(sidp->binary, k->contexts[*cn]->identities[*in]->keypairs[*kp]->public_key, SID_SIZE) == 0)
return 1;
}
return 0;
}

109
keyring.h Normal file
View File

@ -0,0 +1,109 @@
#ifndef __SERVALD_KEYRING_H
#define __SERVALD_KEYRING_H
typedef struct keypair {
int type;
unsigned char *private_key;
size_t private_key_len;
unsigned char *public_key;
size_t public_key_len;
} keypair;
/* Contains just the list of private:public key pairs and types,
the pin used to extract them, and the slot in the keyring file
(so that it can be replaced/rewritten as required). */
#define PKR_MAX_KEYPAIRS 64
#define PKR_SALT_BYTES 32
#define PKR_MAC_BYTES 64
typedef struct keyring_identity {
char *PKRPin;
struct subscriber *subscriber;
time_ms_t challenge_expires;
unsigned char challenge[24];
unsigned int slot;
unsigned int keypair_count;
keypair *keypairs[PKR_MAX_KEYPAIRS];
} keyring_identity;
/* 64K identities, can easily be increased should the need arise,
but keep it low-ish for now so that the 64K pointers don't eat too
much ram on a small device. Should probably think about having
small and large device settings for some of these things */
#define KEYRING_MAX_IDENTITIES 65536
typedef struct keyring_context {
char *KeyRingPin;
unsigned char *KeyRingSalt;
int KeyRingSaltLen;
unsigned int identity_count;
keyring_identity *identities[KEYRING_MAX_IDENTITIES];
} keyring_context;
#define KEYRING_PAGE_SIZE 4096LL
#define KEYRING_BAM_BYTES 2048LL
#define KEYRING_BAM_BITS (KEYRING_BAM_BYTES<<3)
#define KEYRING_SLAB_SIZE (KEYRING_PAGE_SIZE*KEYRING_BAM_BITS)
typedef struct keyring_bam {
off_t file_offset;
unsigned char bitmap[KEYRING_BAM_BYTES];
struct keyring_bam *next;
} keyring_bam;
#define KEYRING_MAX_CONTEXTS 256
typedef struct keyring_file {
int context_count;
keyring_bam *bam;
keyring_context *contexts[KEYRING_MAX_CONTEXTS];
FILE *file;
off_t file_size;
} keyring_file;
void keyring_free(keyring_file *k);
void keyring_release_identity(keyring_file *k, int cn, int id);
#define KEYTYPE_CRYPTOBOX 0x01 // must be lowest
#define KEYTYPE_CRYPTOSIGN 0x02
#define KEYTYPE_RHIZOME 0x03
/* DIDs aren't really keys, but the keyring is a real handy place to keep them,
and keep them private if people so desire */
#define KEYTYPE_DID 0x04
/* Arbitrary name / value pairs */
#define KEYTYPE_PUBLIC_TAG 0x05
/* handle to keyring file for use in running instance */
extern keyring_file *keyring;
/* Public calls to keyring management */
keyring_file *keyring_open(const char *path, int writeable);
keyring_file *keyring_open_instance();
keyring_file *keyring_open_instance_cli(const struct cli_parsed *parsed);
int keyring_enter_pin(keyring_file *k, const char *pin);
int keyring_set_did(keyring_identity *id, const char *did, const char *name);
int keyring_sanitise_position(const keyring_file *k,int *cn,int *in,int *kp);
int keyring_next_keytype(const keyring_file *k, int *cn, int *in, int *kp, int keytype);
int keyring_next_identity(const keyring_file *k,int *cn,int *in,int *kp);
int keyring_identity_find_keytype(const keyring_file *k, int cn, int in, int keytype);
int keyring_find_did(const keyring_file *k,int *cn,int *in,int *kp, const char *did);
int keyring_find_sid(const keyring_file *k,int *cn,int *in,int *kp, const sid_t *sidp);
unsigned char *keyring_find_sas_private(keyring_file *k, const sid_t *sidp, unsigned char **sas_public);
int keyring_send_sas_request(struct subscriber *subscriber);
int keyring_commit(keyring_file *k);
keyring_identity *keyring_create_identity(keyring_file *k,keyring_context *c, const char *pin);
int keyring_seed(keyring_file *k);
void keyring_identity_extract(const keyring_identity *id, const sid_t **sidp, const char **didp, const char **namep);
int keyring_load(keyring_file *k, const char *keyring_pin, unsigned entry_pinc, const char **entry_pinv, FILE *input);
int keyring_dump(keyring_file *k, XPRINTF xpf, int include_secret);
unsigned char *keyring_get_nm_bytes(const sid_t *known_sidp, const sid_t *unknown_sidp);
int keyring_mapping_request(keyring_file *k, struct overlay_frame *frame, overlay_mdp_frame *req);
int keyring_send_unlock(struct subscriber *subscriber);
void keyring_release_subscriber(keyring_file *k, const sid_t *sid);
int keyring_set_public_tag(keyring_identity *id, const char *name, const unsigned char *value, size_t length);
int keyring_find_public_tag(const keyring_file *k, int *cn, int *in, int *kp, const char *name, const unsigned char **value, size_t *length);
int keyring_find_public_tag_value(const keyring_file *k, int *cn, int *in, int *kp, const char *name, const unsigned char *value, size_t length);
int keyring_unpack_tag(const unsigned char *packed, size_t packed_len, const char **name, const unsigned char **value, size_t *length);
int keyring_pack_tag(unsigned char *packed, size_t *packed_len, const char *name, const unsigned char *value, size_t length);
#endif // __SERVALD_KEYRING_H

View File

@ -48,14 +48,27 @@ struct mdp_header {
#define ACTION_LOCK 1
#define ACTION_UNLOCK 2
/* Port numbers for commands sent to the local daemon*/
/* lock and unlock identities from the local keyring
* Requests start with an mdp_identity_request structure followed by a list of pins or SIDs
*/
#define MDP_IDENTITY 1
/* Search unlocked identities from the running daemon
* If the request is empty, all identities will be returned
* if the request contains a packed tag / value, identities with a matching tag will be returned
* if the value passed in is zero length, all identities with that tag and any value will be returned
*/
#define MDP_SEARCH_IDS 2
// an identity request is sent to port MDP_IDENTITY, sid ANY
struct mdp_identity_request{
uint8_t action;
uint8_t type;
// followed by a list of SID's or NULL terminated entry pins for the remainder of the payload
// the request is followed by a list of SID's or NULL terminated entry pins for the remainder of the payload
};
#define MDP_IDENTITY 1
#pragma pack(pop)
struct overlay_route_record{

View File

@ -5,6 +5,7 @@
#include "conf.h"
#include "crypto.h"
#include "strlcpy.h"
#include "keyring.h"
#define MESHMS_BLOCK_TYPE_ACK 0x01
#define MESHMS_BLOCK_TYPE_MESSAGE 0x02

View File

@ -72,6 +72,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "conf.h"
#include "rhizome.h"
#include "strbuf.h"
#include "keyring.h"
int overlayMode=0;

View File

@ -82,7 +82,7 @@ struct subscriber{
unsigned char sas_valid;
// private keys for local identities
keyring_identity *identity;
struct keyring_identity *identity;
};
struct broadcast{

View File

@ -4,6 +4,7 @@
#include "overlay_address.h"
#include "overlay_buffer.h"
#include "overlay_packet.h"
#include "keyring.h"
#define MIN_BURST_LENGTH 5000

View File

@ -29,6 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "overlay_packet.h"
#include "mdp_client.h"
#include "crypto.h"
#include "keyring.h"
static void overlay_mdp_poll(struct sched_ent *alarm);
static void mdp_poll2(struct sched_ent *alarm);
@ -963,7 +964,7 @@ static int mdp_reply2(const struct mdp_client *client, const struct mdp_header *
#define mdp_reply_ok(A,B) mdp_reply2(A,B,MDP_FLAG_OK,NULL,0)
static int mdp_process_identity_request(struct mdp_client *client, struct mdp_header *header,
const unsigned char *payload, int payload_len)
const unsigned char *payload, size_t payload_len)
{
if (payload_len<sizeof(struct mdp_identity_request)){
mdp_reply_error(client, header);
@ -979,7 +980,7 @@ static int mdp_process_identity_request(struct mdp_client *client, struct mdp_he
case TYPE_PIN:
{
const char *pin = (char *)payload;
int ofs=0;
size_t ofs=0;
while(ofs < payload_len){
if (!payload[ofs++]){
int cn, in;
@ -1018,7 +1019,7 @@ static int mdp_process_identity_request(struct mdp_client *client, struct mdp_he
}
int unlock_count=0;
const char *pin = (char *)payload;
int ofs=0;
size_t ofs=0;
while(ofs < payload_len){
if (!payload[ofs++]){
unlock_count += keyring_enter_pin(keyring, pin);
@ -1035,6 +1036,56 @@ static int mdp_process_identity_request(struct mdp_client *client, struct mdp_he
return 0;
}
// return one response per matching identity
static int mdp_search_identities(struct mdp_client *client, struct mdp_header *header,
const unsigned char *payload, size_t payload_len)
{
int cn=0, in=0, kp=0;
const char *tag=NULL;
const unsigned char *value=NULL;
size_t value_len=0;
if (payload_len){
if (keyring_unpack_tag(payload, payload_len, &tag, &value, &value_len)){
mdp_reply_error(client, header);
return -1;
}
}
while(1){
if (value_len){
if (config.debug.mdprequests)
DEBUGF("Looking for next %s tag & value", tag);
if (!keyring_find_public_tag_value(keyring, &cn, &in, &kp, tag, value, value_len))
break;
}else if(tag){
if (config.debug.mdprequests)
DEBUGF("Looking for next %s tag", tag);
if (!keyring_find_public_tag(keyring, &cn, &in, &kp, tag, NULL, NULL))
break;
}else{
if (config.debug.mdprequests)
DEBUGF("Looking for next identity");
if (!keyring_next_identity(keyring, &cn, &in, &kp))
break;
}
keyring_identity *id = keyring->contexts[cn]->identities[in];
unsigned char reply_payload[1200];
int ofs=0;
bcopy(id->subscriber->sid.binary, &reply_payload[ofs], sizeof(id->subscriber->sid));
ofs+=sizeof(id->subscriber->sid);
// TODO return other details of this identity
mdp_reply2(client, header, 0, reply_payload, ofs);
kp++;
}
mdp_reply_ok(client, header);
return 0;
}
static void mdp_poll2(struct sched_ent *alarm)
{
if (alarm->poll.revents & POLLIN) {
@ -1048,7 +1099,7 @@ static void mdp_poll2(struct sched_ent *alarm)
ssize_t len = recvwithttl(alarm->poll.fd, buffer, sizeof(buffer), &ttl, (struct sockaddr *)&addr, &client.addrlen);
if (len<=sizeof(struct mdp_header)){
if (len<sizeof(struct mdp_header)){
WHYF("Expected length %d, got %d from %s", (int)sizeof(struct mdp_header), (int)len, alloca_sockaddr(client.addr, client.addrlen));
return;
}
@ -1056,16 +1107,23 @@ static void mdp_poll2(struct sched_ent *alarm)
struct mdp_header *header = (struct mdp_header *)buffer;
unsigned char *payload = &buffer[sizeof(struct mdp_header)];
int payload_len = len - sizeof(struct mdp_header);
size_t payload_len = len - sizeof(struct mdp_header);
if (is_sid_t_any(header->remote.sid)){
// process local commands
switch(header->remote.port){
// lock and unlock identities
case MDP_IDENTITY:
if (config.debug.mdprequests)
DEBUGF("Processing MDP_IDENTITY from %s", alloca_sockaddr(client.addr, client.addrlen));
mdp_process_identity_request(&client, header, payload, payload_len);
break;
// seach unlocked identities
case MDP_SEARCH_IDS:
if (config.debug.mdprequests)
DEBUGF("Processing MDP_SEARCH_IDS from %s", alloca_sockaddr(client.addr, client.addrlen));
mdp_search_identities(&client, header, payload, payload_len);
break;
default:
mdp_reply_error(&client, header);
WHY("Unknown port number");

View File

@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "rhizome.h"
#include "crypto.h"
#include "log.h"
#include "keyring.h"
int rhizome_mdp_send_block(struct subscriber *dest, const rhizome_bid_t *bid, uint64_t version, uint64_t fileOffset, uint32_t bitmap, uint16_t blockLength)
{

View File

@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "rhizome.h"
#include "str.h"
#include "mem.h"
#include "keyring.h"
static const char *rhizome_manifest_get(const rhizome_manifest *m, const char *var)
{

View File

@ -29,6 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "str.h"
#include "rhizome.h"
#include "crypto.h"
#include "keyring.h"
/* Work out the encrypt/decrypt key for the supplied manifest.
If the manifest is not encrypted, then return NULL.

View File

@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "strbuf.h"
#include "strbuf_helpers.h"
#include "str.h"
#include "keyring.h"
static char rhizome_thisdatastore_path[256];

View File

@ -4,6 +4,7 @@
#include "overlay_packet.h"
#include "str.h"
#include "conf.h"
#include "keyring.h"
#include <assert.h>
/*

View File

@ -103,7 +103,6 @@ struct in_addr {
#endif
#include <fcntl.h>
#include <ctype.h>
#include <sys/stat.h>
#include "fdqueue.h"
@ -240,100 +239,9 @@ extern char *instrumentation_file;
extern char *batman_socket;
extern char *batman_peerfile;
struct subscriber;
struct decode_context;
typedef struct keypair {
int type;
unsigned char *private_key;
size_t private_key_len;
unsigned char *public_key;
size_t public_key_len;
} keypair;
/* Contains just the list of private:public key pairs and types,
the pin used to extract them, and the slot in the keyring file
(so that it can be replaced/rewritten as required). */
#define PKR_MAX_KEYPAIRS 64
#define PKR_SALT_BYTES 32
#define PKR_MAC_BYTES 64
typedef struct keyring_identity {
char *PKRPin;
struct subscriber *subscriber;
time_ms_t challenge_expires;
unsigned char challenge[24];
unsigned int slot;
unsigned int keypair_count;
keypair *keypairs[PKR_MAX_KEYPAIRS];
} keyring_identity;
/* 64K identities, can easily be increased should the need arise,
but keep it low-ish for now so that the 64K pointers don't eat too
much ram on a small device. Should probably think about having
small and large device settings for some of these things */
#define KEYRING_MAX_IDENTITIES 65536
typedef struct keyring_context {
char *KeyRingPin;
unsigned char *KeyRingSalt;
int KeyRingSaltLen;
unsigned int identity_count;
keyring_identity *identities[KEYRING_MAX_IDENTITIES];
} keyring_context;
#define KEYRING_PAGE_SIZE 4096LL
#define KEYRING_BAM_BYTES 2048LL
#define KEYRING_BAM_BITS (KEYRING_BAM_BYTES<<3)
#define KEYRING_SLAB_SIZE (KEYRING_PAGE_SIZE*KEYRING_BAM_BITS)
typedef struct keyring_bam {
off_t file_offset;
unsigned char bitmap[KEYRING_BAM_BYTES];
struct keyring_bam *next;
} keyring_bam;
#define KEYRING_MAX_CONTEXTS 256
typedef struct keyring_file {
int context_count;
keyring_bam *bam;
keyring_context *contexts[KEYRING_MAX_CONTEXTS];
FILE *file;
off_t file_size;
} keyring_file;
void keyring_free(keyring_file *k);
void keyring_release_identity(keyring_file *k, int cn, int id);
#define KEYTYPE_CRYPTOBOX 0x01 // must be lowest
#define KEYTYPE_CRYPTOSIGN 0x02
#define KEYTYPE_RHIZOME 0x03
/* DIDs aren't really keys, but the keyring is a real handy place to keep them,
and keep them private if people so desire */
#define KEYTYPE_DID 0x04
/* handle to keyring file for use in running instance */
extern keyring_file *keyring;
/* Public calls to keyring management */
keyring_file *keyring_open(const char *path, int writeable);
keyring_file *keyring_open_instance();
keyring_file *keyring_open_instance_cli(const struct cli_parsed *parsed);
int keyring_enter_pin(keyring_file *k, const char *pin);
int keyring_set_did(keyring_identity *id, const char *did, const char *name);
int keyring_sanitise_position(const keyring_file *k,int *cn,int *in,int *kp);
int keyring_next_keytype(const keyring_file *k, int *cn, int *in, int *kp, int keytype);
int keyring_next_identity(const keyring_file *k,int *cn,int *in,int *kp);
int keyring_identity_find_keytype(const keyring_file *k, int cn, int in, int keytype);
int keyring_find_did(const keyring_file *k,int *cn,int *in,int *kp,char *did);
int keyring_find_sid(const keyring_file *k,int *cn,int *in,int *kp, const sid_t *sidp);
unsigned char *keyring_find_sas_private(keyring_file *k, const sid_t *sidp, unsigned char **sas_public);
int keyring_send_sas_request(struct subscriber *subscriber);
int keyring_commit(keyring_file *k);
keyring_identity *keyring_create_identity(keyring_file *k,keyring_context *c, const char *pin);
int keyring_seed(keyring_file *k);
void keyring_identity_extract(const keyring_identity *id, const sid_t **sidp, const char **didp, const char **namep);
int keyring_load(keyring_file *k, const char *keyring_pin, unsigned entry_pinc, const char **entry_pinv, FILE *input);
int keyring_dump(keyring_file *k, XPRINTF xpf, int include_secret);
/* Make sure we have space to put bytes of the packet as we go along */
#define CHECK_PACKET_LEN(B) {if (((*packet_len)+(B))>=packet_maxlen) { return WHY("Packet composition ran out of space."); } }
@ -612,7 +520,6 @@ typedef struct sockaddr_mdp {
sid_t sid;
mdp_port_t port;
} sockaddr_mdp;
unsigned char *keyring_get_nm_bytes(const sid_t *known_sidp, const sid_t *unknown_sidp);
typedef struct overlay_mdp_data_frame {
sockaddr_mdp src;
@ -664,10 +571,6 @@ typedef struct overlay_mdp_frame {
};
} overlay_mdp_frame;
int keyring_mapping_request(keyring_file *k, struct overlay_frame *frame, overlay_mdp_frame *req);
int keyring_send_unlock(struct subscriber *subscriber);
void keyring_release_subscriber(keyring_file *k, const sid_t *sid);
/* Server-side MDP functions */
int overlay_mdp_swap_src_dst(overlay_mdp_frame *mdp);
int overlay_mdp_reply(int sock,struct sockaddr_un *recvaddr, socklen_t recvaddrlen,

4
str.h
View File

@ -104,7 +104,9 @@ size_t toprint_len(const char *srcBuf, size_t srcBytes, const char quotes[2]);
size_t toprint_str_len(const char *srcStr, const char quotes[2]);
size_t strn_fromprint(unsigned char *dst, size_t dstsiz, const char *src, size_t srclen, char endquote, const char **afterp);
#define alloca_toprint(dstlen,buf,len) toprint((char *)alloca((dstlen) == -1 ? toprint_len((const char *)(buf),(len), "``") + 1 : (dstlen)), (dstlen), (const char *)(buf), (len), "``")
#define alloca_toprint_quoted(dstlen,buf,len,quotes) toprint((char *)alloca((dstlen) == -1 ? toprint_len((const char *)(buf),(len), (quotes)) + 1 : (dstlen)), (dstlen), (const char *)(buf), (len), (quotes))
#define alloca_toprint(dstlen,buf,len) alloca_toprint_quoted(dstlen,buf,len,"``")
#define alloca_str_toprint_quoted(str, quotes) toprint_str((char *)alloca(toprint_str_len((str), (quotes)) + 1), -1, (str), (quotes))
#define alloca_str_toprint(str) alloca_str_toprint_quoted(str, "``")

View File

@ -29,6 +29,12 @@ setup() {
set_instance +A
}
teardown_servald() {
kill_all_servald_processes
assert_no_servald_processes
report_servald_server
}
setup_instances() {
for arg; do
set_instance $arg
@ -56,6 +62,46 @@ test_KeyringCreate() {
assert_keyring_list 0
}
doc_DidName="Create an identity & set the name and number"
test_DidName() {
executeOk_servald keyring add ''
assertStdoutGrep --matches=1 "^sid:"
assertStdoutLineCount '==' 1
extract_stdout_keyvalue SID sid "$rexp_sid"
executeOk_servald keyring set did "$SID" '123456' 'Display Name'
assertStdoutGrep --matches=1 "^sid:$SID\$"
assertStdoutGrep --matches=1 "^did:123456\$"
assertStdoutGrep --matches=1 "^name:Display Name\$"
assertStdoutLineCount '==' 3
executeOk_servald keyring list
assertStdoutGrep --stderr --matches=1 "^$SID:123456:Display Name\$"
}
keyring_set_tag() {
executeOk_servald keyring set tag "$1" "$2" "$3"
assertStdoutGrep --matches=1 "^sid:$1\$"
assertStdoutGrep --matches=1 "^$2:$3\$"
}
doc_SetTag="Set a named tag against an identity"
test_SetTag() {
executeOk_servald keyring add ''
assertStdoutGrep --matches=1 "^sid:"
assertStdoutLineCount '==' 1
extract_stdout_keyvalue SID sid "$rexp_sid"
keyring_set_tag "$SID" 'tag1' 'First Value'
assertStdoutLineCount '==' 2
keyring_set_tag "$SID" 'tag2' 'Second Value'
executeOk_servald keyring set tag "$SID" 'tag2' 'Second Value'
assertStdoutGrep --matches=1 "^tag1:First Value\$"
assertStdoutLineCount '==' 3
keyring_set_tag "$SID" 'tag1' 'Third Value'
assertStdoutGrep --matches=1 "^tag2:Second Value\$"
assertStdoutLineCount '==' 3
executeOk_servald keyring dump --secret
tfw_cat --stdout
}
doc_Pinless="No keyring PIN with PIN-less identities"
test_Pinless() {
executeOk_servald keyring add ''
@ -141,9 +187,7 @@ finally_KeyringAutoCreate() {
stop_servald_server
}
teardown_KeyringAutoCreate() {
kill_all_servald_processes
assert_no_servald_processes
report_servald_server
teardown_servald
}
doc_KeyringPinServer="Start daemon with a keyring PIN"
@ -161,9 +205,7 @@ finally_KeyringPinServer() {
stop_servald_server
}
teardown_KeyringPinServer() {
kill_all_servald_processes
assert_no_servald_processes
report_servald_server
teardown_servald
}
doc_EntryPinServer="Start daemon with an entry PIN"
@ -181,9 +223,7 @@ finally_KeyringPinServer() {
stop_servald_server
}
teardown_KeyringPinServer() {
kill_all_servald_processes
assert_no_servald_processes
report_servald_server
teardown_servald
}
doc_KeyringEntryPinServer="Start daemon with a keyring and an entry PIN"
@ -201,9 +241,7 @@ finally_KeyringKeyringPinServer() {
stop_servald_server
}
teardown_KeyringKeyringPinServer() {
kill_all_servald_processes
assert_no_servald_processes
report_servald_server
teardown_servald
}
doc_KeyringEntryPinServer="Start daemon, unlock and lock identities"
@ -224,34 +262,64 @@ test_KeyringEntryPinServer() {
assertStdoutLineCount == 1
assertStdoutGrep --fixed-strings "$SIDA"
executeOk_servald id enter pin 'one'
executeOk_servald id self
executeOk_servald id list
assertStdoutLineCount == 2
assertStdoutGrep --fixed-strings "$SIDA"
assertStdoutGrep --fixed-strings "$ONE"
assertStdoutGrep --fixed-strings "sid:$SIDA"
assertStdoutGrep --fixed-strings "sid:$ONE"
executeOk_servald id enter pin 'two'
executeOk_servald id self
executeOk_servald id list
assertStdoutLineCount == 4
assertStdoutGrep --fixed-strings "$SIDA"
assertStdoutGrep --fixed-strings "$ONE"
assertStdoutGrep --fixed-strings "$TWOA"
assertStdoutGrep --fixed-strings "$TWOB"
assertStdoutGrep --fixed-strings "sid:$SIDA"
assertStdoutGrep --fixed-strings "sid:$ONE"
assertStdoutGrep --fixed-strings "sid:$TWOA"
assertStdoutGrep --fixed-strings "sid:$TWOB"
executeOk_servald id relinquish pin 'one'
executeOk_servald id self
executeOk_servald id list
assertStdoutLineCount == 3
assertStdoutGrep --fixed-strings "$SIDA"
assertStdoutGrep --fixed-strings "$TWOA"
assertStdoutGrep --fixed-strings "$TWOB"
assertStdoutGrep --fixed-strings "sid:$SIDA"
assertStdoutGrep --fixed-strings "sid:$TWOA"
assertStdoutGrep --fixed-strings "sid:$TWOB"
executeOk_servald id relinquish sid "$TWOB"
tfw_cat --stderr
executeOk_servald id self
executeOk_servald id list
assertStdoutLineCount == 2
assertStdoutGrep --fixed-strings "$SIDA"
assertStdoutGrep --fixed-strings "$TWOA"
assertStdoutGrep --fixed-strings "sid:$SIDA"
assertStdoutGrep --fixed-strings "sid:$TWOA"
}
teardown_KeyringEntryPinServer() {
kill_all_servald_processes
assert_no_servald_processes
report_servald_server
teardown_servald
}
doc_ListTags="Search for unlocked identities by their tags & values"
setup_ListTags() {
setup
executeOk_servald keyring add
extract_stdout_keyvalue ONE sid "$rexp_sid"
keyring_set_tag "$ONE" 'tag1' 'First Value'
executeOk_servald keyring add
extract_stdout_keyvalue TWO sid "$rexp_sid"
keyring_set_tag "$TWO" 'tag1' 'Second Value'
executeOk_servald keyring add
extract_stdout_keyvalue THREE sid "$rexp_sid"
keyring_set_tag "$THREE" 'tag2' 'Third Value'
start_servald_server
}
test_ListTags() {
executeOk_servald id list
assertStdoutLineCount == 3
assertStdoutGrep --fixed-strings "sid:$ONE"
assertStdoutGrep --fixed-strings "sid:$TWO"
assertStdoutGrep --fixed-strings "sid:$THREE"
executeOk_servald id list 'tag1'
assertStdoutLineCount == 2
assertStdoutGrep --fixed-strings "sid:$ONE"
assertStdoutGrep --fixed-strings "sid:$TWO"
executeOk_servald id list 'tag1' 'First Value'
assertStdoutLineCount == 1
assertStdoutGrep --fixed-strings "sid:$ONE"
}
teardown_ListTags() {
teardown_servald
}
doc_Load="Load keyring entries from a keyring dump"