Improve SAS resolution debug messages

This commit is contained in:
Andrew Bettison 2012-08-14 14:06:59 +09:30
parent cd35c5e2ae
commit eec8fb6e95
5 changed files with 70 additions and 75 deletions

View File

@ -51,6 +51,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#define SID_SIZE 32 #define SID_SIZE 32
#define SAS_SIZE 32 // == crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES
#define DID_MINSIZE 5 #define DID_MINSIZE 5
#define DID_MAXSIZE 32 #define DID_MAXSIZE 32
#define SIDDIDFIELD_LEN (SID_SIZE+1) #define SIDDIDFIELD_LEN (SID_SIZE+1)

110
keyring.c
View File

@ -1144,7 +1144,7 @@ unsigned char *keyring_find_sas_private(keyring_file *k,unsigned char *sid,
struct sid_sas_mapping { struct sid_sas_mapping {
unsigned char sid[SID_SIZE]; unsigned char sid[SID_SIZE];
unsigned char sas_public[crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES]; unsigned char sas_public[SAS_SIZE];
time_ms_t last_request_time_in_ms; time_ms_t last_request_time_in_ms;
unsigned char validP; unsigned char validP;
}; };
@ -1153,7 +1153,7 @@ struct sid_sas_mapping {
int sid_sas_mapping_count=0; int sid_sas_mapping_count=0;
struct sid_sas_mapping sid_sas_mappings[MAX_SID_SAS_MAPPINGS]; struct sid_sas_mapping sid_sas_mappings[MAX_SID_SAS_MAPPINGS];
int keyring_mapping_request(keyring_file *k,overlay_mdp_frame *req) int keyring_mapping_request(keyring_file *k, overlay_mdp_frame *req)
{ {
if (!k) return WHY("keyring is null"); if (!k) return WHY("keyring is null");
if (!req) return WHY("req is null"); if (!req) return WHY("req is null");
@ -1167,8 +1167,7 @@ int keyring_mapping_request(keyring_file *k,overlay_mdp_frame *req)
/* It's a request, so find the SAS for the SID the request was addressed to, /* 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. */ use that to sign that SID, and then return it in an authcrypted frame. */
unsigned char *sas_public=NULL; unsigned char *sas_public=NULL;
unsigned char *sas_priv unsigned char *sas_priv =keyring_find_sas_private(keyring,req->out.dst.sid,&sas_public);
=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"); if ((!sas_priv)||(!sas_public)) return WHY("I don't have that SAS key");
unsigned long long slen; unsigned long long slen;
@ -1176,8 +1175,7 @@ int keyring_mapping_request(keyring_file *k,overlay_mdp_frame *req)
req->out.payload[0]=KEYTYPE_CRYPTOSIGN; req->out.payload[0]=KEYTYPE_CRYPTOSIGN;
/* the public key itself */ /* the public key itself */
int sigbytes=crypto_sign_edwards25519sha512batch_BYTES; int sigbytes=crypto_sign_edwards25519sha512batch_BYTES;
int keybytes=crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES; bcopy(sas_public,&req->out.payload[1], SAS_SIZE);
bcopy(sas_public,&req->out.payload[1],keybytes);
/* and a signature of the SID using the SAS key, to prove possession of /* 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 the key. Possession of the SID has already been established by the
decrypting of the surrounding MDP packet. decrypting of the surrounding MDP packet.
@ -1187,43 +1185,37 @@ int keyring_mapping_request(keyring_file *k,overlay_mdp_frame *req)
not once per packet. Unless I get excited enough to do it, that is. not once per packet. Unless I get excited enough to do it, that is.
*/ */
if (crypto_sign_edwards25519sha512batch if (crypto_sign_edwards25519sha512batch
(&req->out.payload[1+keybytes],&slen,req->out.dst.sid,SID_SIZE,sas_priv)) (&req->out.payload[1+SAS_SIZE],&slen,req->out.dst.sid,SID_SIZE,sas_priv))
return WHY("crypto_sign() failed"); return WHY("crypto_sign() failed");
/* chop the SID out of the signature, since it can be reinserted on reception */ /* chop the SID out of the signature, since it can be reinserted on reception */
bcopy(&req->out.payload[1+keybytes+32+SID_SIZE], bcopy(&req->out.payload[1+SAS_SIZE+32+SID_SIZE], &req->out.payload[1+SAS_SIZE+32], sigbytes-32);
&req->out.payload[1+keybytes+32],sigbytes-32);
slen-=SID_SIZE; slen-=SID_SIZE;
/* and record the full length of this */ /* and record the full length of this */
req->out.payload_length req->out.payload_length = 1 + SAS_SIZE + slen;
=1
+crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES
+slen;
overlay_mdp_swap_src_dst(req); overlay_mdp_swap_src_dst(req);
req->packetTypeAndFlags=MDP_TX; /* crypt and sign */ req->packetTypeAndFlags=MDP_TX; /* crypt and sign */
if (debug & DEBUG_KEYRING) { if (debug & DEBUG_KEYRING)
DEBUG("Sent SID:SAS mapping mutual-signature"); DEBUGF("Sending SID:SAS mapping, %d bytes, %s:0x%X -> %s:0x%X",
DEBUGF("%d byte reply from %s:%u to %s:%u",
req->out.payload_length, req->out.payload_length,
alloca_tohex_sid(req->out.src.sid),req->out.src.port, alloca_tohex_sid(req->out.src.sid), req->out.src.port,
alloca_tohex_sid(req->out.dst.sid),req->out.dst.port); alloca_tohex_sid(req->out.dst.sid), req->out.dst.port
} );
return overlay_mdp_dispatch(req,1,NULL,0); return overlay_mdp_dispatch(req,1,NULL,0);
} else { } else {
/* It's probably a response. */ /* It's probably a response. */
if (debug & DEBUG_KEYRING) if (debug & DEBUG_KEYRING)
DEBUGF("Received %d byte key mapping response", req->out.payload_length); DEBUGF("Received SID:SAS mapping, %d bytes", req->out.payload_length);
switch(req->out.payload[0]) { unsigned keytype = req->out.payload[0];
switch (keytype) {
case KEYTYPE_CRYPTOSIGN: case KEYTYPE_CRYPTOSIGN:
{ {
if (req->out.payload_length< if (req->out.payload_length < 1 + SAS_SIZE)
(1
+crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES))
return WHY("Truncated key mapping announcement?"); return WHY("Truncated key mapping announcement?");
unsigned char plain[req->out.payload_length]; unsigned char plain[req->out.payload_length];
unsigned long long plain_len=0; unsigned long long plain_len=0;
unsigned char *sas_public=&req->out.payload[1]; unsigned char *sas_public=&req->out.payload[1];
unsigned char *compactsignature unsigned char *compactsignature = &req->out.payload[1+SAS_SIZE];
=&req->out.payload[1+crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES];
/* reconstitute signed SID for verification */ /* reconstitute signed SID for verification */
int siglen=SID_SIZE+crypto_sign_edwards25519sha512batch_BYTES; int siglen=SID_SIZE+crypto_sign_edwards25519sha512batch_BYTES;
unsigned char signature[siglen]; unsigned char signature[siglen];
@ -1235,42 +1227,40 @@ int keyring_mapping_request(keyring_file *k,overlay_mdp_frame *req)
signature,siglen, signature,siglen,
sas_public); sas_public);
if (r) if (r)
return WHY("Verification of signed SID in key mapping assertion failed"); return WHY("SID:SAS mapping verification signature does not verify");
/* These next two tests should never be able to fail, but let's just /* These next two tests should never be able to fail, but let's just check anyway. */
check anyway. */ if (plain_len != SID_SIZE)
if (plain_len!=SID_SIZE) return WHY("SID:SAS mapping signed block is wrong length");
return WHY("key mapping signed block is wrong length"); if (memcmp(plain, req->out.src.sid, SID_SIZE) != 0)
if (memcmp(plain,req->out.src.sid,SID_SIZE)) return WHY("SID:SAS mapping signed block is for wrong SID");
return WHY("key mapping signed block is for wrong SID");
if (debug & DEBUG_KEYRING)
DEBUG("Key mapping looks valid");
/* work out where to put it */ /* work out where to put it */
int i; int i;
for(i=0;i<sid_sas_mapping_count;i++) for (i = 0; i < sid_sas_mapping_count; ++i)
if (!memcmp(req->out.src.sid,sid_sas_mappings[i].sid,SID_SIZE)) break; if (memcmp(req->out.src.sid, sid_sas_mappings[i].sid, SID_SIZE) == 0)
break;
if (i>=MAX_SID_SAS_MAPPINGS) i=random()%MAX_SID_SAS_MAPPINGS; if (i >= MAX_SID_SAS_MAPPINGS)
if (i>=sid_sas_mapping_count) sid_sas_mapping_count=i+1; i = random() % MAX_SID_SAS_MAPPINGS;
else if (i >= sid_sas_mapping_count)
i = sid_sas_mapping_count++;
/* now put it */ /* now put it */
bcopy(&req->out.src.sid,&sid_sas_mappings[i].sid[0],SID_SIZE); bcopy(&req->out.src.sid, &sid_sas_mappings[i].sid[0], SID_SIZE);
bcopy(sas_public,&sid_sas_mappings[i].sas_public[0], bcopy(sas_public, &sid_sas_mappings[i].sas_public[0], SAS_SIZE);
crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES);
if (debug & DEBUG_KEYRING) if (debug & DEBUG_KEYRING)
DEBUGF("Mapping #%d (count=%d) SID=%s to SAS=%s*\n",i, DEBUGF("Stored SID:SAS mapping #%d of %d, SID=%s to SAS=%s",
sid_sas_mapping_count, i, sid_sas_mapping_count,
alloca_tohex_sid(sid_sas_mappings[i].sid), alloca_tohex_sid(sid_sas_mappings[i].sid),
alloca_tohex_sid(sid_sas_mappings[i].sas_public)); alloca_tohex_sas(sid_sas_mappings[i].sas_public)
);
sid_sas_mappings[i].validP=1; sid_sas_mappings[i].validP=1;
sid_sas_mappings[i].last_request_time_in_ms = -1; sid_sas_mappings[i].last_request_time_in_ms = -1;
if (debug & DEBUG_KEYRING)
DEBUG("Stored mapping");
return 0; return 0;
} }
break; break;
default: default:
WARN("Key mapping response for unknown key type. Oh well."); WARNF("Ignoring SID:SAS mapping with unsupported key type %u", keytype);
break;
} }
} }
return WHY("Not implemented"); return WHY("Not implemented");
@ -1298,19 +1288,21 @@ unsigned char *keyring_find_sas_public(keyring_file *k,unsigned char *sid)
if (memcmp(sid,sid_sas_mappings[i].sid,SID_SIZE)) continue; if (memcmp(sid,sid_sas_mappings[i].sid,SID_SIZE)) continue;
if (sid_sas_mappings[i].validP) { if (sid_sas_mappings[i].validP) {
if (debug & DEBUG_KEYRING) if (debug & DEBUG_KEYRING)
DEBUGF("Found SAS public entry for %s*", alloca_tohex(sid, 7)); DEBUGF("Found SAS for SID=%s", alloca_tohex_sid(sid));
RETURN(sid_sas_mappings[i].sas_public); RETURN(sid_sas_mappings[i].sas_public);
} }
/* Don't flood the network with mapping requests */ /* Don't flood the network with mapping requests */
if (sid_sas_mappings[i].last_request_time_in_ms != -1 && now < sid_sas_mappings[i].last_request_time_in_ms + 1000) if (sid_sas_mappings[i].last_request_time_in_ms != -1 && now < sid_sas_mappings[i].last_request_time_in_ms + 1000) {
RETURN(WHYNULL("Too soon to ask for SAS mapping again.")); INFO("Too soon to ask for SAS mapping again");
RETURN(NULL);
}
/* we can request again, so fall out to where we do that. /* we can request again, so fall out to where we do that.
i is set to this mapping, so the request process will update this i is set to this mapping, so the request process will update this
record. */ record. */
break; break;
} }
if (debug & DEBUG_KEYRING) if (debug & DEBUG_KEYRING)
DEBUGF("Asking for SAS mapping for %s", alloca_tohex_sid(sid)); DEBUGF("Requesting SAS mapping for SID=%s", alloca_tohex_sid(sid));
/* allocate mapping slot or replace one at random, depending on how full things /* allocate mapping slot or replace one at random, depending on how full things
are */ are */
@ -1320,9 +1312,8 @@ unsigned char *keyring_find_sas_public(keyring_file *k,unsigned char *sid)
} }
/* pre-populate mapping slot */ /* pre-populate mapping slot */
bcopy(&sid[0],&sid_sas_mappings[i].sid[0],SID_SIZE); bcopy(&sid[0], &sid_sas_mappings[i].sid[0], SID_SIZE);
bzero(&sid_sas_mappings[i].sas_public, bzero(&sid_sas_mappings[i].sas_public, SAS_SIZE);
crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES);
sid_sas_mappings[i].validP=0; sid_sas_mappings[i].validP=0;
sid_sas_mappings[i].last_request_time_in_ms = now; sid_sas_mappings[i].last_request_time_in_ms = now;
@ -1341,9 +1332,8 @@ unsigned char *keyring_find_sas_public(keyring_file *k,unsigned char *sid)
else { RETURN(WHYNULL("couldn't request SAS (I don't know who I am)")); } else { RETURN(WHYNULL("couldn't request SAS (I don't know who I am)")); }
mdp.out.payload_length=1; mdp.out.payload_length=1;
mdp.out.payload[0]=KEYTYPE_CRYPTOSIGN; mdp.out.payload[0]=KEYTYPE_CRYPTOSIGN;
if (overlay_mdp_dispatch(&mdp,0 /* system generated */, if (overlay_mdp_dispatch(&mdp, 0 /* system generated */, NULL, 0))
NULL,0)) RETURN(WHYNULL("Failed to send SAS resolution request"));
{ RETURN(WHYNULL("Failed to send SAS resolution request")); }
if (debug & DEBUG_KEYRING) if (debug & DEBUG_KEYRING)
DEBUGF("Dispatched SAS resolution request"); DEBUGF("Dispatched SAS resolution request");
RETURN(NULL); RETURN(NULL);

