fixed bug in RFS size patching.

A lot of debug output tweaks to track the problem down.
This commit is contained in:
gardners 2012-04-16 06:06:43 +09:30
parent caab3078e5
commit e7e8b2d630
11 changed files with 199 additions and 39 deletions

1
dna.c
View File

@ -484,6 +484,7 @@ int setVerbosity(char *optarg) {
if (strstr(optarg,"simulation")) debug|=DEBUG_SIMULATION;
if (strstr(optarg,"dnavars")) debug|=DEBUG_DNAVARS;
if (strstr(optarg,"packetformats")) debug|=DEBUG_PACKETFORMATS;
if (strstr(optarg,"packetconstruction")) debug|=DEBUG_PACKETCONSTRUCTION;
if (strstr(optarg,"gateway")) debug|=DEBUG_GATEWAY;
if (strstr(optarg,"hlr")) debug|=DEBUG_HLR;
if (strstr(optarg,"sockio")) debug|=DEBUG_IO;

View File

@ -1055,7 +1055,8 @@ int keyring_sanitise_position(keyring_file *k,int *cn,int *in,int *kp)
return 0;
}
unsigned char *keyring_find_sas_private(keyring_file *k,unsigned char *sid)
unsigned char *keyring_find_sas_private(keyring_file *k,unsigned char *sid,
unsigned char **sas_public)
{
int cn=0,in=0,kp=0;
@ -1064,7 +1065,12 @@ unsigned char *keyring_find_sas_private(keyring_file *k,unsigned char *sid)
for(kp=0;kp<k->contexts[cn]->identities[in]->keypair_count;kp++)
if (k->contexts[cn]->identities[in]->keypairs[kp]->type==KEYTYPE_CRYPTOSIGN)
return k->contexts[cn]->identities[in]->keypairs[kp]->private_key;
{
if (sas_public)
*sas_public=
k->contexts[cn]->identities[in]->keypairs[kp]->public_key;
return k->contexts[cn]->identities[in]->keypairs[kp]->private_key;
}
WHYRETNULL("Identity lacks SAS");
}
@ -1087,17 +1093,87 @@ int keyring_mapping_request(keyring_file *k,overlay_mdp_frame *req)
/* The authcryption of the MDP frame proves that the SAS key is owned by the
owner of the SID, and so is absolutely compulsory. */
if (req->packetTypeAndFlags&MDP_NOCRYPT)
if (req->packetTypeAndFlags&(MDP_NOCRYPT|MDP_NOSIGN))
return WHY("mapping requests must be performed under authcryption");
if (req->out.payload_length==1) {
/* It's a request, so find the SAS for the SID the request was addressed to,
use that to sign that SID, and then return it in an authcrypted frame. */
WHY("Not implemented");
unsigned char *sas_public=NULL;
unsigned char *sas_priv
=keyring_find_sas_private(keyring,req->out.dst.sid,&sas_public);
if ((!sas_priv)||(!sas_public)) return WHY("I don't have that SAS key");
unsigned long long slen;
/* type of key being verified */
req->out.payload[0]=KEYTYPE_CRYPTOSIGN;
/* the public key itself */
int sigbytes=crypto_sign_edwards25519sha512batch_BYTES;
int keybytes=crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES;
bcopy(sas_public,&req->out.payload[1],keybytes);
/* and a signature of the SID using the SAS key, to prove possession of
the key. Possession of the SID has already been established by the
decrypting of the surrounding MDP packet.
XXX - We could chop the SID out of the middle of the signed block here,
just as we do for signed MDP packets to save 32 bytes. We won't worry
about doing this, however, as the mapping process is only once per session,
not once per packet. Unless I get excited enough to do it, that is.
*/
if (crypto_sign_edwards25519sha512batch
(&req->out.payload[1+keybytes],&slen,req->out.dst.sid,SID_SIZE,sas_priv))
return WHY("crypto_sign() failed");
/* chop the SID out of the signature, since it can be reinserted on reception */
bcopy(&req->out.payload[1+keybytes+32+SID_SIZE],
&req->out.payload[1+keybytes+32],sigbytes-32);
slen-=SID_SIZE;
/* and record the full length of this */
req->out.payload_length
=1
+crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES
+slen;
overlay_mdp_swap_src_dst(req);
#warning disabled crypt and sign for debugging.
req->packetTypeAndFlags=MDP_TX; /* crypt and sign */
WHY("Sent SID:SAS mapping mutual-signature");
printf("%d byte reply is from %s:%u\n to %s:%u\n",
req->out.payload_length,
overlay_render_sid(req->out.src.sid),req->out.src.port,
overlay_render_sid(req->out.dst.sid),req->out.dst.port);
return overlay_mdp_dispatch(req,1,NULL,0);
} else {
/* It's probably a response. */
switch(req->out.payload[0]) {
case KEYTYPE_CRYPTOSIGN:
{
if (req->out.payload_length<
(1
+crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES))
return WHY("Truncated key mapping announcement?");
unsigned char plain[req->out.payload_length];
unsigned long long plain_len=0;
unsigned char *sas_public=&req->out.payload[1];
unsigned char *compactsignature
=&req->out.payload[1+crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES];
/* reconstitute signed SID for verification */
int siglen=SID_SIZE+crypto_sign_edwards25519sha512batch_BYTES;
unsigned char signature[siglen];
bcopy(&compactsignature[0],&signature[0],32);
bcopy(&req->out.src.sid[0],&signature[32],SID_SIZE);
bcopy(&compactsignature[32],&signature[32+SID_SIZE],32);
int r=crypto_sign_edwards25519sha512batch_open(plain,&plain_len,
signature,siglen,
sas_public);
if (r)
return
WHY("Verification of signed SID in key mapping assertion failed");
/* These next two tests should never be able to fail, but let's just
check anyway. */
if (plain_len!=SID_SIZE)
return WHY("key mapping signed block is wrong length");
if (bcmp(plain,req->out.src.sid,SID_SIZE))
return WHY("key mapping signed block is for wrong SID");
WHY("Key mapping looks valid");
}
WHY("Not implemented");
break;
default:
@ -1126,7 +1202,7 @@ unsigned char *keyring_find_sas_public(keyring_file *k,unsigned char *sid)
for(i=0;i<sid_sas_mapping_count;i++)
{
if (bcmp(sid,sid_sas_mappings[i].sid,SID_SIZE)) continue;
if (sid_sas_mappings[i].validP) return sid_sas_mappings[i].sas_public;
if (sid_sas_mappings[i].validP) return sid_sas_mappings[i].sas_public;
/* Don't flood the network with mapping requests */
if ((now-sid_sas_mappings[i].last_request_time_in_ms)<1000) return NULL;
/* we can request again, so fall out to where we do that.

View File

@ -225,7 +225,7 @@ int overlay_frame_process(int interface,overlay_frame *f)
if (f->source_address_status==OA_RESOLVED&&overlay_address_is_local(f->source))
return WHY("Dropping frame claiming to come from myself.");
if (debug&DEBUG_OVERLAYFRAMES) fprintf(stderr,">>> Received frame (type=%02x)\n",f->type);
if (debug&DEBUG_OVERLAYFRAMES) fprintf(stderr,">>> Received frame (type=%02x, bytes=%d)\n",f->type,f->payload?f->payload->length:-1);
/* First order of business is whether the nexthop address has been resolved.
If not, we need to think about asking for it to be resolved.

View File

@ -228,6 +228,11 @@ int overlay_abbreviate_append_address(overlay_buffer *b,unsigned char *a)
int count=0;
ob_makespace(b,SID_SIZE+3);
int r=overlay_abbreviate_address(a,&b->bytes[b->length],&count);
if (DEBUG_PACKETCONSTRUCTION) {
fprintf(stderr,"address %s abbreviates as shown in this ",
overlay_render_sid(a));
dump(NULL,&b->bytes[b->length],count);
}
if (r) return r;
b->length+=count;
return 0;

View File

@ -277,7 +277,7 @@ int ob_indel_space(overlay_buffer *b,int offset,int shift)
if (ob_makespace(b,-shift)) return -1;
bcopy(&b->bytes[offset],&b->bytes[offset+shift],b->length-(offset+shift));
} else if (shift<0) { /* free up space */
bcopy(&b->bytes[offset],&b->bytes[offset-shift],b->length-(offset-shift));
bcopy(&b->bytes[offset],&b->bytes[offset+shift],b->length-(offset-shift));
}
b->length+=shift;
return 0;
@ -291,10 +291,31 @@ int ob_patch_rfs(overlay_buffer *b,int l)
/* Adjust size of field */
int new_size=rfs_length(l);
int shift=new_size-b->var_length_bytes;
if (ob_indel_space(b,b->var_length_offset,shift)) return -1;
if (shift) {
if (debug&DEBUG_PACKETCONSTRUCTION) {
fprintf(stderr,"Patching RFS for rfs_size=%d (was %d), so indel %d btyes\n",
new_size,b->var_length_bytes,shift);
dump("before indel",
&b->bytes[b->var_length_offset],
b->length-b->var_length_offset);
}
if (ob_indel_space(b,b->var_length_offset,shift)) return -1;
if (debug&DEBUG_PACKETCONSTRUCTION) {
dump("after indel",
&b->bytes[b->var_length_offset],
b->length-b->var_length_offset);
}
}
if (rfs_encode(l,&b->bytes[b->var_length_offset])) return -1;
if (debug&DEBUG_PACKETCONSTRUCTION) {
dump("after patch",
&b->bytes[b->var_length_offset],
b->length-b->var_length_offset);
}
return 0;
}

View File

@ -769,6 +769,9 @@ int overlay_tick_interface(int i, long long now)
if (!(debug&DEBUG_DISABLERHIZOME))
overlay_rhizome_add_advertisements(i,e);
if (debug&DEBUG_PACKETCONSTRUCTION)
dump("assembled packet",&e->bytes[0],e->length);
/* Now send the frame. This takes the form of a special DNA packet with a different
service code, which we setup earlier. */
if (debug&DEBUG_OVERLAYINTERFACES)

View File

@ -364,6 +364,15 @@ int overlay_saw_mdp_containing_frame(int interface,overlay_frame *f,long long no
return overlay_saw_mdp_frame(interface,&mdp,now);
}
int overlay_mdp_swap_src_dst(overlay_mdp_frame *mdp)
{
sockaddr_mdp temp;
bcopy(&mdp->out.dst,&temp,sizeof(sockaddr_mdp));
bcopy(&mdp->out.src,&mdp->out.dst,sizeof(sockaddr_mdp));
bcopy(&temp,&mdp->out.src,sizeof(sockaddr_mdp));
return 0;
}
int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now)
{
int i;
@ -434,17 +443,14 @@ int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now)
/* Either respond with the appropriate SAS, or record this one if it
verfies out okay. */
WHY("key mapping request");
return keyring_mapping_request(keyring,&mdp);
return keyring_mapping_request(keyring,mdp);
case MDP_PORT_ECHO: /* well known ECHO port for TCP/UDP and now MDP */
{
/* Echo is easy: we swap the sender and receiver addresses (and thus port
numbers) and send the frame back. */
/* Swap addresses */
sockaddr_mdp temp;
bcopy(&mdp->out.dst,&temp,sizeof(sockaddr_mdp));
bcopy(&mdp->out.src,&mdp->out.dst,sizeof(sockaddr_mdp));
bcopy(&temp,&mdp->out.src,sizeof(sockaddr_mdp));
overlay_mdp_swap_src_dst(mdp);
if (mdp->out.dst.port==7) return WHY("echo loop averted");
/* If the packet was sent to broadcast, then replace broadcast address
@ -502,19 +508,6 @@ int overlay_mdp_sanitytest_sourceaddr(sockaddr_mdp *src,int userGeneratedFrameP,
return WHY("Packet had broadcast address as source address");
}
/* Check for build-in port listeners */
if (!userGeneratedFrameP)
if (overlay_address_is_local(src->sid)) {
switch(src->port) {
case MDP_PORT_ECHO:
case MDP_PORT_KEYMAPREQUEST:
/* locally hard-wired port */
return 0;
default:
break;
}
}
/* Now make sure that source address is in the list of bound addresses,
and that the recvaddr matches. */
int i;
@ -534,8 +527,25 @@ int overlay_mdp_sanitytest_sourceaddr(sockaddr_mdp *src,int userGeneratedFrameP,
}
}
printf("addr=%s port=%d\n",
overlay_render_sid(src->sid),src->port);
/* Check for build-in port listeners */
if (overlay_address_is_local(src->sid)) {
switch(src->port) {
case MDP_PORT_ECHO:
/* we don't allow user/network generated packets claiming to
be from the echo port, largely to prevent echo:echo connections
and the resulting denial of service from triggering endless pongs. */
if (!userGeneratedFrameP) return 0;
break;
/* other built-in listeners */
case MDP_PORT_KEYMAPREQUEST:
return 0;
default:
break;
}
}
printf("addr=%s port=%u (0x%x)\n",
overlay_render_sid(src->sid),src->port,src->port);
return WHY("No such socket binding:unix domain socket tuple exists -- someone might be trying to spoof someone else's connection");
}
@ -697,7 +707,7 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
+crypto_sign_edwards25519sha512batch_BYTES
+mdp->out.payload_length);
{
unsigned char *key=keyring_find_sas_private(keyring,mdp->out.src.sid);
unsigned char *key=keyring_find_sas_private(keyring,mdp->out.src.sid,NULL);
if (!key) { op_free(frame); return WHY("could not find signing key"); }
/* Build plain-text that includes header and hash it so that

View File

@ -178,6 +178,11 @@ int packetOkOverlay(int interface,unsigned char *packet,int len,
int alen=0;
int offset=ofs;
f.nexthop_address_status=overlay_abbreviate_expand_address(interface,packet,&offset,f.nexthop,&alen);
if (debug&DEBUG_PACKETFORMATS) {
if (f.nexthop_address_status==OA_RESOLVED)
fprintf(stderr,"next hop address is %s\n",
overlay_render_sid(f.nexthop));
}
/* Now just make the rest of the frame available via the received frame structure, as the
frame may not be for us, so there is no point wasting time and energy if we don't have
@ -198,7 +203,7 @@ int packetOkOverlay(int interface,unsigned char *packet,int len,
/* Skip the rest of the bytes in this frame so that we can examine the next one in this
ensemble */
if (debug&DEBUG_PACKETFORMATS) fprintf(stderr,"ofs=%d, f.rfs=%d, len=%d\n",ofs,f.rfs,len);
if (debug&DEBUG_PACKETFORMATS) fprintf(stderr,"next ofs=%d, f.rfs=%d, len=%d\n",ofs,f.rfs,len);
ofs+=f.rfs;
}

