mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-01-18 10:46:23 +00:00
Implement id list command
This commit is contained in:
parent
ff1f1ff093
commit
0b404b0260
121
commandline.c
121
commandline.c
@ -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,
|
||||
|
@ -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)
|
||||
|
19
mdp_client.h
19
mdp_client.h
@ -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{
|
||||
|
@ -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");
|
||||
|
105
tests/keyring
105
tests/keyring
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user