View File

@ -263,8 +263,7 @@ int overlay_mdp_process_bind_request(int sock,overlay_mdp_frame *mdp,
return overlay_mdp_reply_ok(sock,recvaddr,recvaddrlen,"Port bound"); return overlay_mdp_reply_ok(sock,recvaddr,recvaddrlen,"Port bound");
} }
unsigned char *overlay_mdp_decrypt(overlay_frame *f,overlay_mdp_frame *mdp, unsigned char *overlay_mdp_decrypt(overlay_frame *f, overlay_mdp_frame *mdp, int *len)
int *len)
{ {
IN(); IN();
@ -277,19 +276,20 @@ unsigned char *overlay_mdp_decrypt(overlay_frame *f,overlay_mdp_frame *mdp,
/* get payload */ /* get payload */
b=&f->payload->bytes[0]; b=&f->payload->bytes[0];
*len=f->payload->length; *len=f->payload->length;
mdp->packetTypeAndFlags|=MDP_NOCRYPT|MDP_NOSIGN; break; mdp->packetTypeAndFlags|=MDP_NOCRYPT|MDP_NOSIGN;
break;
case OF_CRYPTO_CIPHERED: case OF_CRYPTO_CIPHERED:
WHY("decryption not implemented"); RETURN(WHYNULL("decryption not implemented"));
RETURN(NULL); mdp->packetTypeAndFlags|=MDP_NOSIGN;
mdp->packetTypeAndFlags|=MDP_NOSIGN; break; break;
case OF_CRYPTO_SIGNED: case OF_CRYPTO_SIGNED:
{ {
/* This call below will dispatch the request for the SAS if we don't /* This call below will dispatch the request for the SAS if we don't
already have it. In the meantime, we just drop the frame if the SAS already have it. In the meantime, we just drop the frame if the SAS
is not available. */ is not available. */
unsigned char *key=keyring_find_sas_public(keyring,mdp->out.src.sid); unsigned char *key = keyring_find_sas_public(keyring,mdp->out.src.sid);
if (!key) { WHY("SAS key not currently on record, so cannot verify"); if (!key)
RETURN(NULL); } RETURN(WHYNULL("SAS key not currently on record, cannot verify"));
/* get payload and following compacted signature */ /* get payload and following compacted signature */
b=&f->payload->bytes[0]; b=&f->payload->bytes[0];
@ -483,8 +483,9 @@ int overlay_saw_mdp_frame(overlay_mdp_frame *mdp, time_ms_t now)
RETURN(vomp_mdp_received(mdp)); RETURN(vomp_mdp_received(mdp));
case MDP_PORT_KEYMAPREQUEST: case MDP_PORT_KEYMAPREQUEST:
/* Either respond with the appropriate SAS, or record this one if it /* Either respond with the appropriate SAS, or record this one if it
verfies out okay. */ verifies out okay. */
DEBUG("key mapping request"); if (debug & DEBUG_MDPREQUESTS)
DEBUG("MDP_PORT_KEYMAPREQUEST");
RETURN(keyring_mapping_request(keyring,mdp)); RETURN(keyring_mapping_request(keyring,mdp));
case MDP_PORT_DNALOOKUP: /* attempt to resolve DID to SID */ case MDP_PORT_DNALOOKUP: /* attempt to resolve DID to SID */
{ {
@ -918,7 +919,8 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP,
RETURN(WHY("Error enqueuing frame")); RETURN(WHY("Error enqueuing frame"));
} }
else { else {
if (debug&DEBUG_OVERLAYINTERFACES) DEBUG("queued frame"); if (debug&DEBUG_OVERLAYINTERFACES)
DEBUGF("queued frame type=%#x modifiers=%#x ttl=%u", frame->type, frame->modifiers, frame->ttl);
RETURN(0); RETURN(0);
} }
} }

View File

@ -648,6 +648,7 @@ int overlay_frame_resolve_addresses(overlay_frame *f);
#define alloca_tohex(buf,len) tohex((char *)alloca((len)*2+1), (buf), (len)) #define alloca_tohex(buf,len) tohex((char *)alloca((len)*2+1), (buf), (len))
#define alloca_tohex_sid(sid) alloca_tohex((sid), SID_SIZE) #define alloca_tohex_sid(sid) alloca_tohex((sid), SID_SIZE)
#define alloca_tohex_sas(sas) alloca_tohex((sas), SAS_SIZE)
overlay_buffer *ob_new(int size); overlay_buffer *ob_new(int size);
overlay_buffer *ob_static(unsigned char *bytes, int size); overlay_buffer *ob_static(unsigned char *bytes, int size);

View File

@ -63,6 +63,7 @@ set_server_vars() {
executeOk_servald config set debug.tx No executeOk_servald config set debug.tx No
executeOk_servald config set debug.rx No executeOk_servald config set debug.rx No
executeOk_servald config set debug.mdprequests Yes executeOk_servald config set debug.mdprequests Yes
executeOk_servald config set debug.keyring Yes
} }
doc_MultiServer="Start three servald servers with dummy interfaces" doc_MultiServer="Start three servald servers with dummy interfaces"