Implement id list command

This commit is contained in:
Jeremy Lakeman 2013-10-24 12:31:35 +10:30
parent ff1f1ff093
commit 0b404b0260
5 changed files with 237 additions and 68 deletions

View File

@ -2097,6 +2097,24 @@ static int app_keyring_set_tag(const struct cli_parsed *parsed, struct cli_conte
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;
@ -2111,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;
@ -2124,50 +2142,39 @@ 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;
break;
}
}
end:
mdp_close(mdp_sock);
@ -2184,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;
@ -2739,6 +2808,8 @@ struct cli_schema command_line_options[]={
"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

@ -1496,7 +1496,7 @@ int keyring_find_did(const keyring_file *k, int *cn, int *in, int *kp, const cha
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-1;i++){
for (i=0;i<packed_len;i++){
if (packed[i]==0){
*name = (const char*)packed;
if (value)

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

@ -1036,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) {
@ -1049,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;
}
@ -1068,6 +1118,12 @@ static void mdp_poll2(struct sched_ent *alarm)
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

@ -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
@ -71,24 +77,25 @@ test_DidName() {
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"
executeOk_servald keyring set tag "$SID" 'tag1' 'First Value'
assertStdoutGrep --matches=1 "^sid:$SID\$"
assertStdoutGrep --matches=1 "^tag1:First Value\$"
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 "^sid:$SID\$"
assertStdoutGrep --matches=1 "^tag1:First Value\$"
assertStdoutGrep --matches=1 "^tag2:Second Value\$"
assertStdoutLineCount '==' 3
executeOk_servald keyring set tag "$SID" 'tag1' 'Third Value'
assertStdoutGrep --matches=1 "^sid:$SID\$"
assertStdoutGrep --matches=1 "^tag1:Third Value\$"
keyring_set_tag "$SID" 'tag1' 'Third Value'
assertStdoutGrep --matches=1 "^tag2:Second Value\$"
assertStdoutLineCount '==' 3
executeOk_servald keyring dump --secret
@ -180,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"
@ -200,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"
@ -220,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"
@ -240,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"
@ -263,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"