View File

@ -74,6 +74,9 @@ int overlay_frame_package_fmt1(overlay_frame *p,overlay_buffer *b)
if (!p) return WHY("p is NULL");
if (!b) return WHY("b is NULL");
if (debug&DEBUG_PACKETCONSTRUCTION)
dump_payload(p,"package_fmt1 stuffing into packet");
/* Build header */
int fail=0;
@ -128,6 +131,8 @@ int overlay_frame_package_fmt1(overlay_frame *p,overlay_buffer *b)
*/
if (!fail) {
int max_len=((SID_SIZE+3)*3+headers->length+p->payload->length);
if (debug&DEBUG_PACKETCONSTRUCTION)
fprintf(stderr,"Appending RFS for max_len=%d\n",max_len);
ob_append_rfs(headers,max_len);
int addrs_start=headers->length;
@ -142,6 +147,8 @@ int overlay_frame_package_fmt1(overlay_frame *p,overlay_buffer *b)
int addrs_len=headers->length-addrs_start;
int actual_len=addrs_len+p->payload->length;
if (debug&DEBUG_PACKETCONSTRUCTION)
fprintf(stderr,"Patching RFS for actual_len=%d\n",actual_len);
ob_patch_rfs(headers,actual_len);
}
@ -204,6 +211,24 @@ int dump_queue(char *msg,int q)
}
return 0;
}
int dump_payload(overlay_frame *p,char *message)
{
fflush(stdout);
fprintf(stderr,
"+++++\nFrame from %s to %s of type 0x%02x %s:\n",
overlay_render_sid(p->source),
overlay_render_sid(p->destination),p->type,
message?message:"");
fprintf(stderr," next hop is %s\n",overlay_render_sid(p->nexthop));
fflush(stderr);
if (p->payload) dump("payload contents",
&p->payload->bytes[0],p->payload->length);
fflush(stdout); fflush(stderr);
fprintf(stderr,"-----\n");
return 0;
}
int overlay_payload_enqueue(int q,overlay_frame *p)
{
/* Add payload p to queue q.
@ -217,6 +242,8 @@ int overlay_payload_enqueue(int q,overlay_frame *p)
if (q<0||q>=OQ_MAX) return WHY("Invalid queue specified");
if (!p) return WHY("Cannot queue NULL");
if (0) dump_payload(p,"queued for delivery");
if (overlay_tx[q].length>=overlay_tx[q].maxLength) return WHY("Queue congested");
if (0) dump_queue("before",q);

View File

@ -943,13 +943,16 @@ int overlay_route_recalc_neighbour_metrics(overlay_neighbour *n,long long now)
}
char ors_out[SID_STRLEN+1];
int ors_rotor=0;
char ors_out[4][SID_STRLEN+1];
char *overlay_render_sid(unsigned char *sid)
{
int zero=0;
extractSid(sid,&zero,ors_out);
ors_out[SID_STRLEN] = '\0';
return ors_out;
ors_rotor++;
ors_rotor&=3;
extractSid(sid,&zero,ors_out[ors_rotor]);
ors_out[ors_rotor][SID_STRLEN] = '\0';
return ors_out[ors_rotor];
}
char *overlay_render_sid_prefix(unsigned char *sid,int l)
@ -958,9 +961,11 @@ char *overlay_render_sid_prefix(unsigned char *sid,int l)
if (l<0) l=0;
if (l>SID_STRLEN) l=SID_STRLEN;
extractSid(sid,&zero,ors_out);
ors_out[l]=0;
return ors_out;
ors_rotor++;
ors_rotor&=3;
extractSid(sid,&zero,ors_out[ors_rotor]);
ors_out[ors_rotor][l]=0;
return ors_out[ors_rotor];
}

View File

@ -244,7 +244,8 @@ 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);
unsigned char *keyring_find_sas_private(keyring_file *k,unsigned char *sid);
unsigned char *keyring_find_sas_private(keyring_file *k,unsigned char *sid,
unsigned char **sas_public);
unsigned char *keyring_find_sas_public(keyring_file *k,unsigned char *sid);
int keyring_commit(keyring_file *k);
@ -1011,6 +1012,7 @@ int overlay_saw_mdp_containing_frame(int interface,overlay_frame *f,long long no
#define DEBUG_RHIZOMESYNC (1<<21)
#define DEBUG_DISABLERHIZOME (1<<22)
#define DEBUG_PACKETTX (1<<23)
#define DEBUG_PACKETCONSTRUCTION (1<<24)
int serval_packetvisualise(FILE *f,char *message,unsigned char *packet,int plen);
@ -1086,7 +1088,7 @@ typedef struct sockaddr_mdp {
unsigned char *keyring_get_nm_bytes(sockaddr_mdp *priv,sockaddr_mdp *pub);
#define MDP_PORT_ECHO 7
#define MDP_PORT_KEYMAPREQUEST 0xf0000001
#define MDP_PORT_KEYMAPREQUEST 0x10000001
#define MDP_TYPE_MASK 0xff
#define MDP_FLAG_MASK 0xff00
@ -1158,6 +1160,7 @@ int overlay_mdp_send(overlay_mdp_frame *mdp,int flags,int timeout_ms);
/* Server-side MDP functions */
int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now);
int overlay_mdp_swap_src_dst(overlay_mdp_frame *mdp);
int overlay_mdp_reply(int sock,struct sockaddr_un *recvaddr,int recvaddrlen,
overlay_mdp_frame *mdpreply);
int overlay_mdp_relevant_bytes(overlay_mdp_frame *mdp);
@ -1167,6 +1170,10 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
int ob_bcopy(overlay_buffer *b,int from, int to, int len);
int ob_setbyte(overlay_buffer *b,int ofs,unsigned char value);
char *overlay_render_sid(unsigned char *sid);
char *overlay_render_sid_prefix(unsigned char *sid,int l);
int dump_payload(overlay_frame *p,char *message);
int urandombytes(unsigned char *x,unsigned long long xlen);
#ifdef MALLOC_PARANOIA