diff --git a/client.c b/client.c index 7d56996b..4efda05b 100644 --- a/client.c +++ b/client.c @@ -485,6 +485,7 @@ int writeItem(char *sid,int var_id,int instance,unsigned char *value, case ACTION_CREATEHLR: printf("ERROR:You cant respond with CREATEHLR\n"); break; case ACTION_PAD: /* ignore it */ break; case ACTION_EOT: /* ignore it */ break; + case ACTION_RECVTTL: /* ignore it */ break; default: printf("ERROR:Unexpected response code 0x%02x\n",r->code); } fflush(stdout); @@ -821,6 +822,7 @@ int requestItem(char *did,char *sid,char *item,int instance, case ACTION_CREATEHLR: printf("ERROR:You cant respond with CREATEHLR\n"); break; case ACTION_PAD: /* ignore it */ break; case ACTION_EOT: /* ignore it */ break; + case ACTION_RECVTTL: /* ignore it */ break; default: printf("ERROR:Unexpected response code 0x%02x\n",r->code); } fflush(stdout); diff --git a/dataformats.c b/dataformats.c index 68bdb43c..80f6e2c9 100644 --- a/dataformats.c +++ b/dataformats.c @@ -139,8 +139,8 @@ int packetGetID(unsigned char *packet,int len,char *did,char *sid) return 0; break; default: /* no idea */ - break; return setReason("Unknown ID key"); + break; } return setReason("Impossible event #1 just occurred"); diff --git a/keyring.c b/keyring.c index dc4a3382..d1202f5c 100644 --- a/keyring.c +++ b/keyring.c @@ -996,86 +996,87 @@ int keyring_set_did(keyring_identity *id,char *did) int keyring_find_did(keyring_file *k,int *cn,int *in,int *kp,char *did) { - if (!k) return 0; + if (keyring_sanitise_position(k,cn,in,kp)) return 0; - while ((*cn)context_count) { - while (((*cn)context_count)&&((*in)>=k->contexts[*cn]->identity_count)) { - (*cn)++; (*in)=0; - } - if ((*cn)>=k->context_count) return 0; - - for(*kp=0;*kpcontexts[*cn]->identities[*in]->keypair_count;(*kp)++) + while (1) { + /* we know we have a sane position, so see if it is interesting */ + + if (k->contexts[*cn]->identities[*in]->keypairs[*kp]->type==KEYTYPE_DID) { - if (k->contexts[*cn]->identities[*in]->keypairs[*kp]->type==KEYTYPE_DID) + /* Compare DIDs */ + if ((!did[0])||(!strcasecmp(did,(char *)k->contexts[*cn]->identities[*in] + ->keypairs[*kp]->private_key))) { - /* Compare DIDs */ - if (!strcasecmp(did,(char *)k->contexts[*cn]->identities[*in] - ->keypairs[*kp]->private_key)) - { - /* match */ - return 1; - } + /* match */ + return 1; } } - - /* See if there is still somewhere to search */ - (*in)++; - if ((*in)>=k->contexts[*cn]->identity_count) { - (*cn)++; (*in)=0; - } + + (*kp)++; + if (keyring_sanitise_position(k,cn,in,kp)) return 0; } + return 0; } int keyring_next_identity(keyring_file *k,int *cn,int *in,int *kp) { - if (!k) return 0; + if (keyring_sanitise_position(k,cn,in,kp)) return 0; - while ((*cn)context_count) { - while (((*cn)context_count)&&((*in)>=k->contexts[*cn]->identity_count)) { - (*cn)++; (*in)=0; - } - if ((*cn)>=k->context_count) return 0; + while(1) { + if (k->contexts[*cn]->identities[*in]->keypairs[*kp]->type==KEYTYPE_CRYPTOBOX) + return 1; - for((*kp)=0;*kpcontexts[*cn]->identities[*in]->keypair_count;(*kp)++) - if (k->contexts[*cn]->identities[*in]->keypairs[*kp]->type==KEYTYPE_CRYPTOBOX) - return 1; - - (*in)++; + (*kp)++; + if (keyring_sanitise_position(k,cn,in,kp)) return 0; } return 0; } +int keyring_sanitise_position(keyring_file *k,int *cn,int *in,int *kp) +{ + if (!k) return 1; + /* Sanity check passed in position */ + if ((*cn)>=keyring->context_count) return 1; + if ((*in)>=keyring->contexts[*cn]->identity_count) + { + (*in)=0; (*cn)++; + if ((*cn)>=keyring->context_count) return 1; + } + if ((*kp)>=keyring->contexts[*cn]->identities[*in]->keypair_count) + { + *kp=0; (*in)++; + if ((*in)>=keyring->contexts[*cn]->identity_count) + { + (*in)=0; (*cn)++; + if ((*cn)>=keyring->context_count) return 1; + } + } + return 0; +} + + int keyring_find_sid(keyring_file *k,int *cn,int *in,int *kp,unsigned char *sid) { - if (!k) return 0; + if (keyring_sanitise_position(k,cn,in,kp)) return 0; - while ((*cn)context_count) { - while (((*cn)context_count)&&((*in)>=k->contexts[*cn]->identity_count)) { - (*cn)++; (*in)=0; - } - if ((*cn)>=k->context_count) return 0; + while (1) { + /* we know we have a sane position, so see if it is interesting */ - for((*kp)=0;*kpcontexts[*cn]->identities[*in]->keypair_count;(*kp)++) + if (k->contexts[*cn]->identities[*in]->keypairs[*kp]->type==KEYTYPE_CRYPTOBOX) { - if (k->contexts[*cn]->identities[*in]->keypairs[*kp]->type==KEYTYPE_CRYPTOBOX) + /* Compare SIDs */ + if (!bcmp(sid,(char *)k->contexts[*cn]->identities[*in] + ->keypairs[*kp]->public_key,SID_SIZE)) { - /* Compare SIDs */ - if (!bcmp(sid,(char *)k->contexts[*cn]->identities[*in] - ->keypairs[*kp]->public_key,SID_SIZE)) - { - /* match */ - return 1; - } + /* match */ + return 1; } } - - /* See if there is still somewhere to search */ - (*in)++; - if ((*in)>=k->contexts[*cn]->identity_count) { - (*cn)++; (*in)=0; - } + (*kp)++; + if (keyring_sanitise_position(k,cn,in,kp)) return 0; } + return 0; } diff --git a/serval.h b/serval.h index 9ac3b3e1..5dd734ae 100644 --- a/serval.h +++ b/serval.h @@ -240,6 +240,7 @@ keyring_file *keyring_open_with_pins(char *pinlist); int keyring_enter_pin(keyring_file *k,char *pin); int keyring_enter_pins(keyring_file *k,char *pinlist); int keyring_set_did(keyring_identity *id,char *did); +int keyring_sanitise_position(keyring_file *k,int *cn,int *in,int *kp); int keyring_next_identity(keyring_file *k,int *cn,int *in,int *kp); int keyring_find_did(keyring_file *k,int *cn,int *in,int *kp,char *did); int keyring_find_sid(keyring_file *k,int *cn,int *in,int *kp,unsigned char *sid); diff --git a/server.c b/server.c index 271c0676..42e41808 100644 --- a/server.c +++ b/server.c @@ -61,9 +61,11 @@ int recvwithttl(int sock,unsigned char *buffer,int bufferlen,int *ttl, int len = recvmsg(sock,&msg,0); - if (debug&DEBUG_PACKETXFER) + if (debug&DEBUG_PACKETXFER) { fprintf(stderr,"recvmsg returned %d bytes (flags=%d,msg_controllen=%d)\n", len,msg.msg_flags,msg.msg_controllen); + dump("received data",buffer,len); + } struct cmsghdr *cmsg; if (len>0) @@ -254,6 +256,7 @@ int processRequest(unsigned char *packet,int len, int var_id=packet[pofs]; int instance=-1; if (var_id&0x80) instance=packet[++pofs]; + if (instance==0xff) instance=-1; pofs++; int offset=(packet[pofs]<<8)+packet[pofs+1]; pofs+=2; keyring_identity *responding_id=NULL; @@ -285,17 +288,19 @@ int processRequest(unsigned char *packet,int len, int count=0; while(cncontext_count) { found=0; - if (sid) { + if (sid&&sid[0]) { unsigned char packedSid[SID_SIZE]; stowSid(packedSid,0,sid); found=keyring_find_sid(keyring,&cn,&in,&kp,packedSid); } else { found=keyring_find_did(keyring,&cn,&in,&kp,did); + printf("found=%d, instance=%d\n",found,instance); } struct response r; if (found&&(instance==-1||instance==count)) { + printf("preparing response\n"); /* We have a matching identity/DID, now see what variable they want. VAR_DIDS and VAR_LOCATIONS are the only ones we support @@ -319,7 +324,7 @@ int processRequest(unsigned char *packet,int len, packet, and only dispatch it when we are about to produce another. Then at the end of the loop, if we have a packet waiting we simply mark that with with DONE, and everything - falls into place. */ + falls into place. */ if (sendDone>0) /* Send previous packet */ respondSimple(responding_id,ACTION_DATA,data,dlen, @@ -336,8 +341,30 @@ int processRequest(unsigned char *packet,int len, sendDone++; count++; - if (sid) in++; else kp++; } + + /* look for next record. + Here the placing of DONE at the end of the response stream + becomes challenging, as we may be responding as multiple + identities. This means we have to DONE after each identity. */ + int lastin=in,lastcn=cn; + kp++; + keyring_sanitise_position(keyring,&cn,&in,&kp); + if (lastin!=in||lastcn!=cn) { + /* moved off last identity, so send waiting packet if there is + one. */ + if (sendDone) + { + data[dlen++]=ACTION_DONE; + data[dlen++]=sendDone&0xff; + respondSimple(responding_id,ACTION_DATA,data,dlen, + transaction_id, + recvttl,sender,CRYPT_CIPHERED|CRYPT_SIGNED); + } + sendDone=0; + + } + } }