mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-04-13 22:03:09 +00:00
Replaced use of HLR with keyring for phone number lookups and
other functions. Not yet tested.
This commit is contained in:
parent
7b8d78533d
commit
5ac83f9ca1
14
ciphers.c
14
ciphers.c
@ -32,20 +32,6 @@ int packetSetMySid(char *sid)
|
||||
|
||||
int packetGetPrivateKeyForSid()
|
||||
{
|
||||
/* Add all local SIDs to our cache */
|
||||
int ofs=0;
|
||||
while(findHlr(hlr,&ofs,NULL,NULL)) {
|
||||
// XXX If the SIDs match, then this is it */
|
||||
if (!current_sid_set) {
|
||||
/* we are using the first sid in the HLR */
|
||||
} else {
|
||||
/* Compare current SID with SID of this HLR record */
|
||||
/* XXX get PIN field which contains the private key or ciphered private key.
|
||||
Use code from ACTION_GET case in server.c as a guide */
|
||||
}
|
||||
if (nextHlr(hlr,&ofs)) break;
|
||||
}
|
||||
|
||||
return setReason("Not implemented");
|
||||
}
|
||||
|
||||
|
11
client.c
11
client.c
@ -19,6 +19,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#include "serval.h"
|
||||
|
||||
/* Now that we are using the keyring, we only support a small subset of variables.
|
||||
(VAR_NAME is not properly supported yet)
|
||||
*/
|
||||
struct mphlr_variable vars[]={
|
||||
{VAR_NAME, "name", "Published name of this subscriber"},
|
||||
{VAR_DIDS,"dids","Numbers claimed by this subscriber"},
|
||||
{VAR_LOCATIONS,"locations","Network address of telephone end point"},
|
||||
{0x00,NULL,NULL}
|
||||
};
|
||||
|
||||
|
||||
int packetSendFollowup(struct in_addr destination,
|
||||
unsigned char *packet,int packet_len)
|
||||
{
|
||||
|
@ -245,19 +245,9 @@ int app_server_start(int argc,char **argv,struct command_line_option *o)
|
||||
*/
|
||||
rhizome_datastore_path = serval_instancepath();
|
||||
rhizome_opendb();
|
||||
char *hlr_file;
|
||||
if (asprintf(&hlr_file, "%s/%s", serval_instancepath(), "hlr.dat") == -1) {
|
||||
fprintf(stderr,"ERROR: asprintf() failed\n");
|
||||
return -1;
|
||||
}
|
||||
hlr_size=atof(confValueGet("hlr_size","1"))*1048576;
|
||||
if (hlr_size<0) {
|
||||
fprintf(stderr,"HLR Size must be >0MB\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
overlayMode=1;
|
||||
return server(hlr_file,hlr_size,foregroundP);
|
||||
return server(NULL,foregroundP);
|
||||
}
|
||||
|
||||
int app_server_stop(int argc,char **argv,struct command_line_option *o)
|
||||
|
109
dna.c
109
dna.c
@ -40,45 +40,6 @@ int returnMultiVars=0;
|
||||
|
||||
int hexdigit[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
|
||||
|
||||
struct mphlr_variable vars[]={
|
||||
/* Variables that can have only a single value */
|
||||
{VAR_EOR,"eor","Marks end of record"},
|
||||
{VAR_CREATETIME,"createtime","Time HLR record was created"},
|
||||
{VAR_CREATOR,"creator","Device that created this HLR record"},
|
||||
{VAR_REVISION,"revision","Revision number of this HLR record"},
|
||||
{VAR_REVISOR,"revisor","Device that revised this HLR record"},
|
||||
{VAR_PIN,"pin","Secret PIN for this HLR record"},
|
||||
|
||||
/* GSM encoded audio, so a 16KB MPHLR maximum size shouldn't
|
||||
pose a problem. 8KB = ~4.5 seconds, which is a long time
|
||||
to say your name in, leaving 8KB for other variables. */
|
||||
{VAR_VOICESIG,"voicesig","Voice signature of this subscriber"},
|
||||
|
||||
{VAR_HLRMASTER,"hlrmaster","Location where the master copy of this HLR record is maintained."},
|
||||
{VAR_NAME, "name", "Published name of this subscriber"},
|
||||
|
||||
/* Variables that can take multiple values */
|
||||
{VAR_DIDS,"dids","Numbers claimed by this subscriber"},
|
||||
{VAR_LOCATIONS,"locations","Locations where this subscriber wishes to receive calls"},
|
||||
{VAR_IEMIS,"iemis","GSM IEMIs claimed by this subscriber"},
|
||||
{VAR_TEMIS,"temis","GSM TEMIs claimed by this subscriber"},
|
||||
|
||||
/* Each entry here has a flag byte (unread, ...) */
|
||||
{VAR_CALLS_IN,"callsin","Calls received by this subscriber"},
|
||||
{VAR_CALLS_MISSED,"callsmissed","Calls missed by this subscriber"},
|
||||
{VAR_CALLS_OUT,"callsout","Calls made by this subscriber"},
|
||||
|
||||
{VAR_SMESSAGES,"smessages","SMS received by this subscriber"},
|
||||
|
||||
{VAR_DID2SUBSCRIBER,"did2subscriber","Preferred subscribers for commonly called DIDs"},
|
||||
|
||||
{VAR_HLRBACKUPS,"hlrbackups","Locations where backups of this HLR record are maintained."},
|
||||
|
||||
{VAR_NOTE,"note","Free-form notes on this HLR record"},
|
||||
|
||||
{0x00,NULL,NULL}
|
||||
};
|
||||
|
||||
int sock=-1;
|
||||
|
||||
#ifndef HAVE_BZERO
|
||||
@ -160,7 +121,7 @@ int parseAssignment(unsigned char *text,int *var_id,unsigned char *value,int *va
|
||||
Values are length limited to 65535 bytes.
|
||||
*/
|
||||
|
||||
int i,v;
|
||||
int i;
|
||||
int max_len=*value_len;
|
||||
int vlen=0;
|
||||
int tlen=strlen((char *)text);
|
||||
@ -170,11 +131,13 @@ int parseAssignment(unsigned char *text,int *var_id,unsigned char *value,int *va
|
||||
}
|
||||
|
||||
/* Identify which variable */
|
||||
*var_id=-1;
|
||||
for(i=0;i<tlen;i++) if (text[i]=='=') break;
|
||||
for(v=0;vars[v].name;v++) if (!strncasecmp(vars[v].name,(char *)text,i)) break;
|
||||
|
||||
/* Go through known keyring variables */
|
||||
if (!strcasecmp((char *)text,"did")) *var_id=KEYTYPE_DID;
|
||||
|
||||
if (!vars[v].name) return setReason("Illegal variable name in assignment");
|
||||
*var_id=vars[v].id;
|
||||
if (*var_id==-1) return setReason("Illegal variable name in assignment");
|
||||
|
||||
i++;
|
||||
switch(text[i])
|
||||
@ -222,9 +185,7 @@ int usage(char *complaint)
|
||||
{
|
||||
fprintf(stderr,"dna: %s\n",complaint);
|
||||
fprintf(stderr,"usage:\n");
|
||||
fprintf(stderr," dna [-v <flags>] -S <hlr size in MB> [-f HLR backing file] [-I import.txt] [-N interface,...] [-G gateway specification] [-r rhizome path]\n");
|
||||
fprintf(stderr,"or\n");
|
||||
fprintf(stderr," dna [-v <flags>] -f <HLR backing file> -E <hlr export file>\n");
|
||||
fprintf(stderr," dna [-v <flags>] -S [-f keyring file] [-N interface,...] [-G gateway specification] [-r rhizome path]\n");
|
||||
fprintf(stderr,"or\n");
|
||||
fprintf(stderr," dna -r <rhizome path> -M <manifest name>\n");
|
||||
fprintf(stderr,"or\n");
|
||||
@ -238,12 +199,10 @@ int usage(char *complaint)
|
||||
fprintf(stderr,"or\n");
|
||||
fprintf(stderr," dna [-v <flags>] [-t timeout] -d did -C\n");
|
||||
fprintf(stderr,"or\n");
|
||||
fprintf(stderr," dna [-v <flags>] -f <hlr.dat> -E <export.txt>\n");
|
||||
fprintf(stderr," dna [-v <flags>] -f <keyring file> -E <export.txt>\n");
|
||||
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr," -v - Set verbosity.\n");
|
||||
fprintf(stderr," -E - Export specified HLR database into specified flat text file.\n");
|
||||
fprintf(stderr," -I - Import a previously exported HLR database into this one.\n");
|
||||
fprintf(stderr," -A - Ask for address of subscriber.\n");
|
||||
fprintf(stderr," -b - Specify BATMAN socket to obtain peer list (flaky).\n");
|
||||
fprintf(stderr," -l - Specify BATMAN socket to obtain peer list (better, but requires Serval patched BATMAN).\n");
|
||||
@ -251,8 +210,8 @@ int usage(char *complaint)
|
||||
fprintf(stderr," -m - Return multiple variable values instead of only first response.\n");
|
||||
fprintf(stderr," -M - Create and import a new bundle from the specified manifest.\n");
|
||||
fprintf(stderr," -n - Do not detach from foreground in server mode.\n");
|
||||
fprintf(stderr," -S - Run in server mode with an HLR of the specified size.\n");
|
||||
fprintf(stderr," -f - Use the specified file as a permanent store for HLR data.\n");
|
||||
fprintf(stderr," -S - Run in server mode.\n");
|
||||
fprintf(stderr," -f - Location of keyring file.\n");
|
||||
fprintf(stderr," -d - Search by Direct Inward Dial (DID) number.\n");
|
||||
fprintf(stderr," -s - Search by Subscriber ID (SID) number.\n");
|
||||
fprintf(stderr," -p - Specify additional DNA nodes to query.\n");
|
||||
@ -550,7 +509,7 @@ int main(int argc,char **argv)
|
||||
char *pin=NULL;
|
||||
char *did=NULL;
|
||||
char *sid=NULL;
|
||||
char *hlr_file=NULL;
|
||||
char *keyring_file=NULL;
|
||||
int instance=-1;
|
||||
int foregroundMode=0;
|
||||
|
||||
@ -599,20 +558,22 @@ int main(int argc,char **argv)
|
||||
" Type '%s help' to learn about the new command line structure.\n",
|
||||
argv[0]);
|
||||
|
||||
while((c=getopt(argc,argv,"Ab:B:E:G:I:S:f:d:i:l:L:mnp:P:r:s:t:v:R:W:U:D:CO:M:N:")) != -1 )
|
||||
while((c=getopt(argc,argv,"Ab:B:E:G:I:Sf:d:i:l:L:mnp:P:r:s:t:v:R:W:U:D:CO:M:N:")) != -1 )
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case 'S': serverMode=1; break;
|
||||
case 'r': /* Enable rhizome */
|
||||
if (rhizome_datastore_path) return WHY("-r specified more than once");
|
||||
rhizome_datastore_path=optarg;
|
||||
rhizome_opendb();
|
||||
/* Also set hlr file to be in the Rhizome directory, to save the need to specify it
|
||||
/* Also set keyring file to be in the Rhizome directory, to save the need to specify it
|
||||
separately. */
|
||||
char temp[1024];
|
||||
if (snprintf(temp, sizeof(temp), "%s/hlr.dat", optarg) >= sizeof(temp))
|
||||
if (snprintf(temp, sizeof(temp), "%s/serval.keyring", optarg)
|
||||
>= sizeof(temp))
|
||||
exit(WHY("Rhizome directory name too long."));
|
||||
hlr_file = strdup(temp);
|
||||
keyring_file = strdup(temp);
|
||||
break;
|
||||
case 'M': /* Distribute specified manifest and file pair using Rhizome. */
|
||||
/* This option assumes that the manifest is locally produced, and will
|
||||
@ -638,19 +599,6 @@ int main(int argc,char **argv)
|
||||
gatewayspec=strdup(optarg);
|
||||
if(prepareGateway(gatewayspec)) return usage("Invalid gateway specification");
|
||||
break;
|
||||
case 'E': /* Export HLR into plain text file that can be imported later */
|
||||
if (!hlr_file) usage("You must specify an HLR file to export from, i.e., dna -f hlr.dat -E hlr.txt");
|
||||
return exportHlr((unsigned char*)hlr_file,optarg);
|
||||
break;
|
||||
case 'I': /* Import HLR data from a plain text file into current HLR */
|
||||
if (importFile) usage("-I multiply specified.");
|
||||
importFile=optarg;
|
||||
if (!hlr_file||!serverMode) usage("-I requires -S and -f.");
|
||||
if (openHlrFile(hlr_file,hlr_size))
|
||||
exit(setReason("Failed to open HLR database"));
|
||||
importHlr(importFile);
|
||||
return 0;
|
||||
break;
|
||||
case 'n': /* don't detach from foreground in server mode */
|
||||
foregroundMode=1; break;
|
||||
case 'b': /* talk peers on a BATMAN mesh */
|
||||
@ -666,18 +614,13 @@ int main(int argc,char **argv)
|
||||
simulatedBER=atof(optarg);
|
||||
fprintf(stderr,"WARNING: Bit error injection enabled -- this will cause packet loss and is intended only for testing.\n");
|
||||
break;
|
||||
case 'S':
|
||||
if (atof(optarg)<0.1||atof(optarg)>16384) usage("HLR must be 0.1MB - 16384MB in size.");
|
||||
hlr_size=(int)(atof(optarg)*1048576.0);
|
||||
serverMode=1;
|
||||
break;
|
||||
case 'i':
|
||||
instance=atoi(optarg);
|
||||
if (instance<-1||instance>255) usage("Illegal variable instance ID.");
|
||||
break;
|
||||
case 'f':
|
||||
if (clientMode) usage("Only servers use backing files");
|
||||
hlr_file=strdup(optarg);
|
||||
if (clientMode) usage("Only servers use keyring files");
|
||||
keyring_file=strdup(optarg);
|
||||
break;
|
||||
case 'p': /* additional peers to query */
|
||||
if (additionalPeer(optarg)) exit(-3);
|
||||
@ -730,12 +673,8 @@ int main(int argc,char **argv)
|
||||
return writeItem(did?did:sid,var_id,instance,value,0,value_len,SET_REPLACE,-1,NULL);
|
||||
}
|
||||
break;
|
||||
case 'C': /* create a new HLR entry */
|
||||
{
|
||||
if (optind<argc) usage("Extraneous options after HLR creation request");
|
||||
if ((!did)||(sid)) usage("Specify exactly one DID and no SID to create a new HLR entry");
|
||||
return requestNewHLR(did,pin,sid,-1,NULL);
|
||||
}
|
||||
case 'C': /* create a new keyring entry */
|
||||
return WHY("Entries in new keyring format must be used with new command line framework.");
|
||||
break;
|
||||
case 'O': /* output to templated files */
|
||||
if (outputtemplate) usage("You can only specify -O once");
|
||||
@ -749,10 +688,10 @@ int main(int argc,char **argv)
|
||||
|
||||
if (optind<argc) usage("Extraneous options at end of command");
|
||||
|
||||
if (hlr_file&&clientMode) usage("Only servers use backing files");
|
||||
if (keyring_file&&clientMode) usage("Only servers use backing files");
|
||||
if (serverMode&&clientMode) usage("You asked me to be both server and client. That's silly.");
|
||||
if (serverMode) return server(hlr_file,hlr_size,foregroundMode);
|
||||
if (!clientMode) usage("Mesh Potato Home Location Register (HLR) Tool.");
|
||||
if (serverMode) return server(keyring_file,foregroundMode);
|
||||
if (!clientMode) usage("Serval server and client utility.");
|
||||
|
||||
#if defined WIN32
|
||||
WSACleanup();
|
||||
|
63
keyring.c
63
keyring.c
@ -756,19 +756,20 @@ int keyring_enter_pin(keyring_file *k,char *pin)
|
||||
The crypto_box and crypto_sign key pairs are automatically created, and the PKR
|
||||
is packed and written to a hithero unallocated slot which is then marked full.
|
||||
*/
|
||||
int keyring_create_identity(keyring_file *k,keyring_context *c,char *pin)
|
||||
keyring_identity *keyring_create_identity(keyring_file *k,keyring_context *c,char *pin)
|
||||
{
|
||||
/* Check obvious abort conditions early */
|
||||
if (!k) return WHY("keyring is NULL");
|
||||
if (!k->bam) return WHY("keyring lacks BAM (not to be confused with KAPOW)");
|
||||
if (!c) return WHY("keyring context is NULL");
|
||||
if (c->identity_count>=KEYRING_MAX_IDENTITIES) return WHY("keyring context has too many identities");
|
||||
if (!k) { WHY("keyring is NULL"); return NULL; }
|
||||
if (!k->bam) { WHY("keyring lacks BAM (not to be confused with KAPOW)"); return NULL; }
|
||||
if (!c) { WHY("keyring context is NULL"); return NULL; }
|
||||
if (c->identity_count>=KEYRING_MAX_IDENTITIES)
|
||||
{ WHY("keyring context has too many identities"); return NULL; }
|
||||
|
||||
int exit_code=1;
|
||||
if (!pin) pin="";
|
||||
|
||||
keyring_identity *id=calloc(sizeof(keyring_identity),1);
|
||||
|
||||
if (!id) { WHY("calloc() failed"); return NULL; }
|
||||
|
||||
/* Store pin */
|
||||
id->PKRPin=strdup(pin);
|
||||
if (!id->PKRPin) {
|
||||
@ -885,11 +886,11 @@ int keyring_create_identity(keyring_file *k,keyring_context *c,char *pin)
|
||||
else
|
||||
#endif
|
||||
/* Everything went fine */
|
||||
return 0;
|
||||
return id;
|
||||
|
||||
kci_safeexit:
|
||||
if (id) keyring_free_identity(id);
|
||||
return exit_code;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int keyring_commit(keyring_file *k)
|
||||
@ -1026,6 +1027,25 @@ int keyring_find_did(keyring_file *k,int *cn,int *in,int *kp,char *did)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int keyring_next_identity(keyring_file *k,int *cn,int *in,int *kp)
|
||||
{
|
||||
if (!k) return 0;
|
||||
|
||||
while ((*cn)<k->context_count) {
|
||||
while (((*cn)<k->context_count)&&((*in)>=k->contexts[*cn]->identity_count)) {
|
||||
(*cn)++; (*in)=0;
|
||||
}
|
||||
if ((*cn)>=k->context_count) return 0;
|
||||
|
||||
for((*kp)=0;*kp<k->contexts[*cn]->identities[*in]->keypair_count;(*kp)++)
|
||||
if (k->contexts[*cn]->identities[*in]->keypairs[*kp]->type==KEYTYPE_CRYPTOBOX)
|
||||
return 1;
|
||||
|
||||
(*in)++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int keyring_find_sid(keyring_file *k,int *cn,int *in,int *kp,unsigned char *sid)
|
||||
{
|
||||
if (!k) return 0;
|
||||
@ -1095,3 +1115,28 @@ keyring_file *keyring_open_with_pins(char *pinlist)
|
||||
return k;
|
||||
}
|
||||
|
||||
/* If no identities, create an initial identity with a phone number.
|
||||
This identity will not be pin protected (initially). */
|
||||
int keyring_seed(keyring_file *k)
|
||||
{
|
||||
if (!k) return WHY("keyring is null");
|
||||
|
||||
/* nothing to do if there is already an identity */
|
||||
if (k->contexts[0]->identity_count) return 0;
|
||||
|
||||
int i;
|
||||
char did[65];
|
||||
/* Securely generate random telephone number */
|
||||
urandombytes((unsigned char *)did,10);
|
||||
/* Make DID start with 2 through 9, as 1 is special in many number spaces. */
|
||||
did[0]='2'+did[0]%8;
|
||||
/* Then add 10 more digits, which is what we do in the mobile phone software */
|
||||
for(i=1;i<11;i++) did[i]='0'+did[i]%10; did[11]=0;
|
||||
|
||||
keyring_identity *id=keyring_create_identity(k,k->contexts[0],"");
|
||||
if (!id) return WHY("Could not create new identity");
|
||||
if (keyring_set_did(id,did)) return WHY("Could not set DID of new identity");
|
||||
if (keyring_commit(k)) return WHY("Could not commit new identity to keyring file");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
26
overlay.c
26
overlay.c
@ -74,12 +74,24 @@ int overlayMode=0;
|
||||
|
||||
overlay_txqueue overlay_tx[OQ_MAX];
|
||||
|
||||
keyring_file *keyring=NULL;
|
||||
|
||||
int overlayServerMode()
|
||||
{
|
||||
/* In overlay mode we need to listen to all of our sockets, and also to
|
||||
send periodic traffic. This means we need to */
|
||||
fprintf(stderr,"Running in overlay mode.\n");
|
||||
|
||||
/* Get keyring available for use.
|
||||
Required for MDP, and very soon as a complete replacement for the
|
||||
HLR for DNA lookups, even in non-overlay mode. */
|
||||
keyring=keyring_open_with_pins("");
|
||||
if (!keyring) {
|
||||
return WHY("Could not open serval keyring file.");
|
||||
}
|
||||
/* put initial identity in if we don't have any visible */
|
||||
keyring_seed(keyring);
|
||||
|
||||
/* Set default congestion levels for queues */
|
||||
int i;
|
||||
for(i=0;i<OQ_MAX;i++) {
|
||||
@ -103,20 +115,6 @@ int overlayServerMode()
|
||||
/* Create structures to use 1MB of RAM for testing */
|
||||
overlay_route_init(1);
|
||||
|
||||
/* Add all local SIDs to our cache */
|
||||
int ofs=0;
|
||||
while(findHlr(hlr,&ofs,NULL,NULL)) {
|
||||
int i;
|
||||
if (debug&DEBUG_OVERLAYINTERFACES) {
|
||||
fprintf(stderr,"Adding ");
|
||||
for(i=0;i<SID_SIZE;i++) fprintf(stderr,"%02x",hlr[ofs+4+i]);
|
||||
fprintf(stderr," to list of local addresses.\n");
|
||||
}
|
||||
overlay_add_local_identity(&hlr[ofs+4]);
|
||||
overlay_abbreviate_cache_address(&hlr[ofs+4]);
|
||||
if (nextHlr(hlr,&ofs)) break;
|
||||
}
|
||||
|
||||
/* Get rhizome server started BEFORE populating fd list so that
|
||||
the server's listen socket is in the list for poll() */
|
||||
if (rhizome_datastore_path) rhizome_server_poll();
|
||||
|
@ -462,25 +462,25 @@ int overlay_abbreviate_cache_lookup(unsigned char *in,unsigned char *out,int *of
|
||||
if (memcmp(in,&cache->sids[index].b[0],prefix_bytes))
|
||||
{
|
||||
/* No, it isn't in the cache, but it might be a local address. */
|
||||
int i,j;
|
||||
for(i=0;i<overlay_local_identity_count;i++)
|
||||
{
|
||||
for(j=0;j<prefix_bytes;j++)
|
||||
if (overlay_local_identities[i][j]!=in[j]) break;
|
||||
if (j>=prefix_bytes) {
|
||||
if (debug&DEBUG_OVERLAYABBREVIATIONS)
|
||||
WHY("Found reference to local address.");
|
||||
bcopy(&overlay_local_identities[i][0],&out[(*ofs)],SID_SIZE);
|
||||
(*ofs)+=SID_SIZE;
|
||||
return OA_RESOLVED;
|
||||
}
|
||||
else {
|
||||
if (debug&DEBUG_OVERLAYABBREVIATIONS)
|
||||
fprintf(stderr,"not identity #%d (%02x != %02x)\n",
|
||||
i,in[j],overlay_local_identities[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
int cn=0,id=0,kp=0;
|
||||
for(cn=0;cn<keyring->context_count;cn++)
|
||||
for(id=0;id<keyring->contexts[cn]->identity_count;id++)
|
||||
for(kp=0;kp<keyring->contexts[cn]->identities[id]->keypair_count;kp++)
|
||||
if (keyring->contexts[cn]->identities[id]->keypairs[kp]->type
|
||||
==KEYTYPE_CRYPTOBOX)
|
||||
{
|
||||
if (!bcmp(in,keyring->contexts[cn]->identities[id]
|
||||
->keypairs[kp]->public_key,prefix_bytes))
|
||||
{
|
||||
if (debug&DEBUG_OVERLAYABBREVIATIONS)
|
||||
WHY("Found reference to local address.");
|
||||
bcopy(&keyring->contexts[cn]->identities[id]
|
||||
->keypairs[kp]->public_key[0],&out[(*ofs)],SID_SIZE);
|
||||
(*ofs)+=SID_SIZE;
|
||||
return OA_RESOLVED;
|
||||
}
|
||||
}
|
||||
|
||||
if (debug&DEBUG_OVERLAYABBREVIATIONS)
|
||||
WHY("Encountered unresolvable address -- are we asking for explanation?");
|
||||
return OA_PLEASEEXPLAIN;
|
||||
@ -490,7 +490,7 @@ int overlay_abbreviate_cache_lookup(unsigned char *in,unsigned char *out,int *of
|
||||
colliding prefixes and ask the sender to resolve them for us, or better yet dynamically
|
||||
size the prefix length based on whether any given short prefix has collided */
|
||||
|
||||
if (debug&DEBUG_OVERLAYABBREVIATIONS) {
|
||||
if (debug&DEBUG_OVERLAYABBREVIATIONS) {
|
||||
/* It is here, so let's return it */
|
||||
fprintf(stderr,"I think I looked up the following: ");
|
||||
for(i=0;i<SID_SIZE;i++) fprintf(stderr,"%02x",cache->sids[index].b[i]);
|
||||
|
@ -181,17 +181,8 @@ int overlay_mdp_process_bind_request(int sock,overlay_mdp_frame *mdp,
|
||||
for(i=0;i<SID_SIZE;i++) if (mdp->bind.sid[i]) break;
|
||||
if (i<SID_SIZE) {
|
||||
/* Not all zeroes, so make sure it is a valid SID */
|
||||
int j,ok=0;
|
||||
for(j=0;j<overlay_local_identity_count;j++)
|
||||
{
|
||||
fprintf(stderr,"Comparing %s against local addr ",
|
||||
overlay_render_sid(mdp->bind.sid));
|
||||
fprintf(stderr,"%s\n",
|
||||
overlay_render_sid(overlay_local_identities[j]));
|
||||
for(i=0;i<SID_SIZE;i++)
|
||||
if (mdp->bind.sid[i]!=overlay_local_identities[j][i]) break;
|
||||
if (i==SID_SIZE) { ok=1; break; }
|
||||
}
|
||||
int ok=0;
|
||||
if (overlay_address_is_local(mdp->bind.sid)) ok=1;
|
||||
if (!ok) {
|
||||
/* Source address is invalid */
|
||||
return overlay_mdp_reply_error(sock,recvaddr,recvaddrlen,7,
|
||||
@ -355,8 +346,12 @@ int overlay_saw_mdp_frame(int interface, overlay_mdp_frame *mdp,long long now)
|
||||
with our local address. For now just responds with first local address */
|
||||
if (overlay_address_is_broadcast(mdp->out.src.sid))
|
||||
{
|
||||
if (overlay_local_identity_count)
|
||||
bcopy(&overlay_local_identities[0][0],mdp->out.src.sid,SID_SIZE);
|
||||
if (keyring->contexts[0]->identity_count&&
|
||||
keyring->contexts[0]->identities[0]->keypair_count&&
|
||||
keyring->contexts[0]->identities[0]->keypairs[0]->type
|
||||
==KEYTYPE_CRYPTOBOX)
|
||||
bcopy(keyring->contexts[0]->identities[0]->keypairs[0]->public_key,
|
||||
mdp->out.src.sid,SID_SIZE);
|
||||
else
|
||||
/* No local addresses, so put all zeroes */
|
||||
bzero(mdp->out.src.sid,SID_SIZE);
|
||||
@ -592,26 +587,35 @@ int overlay_mdp_poll()
|
||||
int max_sids=mdp->addrlist.frame_sid_count;
|
||||
/* ... and constrain list for sanity */
|
||||
if (sid_num<0) sid_num=0;
|
||||
if (sid_num>overlay_local_identity_count) max_sids=0;
|
||||
if (max_sids>MDP_MAX_SID_REQUEST) max_sids=MDP_MAX_SID_REQUEST;
|
||||
if (max_sids>(overlay_local_identity_count-sid_num))
|
||||
max_sids=overlay_local_identity_count-sid_num;
|
||||
if (max_sid>(overlay_local_identity_count-sid_num))
|
||||
max_sid=overlay_local_identity_count-sid_num;
|
||||
if (max_sids<0) max_sids=0;
|
||||
|
||||
/* Prepare reply packet */
|
||||
mdpreply.packetTypeAndFlags=MDP_ADDRLIST;
|
||||
mdpreply.addrlist.server_sid_count=overlay_local_identity_count;
|
||||
{
|
||||
int cn=0,in=0,kp=0;
|
||||
int count=0;
|
||||
while(keyring_next_identity(keyring,&cn,&in,&kp)) {
|
||||
in++; count++;
|
||||
}
|
||||
mdpreply.addrlist.server_sid_count=count;
|
||||
}
|
||||
mdpreply.addrlist.first_sid=sid_num;
|
||||
mdpreply.addrlist.last_sid=max_sid;
|
||||
mdpreply.addrlist.frame_sid_count=max_sids;
|
||||
|
||||
/* Populate with SIDs */
|
||||
int i;
|
||||
for(i=0;i<max_sids;i++)
|
||||
bcopy(overlay_local_identities[sid_num+i],
|
||||
mdpreply.addrlist.sids[i],SID_SIZE);
|
||||
int cn=0,in=0,kp=0;
|
||||
int i=0;
|
||||
int count=0;
|
||||
while(keyring_next_identity(keyring,&cn,&in,&kp)) {
|
||||
if (count>=sid_num&&(i<max_sids))
|
||||
bcopy(keyring->contexts[cn]->identities[in]->keypairs[kp]->public_key,
|
||||
mdpreply.addrlist.sids[i++],SID_SIZE);
|
||||
in++; kp=0;
|
||||
count++;
|
||||
if (i>=max_sids) break;
|
||||
}
|
||||
|
||||
/* Send back to caller */
|
||||
return overlay_mdp_reply(mdp_named_socket,
|
||||
|
@ -278,11 +278,20 @@ int overlay_frame_set_broadcast_as_destination(overlay_frame *f)
|
||||
|
||||
unsigned char *overlay_get_my_sid()
|
||||
{
|
||||
|
||||
/* Make sure we can find our SID */
|
||||
int zero=0;
|
||||
if (!findHlr(hlr,&zero,NULL,NULL)) { WHY("Could not find first entry in HLR"); return NULL; }
|
||||
return &hlr[zero+4];
|
||||
int kp;
|
||||
if (!keyring)
|
||||
{ WHY("keyring is null"); return NULL; }
|
||||
if (!keyring->context_count)
|
||||
{ WHY("No context zero in keyring"); return NULL; }
|
||||
if (!keyring->contexts[0]->identity_count)
|
||||
{ WHY("No identity in keyring context zero"); return NULL; }
|
||||
|
||||
for(kp=0;kp<keyring->contexts[0]->identities[0]->keypair_count;kp++)
|
||||
if (keyring->contexts[0]->identities[0]->keypairs[kp]->type==KEYTYPE_CRYPTOBOX)
|
||||
return keyring->contexts[0]->identities[0]->keypairs[kp]->public_key;
|
||||
|
||||
WHY("Could not find first entry in HLR"); return NULL;
|
||||
}
|
||||
|
||||
int overlay_frame_set_me_as_source(overlay_frame *f)
|
||||
|
@ -1046,39 +1046,12 @@ int overlay_route_record_link(long long now,unsigned char *to,unsigned char *via
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_local_identity_count=0;
|
||||
unsigned char *overlay_local_identities[OVERLAY_MAX_LOCAL_IDENTITIES];
|
||||
|
||||
int overlay_address_is_local(unsigned char *s)
|
||||
{ int ii,i;
|
||||
for (ii=0;ii<overlay_local_identity_count;ii++) {
|
||||
for(i=0;i<SID_SIZE;i++)
|
||||
if (s[i]!=overlay_local_identities[ii][i])
|
||||
{ if (debug&DEBUG_OVERLAYROUTING) fprintf(stderr,"address is not local address #%d, since byte %d = %02x != %02x\n",
|
||||
ii,i,s[i],overlay_local_identities[ii][i]);
|
||||
break; }
|
||||
if (i==SID_SIZE) { return 1; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
int cn=0,in=0,kp=0;
|
||||
int found=keyring_find_sid(keyring,&cn,&in,&kp,s);
|
||||
|
||||
int overlay_add_local_identity(unsigned char *s)
|
||||
{
|
||||
int i;
|
||||
if (overlay_local_identity_count>=OVERLAY_MAX_LOCAL_IDENTITIES)
|
||||
return WHY("Too many local identities. Increase OVERLAY_MAX_LOCAL_IDENTITIES.");
|
||||
|
||||
overlay_local_identities[overlay_local_identity_count]=malloc(SID_SIZE);
|
||||
if (!overlay_local_identities[overlay_local_identity_count])
|
||||
return WHY("malloc() failed while recording local identity.");
|
||||
|
||||
for(i=0;i<SID_SIZE;i++) {
|
||||
overlay_local_identities[overlay_local_identity_count][i]=s[i];
|
||||
}
|
||||
|
||||
overlay_local_identity_count++;
|
||||
|
||||
return 0;
|
||||
return found;
|
||||
}
|
||||
|
||||
int overlay_route_dump()
|
||||
@ -1087,13 +1060,18 @@ int overlay_route_dump()
|
||||
long long now=overlay_gettime_ms();
|
||||
|
||||
fprintf(stderr,"\nOverlay Local Identities\n------------------------\n");
|
||||
for(n=0;n<overlay_local_identity_count;n++)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<SID_SIZE;i++)
|
||||
fprintf(stderr,"%02x",overlay_local_identities[n][i]);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
int cn,in,kp;
|
||||
for(cn=0;cn<keyring->context_count;cn++)
|
||||
for(in=0;in<keyring->contexts[cn]->identity_count;in++)
|
||||
for(kp=0;kp<keyring->contexts[cn]->identities[in]->keypair_count;kp++)
|
||||
if (keyring->contexts[cn]->identities[in]->keypairs[kp]->type
|
||||
==KEYTYPE_CRYPTOBOX)
|
||||
{
|
||||
for(i=0;i<SID_SIZE;i++)
|
||||
fprintf(stderr,"%02x",keyring->contexts[cn]->identities[in]
|
||||
->keypairs[kp]->public_key[i]);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
fprintf(stderr,"\nOverlay Neighbour Table\n------------------------\n");
|
||||
for(n=0;n<overlay_neighbour_count;n++)
|
||||
|
@ -206,6 +206,28 @@ int packetSetSid(unsigned char *packet,int packet_maxlen,int *packet_len,char *s
|
||||
return stowSid(packet,ofs,sid);
|
||||
}
|
||||
|
||||
int packetSetSidFromId(unsigned char *packet,int packet_maxlen,int *packet_len,
|
||||
keyring_identity *id)
|
||||
{
|
||||
if (!id) return WHY("id is null");
|
||||
|
||||
unsigned char *sid=NULL;
|
||||
int i;
|
||||
|
||||
for(i=0;i<id->keypair_count;i++)
|
||||
if (id->keypairs[i]->type==KEYTYPE_CRYPTOBOX)
|
||||
{ sid=id->keypairs[i]->public_key; break; }
|
||||
|
||||
if (!sid) return WHY("Could not find SID in identity");
|
||||
|
||||
/* find and copy SID from identity */
|
||||
int ofs=OFS_SIDDIDFIELD;
|
||||
packet[ofs++]=0x01; /* SID */
|
||||
bcopy(sid,&packet[ofs],SID_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int packetFinalise(unsigned char *packet,int packet_maxlen,int recvttl,
|
||||
int *packet_len,int cryptoflags)
|
||||
{
|
||||
@ -512,7 +534,8 @@ int extractResponses(struct in_addr sender,unsigned char *buffer,int len,struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
int packageVariableSegment(unsigned char *data,int *dlen,struct hlrentry_handle *h,
|
||||
int packageVariableSegment(unsigned char *data,int *dlen,
|
||||
struct response *h,
|
||||
int offset,int buffer_size)
|
||||
{
|
||||
int bytes;
|
||||
@ -546,7 +569,7 @@ int packageVariableSegment(unsigned char *data,int *dlen,struct hlrentry_handle
|
||||
if (debug&DEBUG_PACKETFORMATS) fprintf(stderr,"Packaging %d bytes\n",bytes);
|
||||
|
||||
/* Package the variable value itself (or part thereof) */
|
||||
bcopy(&h->value[offset],&data[*dlen],bytes);
|
||||
bcopy(&h->response[offset],&data[*dlen],bytes);
|
||||
(*dlen)+=bytes;
|
||||
|
||||
if (debug&DEBUG_PACKETFORMATS) dump("Variable segment octets",&data[dlen_in],(*dlen)-dlen_in);
|
||||
|
200
serval.h
200
serval.h
@ -163,8 +163,91 @@ extern char *instrumentation_file;
|
||||
extern char *batman_socket;
|
||||
extern char *batman_peerfile;
|
||||
|
||||
/* HLR records can be upto 4GB, so 4x8bits are needed to encode the size */
|
||||
#define HLR_RECORD_LEN_SIZE 4
|
||||
|
||||
typedef struct keypair {
|
||||
int type;
|
||||
unsigned char *private_key;
|
||||
int private_key_len;
|
||||
unsigned char *public_key;
|
||||
int public_key_len;
|
||||
} keypair;
|
||||
|
||||
/* Contains just the list of private:public key pairs and types,
|
||||
the pin used to extract them, and the slot in the keyring file
|
||||
(so that it can be replaced/rewritten as required). */
|
||||
#define PKR_MAX_KEYPAIRS 64
|
||||
#define PKR_SALT_BYTES 32
|
||||
#define PKR_MAC_BYTES 64
|
||||
typedef struct keyring_identity {
|
||||
char *PKRPin;
|
||||
unsigned int slot;
|
||||
int keypair_count;
|
||||
keypair *keypairs[PKR_MAX_KEYPAIRS];
|
||||
} keyring_identity;
|
||||
|
||||
/* 64K identities, can easily be increased should the need arise,
|
||||
but keep it low-ish for now so that the 64K pointers don't eat too
|
||||
much ram on a small device. Should probably think about having
|
||||
small and large device settings for some of these things */
|
||||
#define KEYRING_MAX_IDENTITIES 65536
|
||||
typedef struct keyring_context {
|
||||
char *KeyRingPin;
|
||||
unsigned char *KeyRingSalt;
|
||||
int KeyRingSaltLen;
|
||||
|
||||
int identity_count;
|
||||
keyring_identity *identities[KEYRING_MAX_IDENTITIES];
|
||||
} keyring_context;
|
||||
|
||||
#define KEYRING_PAGE_SIZE 4096LL
|
||||
#define KEYRING_BAM_BYTES 2048LL
|
||||
#define KEYRING_BAM_BITS (KEYRING_BAM_BYTES<<3)
|
||||
#define KEYRING_SLAB_SIZE (KEYRING_PAGE_SIZE*KEYRING_BAM_BITS)
|
||||
typedef struct keyring_bam {
|
||||
off_t file_offset;
|
||||
unsigned char bitmap[KEYRING_BAM_BYTES];
|
||||
struct keyring_bam *next;
|
||||
} keyring_bam;
|
||||
|
||||
#define KEYRING_MAX_CONTEXTS 256
|
||||
typedef struct keyring_file {
|
||||
int context_count;
|
||||
keyring_bam *bam;
|
||||
keyring_context *contexts[KEYRING_MAX_CONTEXTS];
|
||||
FILE *file;
|
||||
off_t file_size;
|
||||
} keyring_file;
|
||||
|
||||
void keyring_free(keyring_file *k);
|
||||
void keyring_free_context(keyring_context *c);
|
||||
void keyring_free_identity(keyring_identity *id);
|
||||
void keyring_free_keypair(keypair *kp);
|
||||
int keyring_identity_mac(keyring_context *c,keyring_identity *id,
|
||||
unsigned char *pkrsalt,unsigned char *mac);
|
||||
#define KEYTYPE_CRYPTOBOX 0x01
|
||||
#define KEYTYPE_CRYPTOSIGN 0x02
|
||||
#define KEYTYPE_RHIZOME 0x03
|
||||
/* DIDs aren't really keys, but the keyring is a real handy place to keep them,
|
||||
and keep them private if people so desire */
|
||||
#define KEYTYPE_DID 0x04
|
||||
|
||||
/* handle to keyring file for use in running instance */
|
||||
extern keyring_file *keyring;
|
||||
|
||||
/* Public calls to keyring management */
|
||||
keyring_file *keyring_open(char *file);
|
||||
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_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);
|
||||
int keyring_commit(keyring_file *k);
|
||||
keyring_identity *keyring_create_identity(keyring_file *k,keyring_context *c,
|
||||
char *pin);
|
||||
|
||||
int keyring_seed(keyring_file *k);
|
||||
|
||||
/* Packet format:
|
||||
|
||||
@ -240,19 +323,6 @@ struct response_set {
|
||||
unsigned char *reply_bitmask;
|
||||
};
|
||||
|
||||
struct hlrentry_handle {
|
||||
int record_length;
|
||||
unsigned char *hlr;
|
||||
int hlr_offset;
|
||||
|
||||
int var_id;
|
||||
int var_instance;
|
||||
unsigned char *value;
|
||||
int value_len;
|
||||
|
||||
int entry_offset;
|
||||
};
|
||||
|
||||
/* Array of variables that can be placed in an MPHLR */
|
||||
#define VAR_EOR 0x00
|
||||
#define VAR_CREATETIME 0x01
|
||||
@ -313,13 +383,14 @@ int stowSid(unsigned char *packet,int ofs,char *sid);
|
||||
int stowDid(unsigned char *packet,int *ofs,char *did);
|
||||
int isFieldZeroP(unsigned char *packet,int start,int count);
|
||||
void srandomdev();
|
||||
int respondSimple(char *sid,int action,unsigned char *action_text,int action_len,
|
||||
int respondSimple(keyring_identity *id,
|
||||
int action,unsigned char *action_text,int action_len,
|
||||
unsigned char *transaction_id,int recvttl,
|
||||
struct sockaddr *recvaddr,int cryptoFlags);
|
||||
int requestItem(char *did,char *sid,char *item,int instance,unsigned char *buffer,int buffer_length,int *len,
|
||||
unsigned char *transaction_id);
|
||||
int requestNewHLR(char *did,char *pin,char *sid,int recvttl,struct sockaddr *recvaddr);
|
||||
int server(char *backing_file,int size,int foregroundMode);
|
||||
int server(char *backing_file,int foregroundMode);
|
||||
int isTransactionInCache(unsigned char *transaction_id);
|
||||
void insertTransactionInCache(unsigned char *transaction_id);
|
||||
|
||||
@ -333,7 +404,10 @@ int process_packet(unsigned char *packet,int len,
|
||||
int recvttl,struct sockaddr *sender,int sender_len);
|
||||
int packetMakeHeader(unsigned char *packet,int packet_maxlen,int *packet_len,unsigned char *transaction_id,int cryptoflags);
|
||||
int packetSetDid(unsigned char *packet,int packet_maxlen,int *packet_len,char *did);
|
||||
int packetSetSid(unsigned char *packet,int packet_maxlen,int *packet_len,char *sid);
|
||||
// Deprecated
|
||||
// int packetSetSid(unsigned char *packet,int packet_maxlen,int *packet_len,char *sid);
|
||||
int packetSetSidFromId(unsigned char *packet,int packet_maxlen,int *packet_len,
|
||||
keyring_identity *id);
|
||||
int packetFinalise(unsigned char *packet,int packet_maxlen,int recvttl,
|
||||
int *packet_len,int cryptoflags);
|
||||
int packetAddHLRCreateRequest(unsigned char *packet,int packet_maxlen,int *packet_len);
|
||||
@ -346,16 +420,8 @@ int sendToPeers(unsigned char *packet,int packet_len,int method,int peerId,struc
|
||||
int getReplyPackets(int method,int peer,int batchP,struct response_set *responses,
|
||||
unsigned char *transaction_id,struct sockaddr *recvaddr,int timeout);
|
||||
int clearResponse(struct response **response);
|
||||
int nextHlr(unsigned char *hlr,int *ofs);
|
||||
int seedHlr();
|
||||
int findHlr(unsigned char *hlr,int *ofs,char *sid,char *did);
|
||||
int createHlr(char *did,char *sid);
|
||||
struct hlrentry_handle *openhlrentry(unsigned char *hlr,int hofs);
|
||||
struct hlrentry_handle *hlrentrygetent(struct hlrentry_handle *h);
|
||||
int hlrStowValue(unsigned char *hlr,int hofs,int hlr_offset,
|
||||
int varid,int varinstance,unsigned char *value,int len);
|
||||
int hlrMakeSpace(unsigned char *hlr,int hofs,int hlr_offset,int bytes);
|
||||
int packageVariableSegment(unsigned char *data,int *dlen,struct hlrentry_handle *h,
|
||||
int packageVariableSegment(unsigned char *data,int *dlen,
|
||||
struct response *h,
|
||||
int offset,int buffer_size);
|
||||
int packetDecipher(unsigned char *packet,int len,int cipher);
|
||||
int safeZeroField(unsigned char *packet,int start,int count);
|
||||
@ -1088,81 +1154,3 @@ void *_serval_debug_malloc(unsigned int bytes,char *file,const char *func,int li
|
||||
void *_serval_debug_calloc(unsigned int bytes,unsigned int count,char *file,const char *func,int line);
|
||||
void _serval_debug_free(void *p,char *file,const char *func,int line);
|
||||
#endif
|
||||
|
||||
typedef struct keypair {
|
||||
int type;
|
||||
unsigned char *private_key;
|
||||
int private_key_len;
|
||||
unsigned char *public_key;
|
||||
int public_key_len;
|
||||
} keypair;
|
||||
|
||||
/* Contains just the list of private:public key pairs and types,
|
||||
the pin used to extract them, and the slot in the keyring file
|
||||
(so that it can be replaced/rewritten as required). */
|
||||
#define PKR_MAX_KEYPAIRS 64
|
||||
#define PKR_SALT_BYTES 32
|
||||
#define PKR_MAC_BYTES 64
|
||||
typedef struct keyring_identity {
|
||||
char *PKRPin;
|
||||
unsigned int slot;
|
||||
int keypair_count;
|
||||
keypair *keypairs[PKR_MAX_KEYPAIRS];
|
||||
} keyring_identity;
|
||||
|
||||
/* 64K identities, can easily be increased should the need arise,
|
||||
but keep it low-ish for now so that the 64K pointers don't eat too
|
||||
much ram on a small device. Should probably think about having
|
||||
small and large device settings for some of these things */
|
||||
#define KEYRING_MAX_IDENTITIES 65536
|
||||
typedef struct keyring_context {
|
||||
char *KeyRingPin;
|
||||
unsigned char *KeyRingSalt;
|
||||
int KeyRingSaltLen;
|
||||
|
||||
int identity_count;
|
||||
keyring_identity *identities[KEYRING_MAX_IDENTITIES];
|
||||
} keyring_context;
|
||||
|
||||
#define KEYRING_PAGE_SIZE 4096LL
|
||||
#define KEYRING_BAM_BYTES 2048LL
|
||||
#define KEYRING_BAM_BITS (KEYRING_BAM_BYTES<<3)
|
||||
#define KEYRING_SLAB_SIZE (KEYRING_PAGE_SIZE*KEYRING_BAM_BITS)
|
||||
typedef struct keyring_bam {
|
||||
off_t file_offset;
|
||||
unsigned char bitmap[KEYRING_BAM_BYTES];
|
||||
struct keyring_bam *next;
|
||||
} keyring_bam;
|
||||
|
||||
#define KEYRING_MAX_CONTEXTS 256
|
||||
typedef struct keyring_file {
|
||||
int context_count;
|
||||
keyring_bam *bam;
|
||||
keyring_context *contexts[KEYRING_MAX_CONTEXTS];
|
||||
FILE *file;
|
||||
off_t file_size;
|
||||
} keyring_file;
|
||||
|
||||
void keyring_free(keyring_file *k);
|
||||
void keyring_free_context(keyring_context *c);
|
||||
void keyring_free_identity(keyring_identity *id);
|
||||
void keyring_free_keypair(keypair *kp);
|
||||
int keyring_identity_mac(keyring_context *c,keyring_identity *id,
|
||||
unsigned char *pkrsalt,unsigned char *mac);
|
||||
#define KEYTYPE_CRYPTOBOX 0x01
|
||||
#define KEYTYPE_CRYPTOSIGN 0x02
|
||||
#define KEYTYPE_RHIZOME 0x03
|
||||
/* DIDs aren't really keys, but the keyring is a real handy place to keep them,
|
||||
and keep them private if people so desire */
|
||||
#define KEYTYPE_DID 0x04
|
||||
|
||||
/* Public calls to keyring management */
|
||||
keyring_file *keyring_open(char *file);
|
||||
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_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);
|
||||
int keyring_commit(keyring_file *k);
|
||||
int keyring_create_identity(keyring_file *k,keyring_context *c,char *pin);
|
||||
|
436
server.c
436
server.c
@ -31,7 +31,7 @@ FILE *i_f=NULL;
|
||||
struct in_addr client_addr;
|
||||
int client_port;
|
||||
|
||||
int getBackingStore(char *s,int size);
|
||||
int getKeyring(char *s);
|
||||
int createServerSocket();
|
||||
int simpleServerMode();
|
||||
|
||||
@ -96,10 +96,10 @@ int recvwithttl(int sock,unsigned char *buffer,int bufferlen,int *ttl,
|
||||
}
|
||||
|
||||
|
||||
int server(char *backing_file,int size,int foregroundMode)
|
||||
int server(char *backing_file,int foregroundMode)
|
||||
{
|
||||
/* Get backing store for HLR */
|
||||
getBackingStore(backing_file,size);
|
||||
getKeyring(backing_file);
|
||||
|
||||
if (overlayMode)
|
||||
{
|
||||
@ -142,55 +142,22 @@ int server(char *backing_file,int size,int foregroundMode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getBackingStore(char *backing_file,int size)
|
||||
int getKeyring(char *backing_file)
|
||||
{
|
||||
if (!backing_file)
|
||||
{
|
||||
/* transitory storage of HLR data, so just malloc() the memory */
|
||||
hlr=calloc(size,1);
|
||||
if (!hlr) exit(setReason("Failed to calloc() HLR database."));
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Allocated %d byte temporary HLR store\n",size);
|
||||
{
|
||||
exit(WHY("Keyring requires a backing file"));
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char zero[8192];
|
||||
FILE *f=fopen(backing_file,"r+");
|
||||
if (!f) f=fopen(backing_file,"w+");
|
||||
if (!f) exit(setReason("Could not open backing file."));
|
||||
bzero(&zero[0],8192);
|
||||
fseek(f,0,SEEK_END);
|
||||
errno=0;
|
||||
while(ftell(f)<size)
|
||||
{
|
||||
int r;
|
||||
fseek(f,0,SEEK_END);
|
||||
if ((r=fwrite(zero,8192,1,f))!=1)
|
||||
{
|
||||
perror("fwrite");
|
||||
exit(setReason("Could not enlarge backing file to requested size (short write)"));
|
||||
}
|
||||
fseek(f,0,SEEK_END);
|
||||
}
|
||||
|
||||
if (errno) perror("fseek");
|
||||
if (fwrite("",1,1,f)!=1)
|
||||
{
|
||||
fprintf(stderr,"Failed to set backing file size.\n");
|
||||
perror("fwrite");
|
||||
}
|
||||
hlr=(unsigned char *)mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_NORESERVE,fileno(f),0);
|
||||
if (hlr==MAP_FAILED) {
|
||||
perror("mmap");
|
||||
exit(setReason("Memory mapping of HLR backing file failed."));
|
||||
if (keyring) {
|
||||
exit(WHY("Keyring being opened twice"));
|
||||
keyring=keyring_open(backing_file);
|
||||
}
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Allocated %d byte HLR store backed by file `%s'\n",
|
||||
size,backing_file);
|
||||
}
|
||||
hlr_size=size;
|
||||
keyring_seed(keyring);
|
||||
|
||||
seedHlr();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int processRequest(unsigned char *packet,int len,
|
||||
@ -198,7 +165,7 @@ int processRequest(unsigned char *packet,int len,
|
||||
unsigned char *transaction_id,int recvttl, char *did,char *sid)
|
||||
{
|
||||
/* Find HLR entry by DID or SID, unless creating */
|
||||
int ofs,rofs=0;
|
||||
int ofs;
|
||||
int records_searched=0;
|
||||
|
||||
int prev_pofs=0;
|
||||
@ -217,26 +184,22 @@ int processRequest(unsigned char *packet,int len,
|
||||
you can't choose a SID. */
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Creating a new HLR record. did='%s', sid='%s'\n",did,sid);
|
||||
if (!did[0]) return respondSimple(NULL,ACTION_DECLINED,NULL,0,transaction_id,recvttl,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
if (sid[0]) return respondSimple(sid,ACTION_DECLINED,NULL,0,transaction_id,recvttl,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
if (sid[0])
|
||||
return respondSimple(NULL,ACTION_DECLINED,NULL,0,transaction_id,
|
||||
recvttl,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Verified that create request supplies DID but not SID\n");
|
||||
|
||||
{
|
||||
/* Look for an existing HLR with the requested DID. If there is one, respond with its
|
||||
SID. This handles duplicates of the same message. If there is none, then make a new
|
||||
HLR with random SID and initial DID. */
|
||||
int ofs = 0;
|
||||
int response = ACTION_DECLINED;
|
||||
if (findHlr(hlr, &ofs, sid, did)) {
|
||||
hlrSid(hlr, ofs, sid);
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"HLR found with did='%s' at ofs=%x: sid='%s'\n", did, ofs, sid);
|
||||
response = ACTION_OKAY;
|
||||
}
|
||||
else if (createHlr(did, sid) == 0) {
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"HLR created with did='%s': sid='%s'\n", did, sid);
|
||||
response = ACTION_OKAY;
|
||||
}
|
||||
return respondSimple(sid, response, NULL, 0, transaction_id, recvttl, sender, CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
/* Creating an identity is nice and easy now with the new keyring */
|
||||
keyring_identity *id=keyring_create_identity(keyring,keyring->contexts[0],
|
||||
"");
|
||||
if (id) keyring_set_did(id,did);
|
||||
if (id==NULL||keyring_commit(keyring))
|
||||
return respondSimple(NULL,ACTION_DECLINED,NULL,0,transaction_id,recvttl,
|
||||
sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
else
|
||||
return respondSimple(id,ACTION_OKAY,NULL,0,transaction_id,recvttl,
|
||||
sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
|
||||
pofs+=1;
|
||||
pofs+=1+SID_SIZE;
|
||||
}
|
||||
@ -269,137 +232,13 @@ int processRequest(unsigned char *packet,int len,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ACTION_DIGITALTELEGRAM:
|
||||
if (debug&DEBUG_DNAREQUESTS) fprintf(stderr,"In ACTION_DIGITALTELEGRAM\n");
|
||||
{
|
||||
// Unpack SMS message.
|
||||
char emitterPhoneNumber[256];
|
||||
char message[256];
|
||||
pofs++;
|
||||
/* char messageType = packet[pofs]; */
|
||||
pofs++;
|
||||
char emitterPhoneNumberLen = packet[pofs];
|
||||
pofs++;
|
||||
char messageLen = packet[pofs];
|
||||
pofs++;
|
||||
strncpy(emitterPhoneNumber, (const char*)packet+pofs, emitterPhoneNumberLen);
|
||||
emitterPhoneNumber[(unsigned int)emitterPhoneNumberLen]=0;
|
||||
|
||||
pofs+=emitterPhoneNumberLen;
|
||||
strncpy(message, (const char*)packet+pofs, messageLen);
|
||||
message[(unsigned int)messageLen]=0;
|
||||
|
||||
pofs+=messageLen;
|
||||
|
||||
// Check if I'm the recipient
|
||||
ofs=0;
|
||||
if (findHlr(hlr, &ofs, sid, did)) {
|
||||
// Check transaction cache to see if message has already been delivered. If not,
|
||||
// then deliver it now.
|
||||
if (!isTransactionInCache(transaction_id)) {
|
||||
// Deliver SMS to android.
|
||||
char amCommand[576]; // 64 char + 2*256(max) char = 576
|
||||
sprintf(amCommand, "am broadcast -a org.servalproject.DT -e number \"%s\" -e content \"%s\"", emitterPhoneNumber, message);
|
||||
if (debug&DEBUG_DNAREQUESTS) fprintf(stderr,"Delivering DT message via intent: %s\n",amCommand);
|
||||
runCommand(amCommand);
|
||||
// Record in cache to prevent re-delivering the same message if a duplicate is received.
|
||||
insertTransactionInCache(transaction_id);
|
||||
}
|
||||
char sid[SID_STRLEN+1];
|
||||
respondSimple(hlrSid(hlr, ofs, sid), ACTION_OKAY, NULL, 0, transaction_id, recvttl, sender, CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ACTION_SET:
|
||||
ofs=0;
|
||||
if (debug&DEBUG_DNAREQUESTS) fprintf(stderr,"Looking for hlr entries with sid='%s' / did='%s'\n",sid,did);
|
||||
|
||||
if ((!sid)||(!sid[0])) {
|
||||
setReason("You can only set variables by SID");
|
||||
return respondSimple(NULL,ACTION_ERROR,
|
||||
(unsigned char *)"SET requires authentication by SID",
|
||||
0,transaction_id,recvttl,
|
||||
sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
|
||||
while(findHlr(hlr,&ofs,sid,did))
|
||||
{
|
||||
int itemId,instance,start_offset,bytes,flags;
|
||||
unsigned char value[9000],oldvalue[65536];
|
||||
int oldr,oldl;
|
||||
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"findHlr found a match for writing at 0x%x\n",ofs);
|
||||
if (debug&DEBUG_HLR) hlrDump(hlr,ofs);
|
||||
|
||||
/* XXX consider taking action on this HLR
|
||||
(check PIN first depending on the action requested) */
|
||||
setReason("You can only set keyring variables locally");
|
||||
return respondSimple(NULL,ACTION_ERROR,
|
||||
(unsigned char *)"Would be insecure",
|
||||
0,transaction_id,recvttl,
|
||||
sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
|
||||
/* XXX Doesn't verify PIN authentication */
|
||||
|
||||
/* Get write request */
|
||||
|
||||
pofs++; rofs=pofs;
|
||||
if (extractRequest(packet,&pofs,len,
|
||||
&itemId,&instance,value,
|
||||
&start_offset,&bytes,&flags))
|
||||
{
|
||||
setReason("Could not extract ACTION_SET request");
|
||||
return
|
||||
respondSimple(NULL,ACTION_ERROR,
|
||||
(unsigned char *)"Mal-formed SET request",
|
||||
0,transaction_id,recvttl,
|
||||
sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
|
||||
/* Get the stored value */
|
||||
oldl=65536;
|
||||
oldr=hlrGetVariable(hlr,ofs,itemId,instance,oldvalue,&oldl);
|
||||
if (oldr) {
|
||||
if (flags==SET_NOREPLACE) {
|
||||
oldl=0;
|
||||
} else {
|
||||
setReason("Tried to SET_NOCREATE/SET_REPLACE a non-existing value");
|
||||
return
|
||||
respondSimple(NULL,ACTION_ERROR,
|
||||
(unsigned char *)"Cannot SET NOCREATE/REPLACE a value that does not exist",
|
||||
0,transaction_id,recvttl,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
} else {
|
||||
if (flags==SET_NOREPLACE) {
|
||||
setReason("Tried to SET_NOREPLACE an existing value");
|
||||
if (debug&DEBUG_DNAREQUESTS) dump("Existing value (in SET_NOREPLACE flagged request)",oldvalue,oldl);
|
||||
return
|
||||
respondSimple(NULL,ACTION_ERROR,
|
||||
(unsigned char *)"Cannot SET NOREPLACE; a value exists",
|
||||
0,transaction_id,recvttl,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
}
|
||||
/* Replace the changed portion of the stored value */
|
||||
if ((start_offset+bytes)>oldl) {
|
||||
bzero(&oldvalue[oldl],start_offset+bytes-oldl);
|
||||
oldl=start_offset+bytes;
|
||||
}
|
||||
bcopy(&value[0],&oldvalue[start_offset],bytes);
|
||||
|
||||
/* Write new value back */
|
||||
if (hlrSetVariable(hlr,ofs,itemId,instance,oldvalue,oldl))
|
||||
{
|
||||
setReason("Failed to write variable");
|
||||
return
|
||||
respondSimple(NULL,ACTION_ERROR,
|
||||
(unsigned char *)"Failed to SET variable",
|
||||
0,transaction_id,recvttl,
|
||||
sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
if (debug&DEBUG_HLR) { fprintf(stderr,"HLR after writing:\n"); hlrDump(hlr,ofs); }
|
||||
|
||||
/* Reply that we wrote the fragment */
|
||||
respondSimple(sid,ACTION_WROTE,&packet[rofs],6,
|
||||
transaction_id,recvttl,
|
||||
sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
/* Advance to next record and keep searching */
|
||||
if (nextHlr(hlr,&ofs)) break;
|
||||
}
|
||||
break;
|
||||
case ACTION_GET:
|
||||
{
|
||||
@ -416,112 +255,132 @@ int processRequest(unsigned char *packet,int len,
|
||||
if (var_id&0x80) instance=packet[++pofs];
|
||||
pofs++;
|
||||
int offset=(packet[pofs]<<8)+packet[pofs+1]; pofs+=2;
|
||||
char *hlr_sid=NULL;
|
||||
char hlr_sid_s[SID_STRLEN+1];
|
||||
keyring_identity *responding_id=NULL;
|
||||
|
||||
pofs+=2;
|
||||
|
||||
if (debug&DEBUG_DNAREQUESTS) fprintf(stderr,"Processing ACTION_GET (var_id=%02x, instance=%02x, pofs=0x%x, len=%d)\n",var_id,instance,pofs,len);
|
||||
|
||||
ofs=0;
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Looking for hlr entries with sid='%s' / did='%s'\n",(sid&&sid[0])?sid:"null",did?did:"null");
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Looking for identities with sid='%s' / did='%s'\n",(sid&&sid[0])?sid:"null",did?did:"null");
|
||||
|
||||
/* Keyring only has DIDs in it for now.
|
||||
Location is implied, so we allow that */
|
||||
switch(var_id) {
|
||||
case VAR_DIDS:
|
||||
case VAR_LOCATIONS:
|
||||
break;
|
||||
default:
|
||||
return respondSimple(NULL,ACTION_ERROR,
|
||||
(unsigned char *)"Unsupported variable",
|
||||
0,transaction_id,recvttl,
|
||||
sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
|
||||
while(1)
|
||||
{
|
||||
struct hlrentry_handle *h;
|
||||
}
|
||||
|
||||
// if an empty did was passed in, get results from all hlr records
|
||||
if (*sid || *did){
|
||||
if (!findHlr(hlr,&ofs,sid,did)) break;
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"findHlr found a match @ 0x%x\n",ofs);
|
||||
{
|
||||
int cn=0,in=0,kp=0;
|
||||
int found=0;
|
||||
int count=0;
|
||||
while(cn<keyring->context_count) {
|
||||
found=0;
|
||||
if (sid) {
|
||||
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);
|
||||
}
|
||||
if (debug&DEBUG_HLR) hlrDump(hlr,ofs);
|
||||
|
||||
/* XXX consider taking action on this HLR
|
||||
(check PIN first depending on the action requested) */
|
||||
|
||||
/* Form a reply packet containing the requested data */
|
||||
|
||||
if (instance==0xff) instance=-1;
|
||||
|
||||
/* Step through HLR to find any matching instances of the requested variable */
|
||||
h=openhlrentry(hlr,ofs);
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"openhlrentry(hlr,%d) returned %p\n",ofs,h);
|
||||
while(h)
|
||||
{
|
||||
/* Is this the variable? */
|
||||
if (debug&DEBUG_HLR) fprintf(stderr," considering var_id=%02x, instance=%02x\n",
|
||||
h->var_id,h->var_instance);
|
||||
if (h->var_id==var_id)
|
||||
{
|
||||
if (h->var_instance==instance||instance==-1)
|
||||
{
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Sending matching variable value instance (instance #%d), value offset %d.\n",
|
||||
h->var_instance,offset);
|
||||
|
||||
// only send each value when the *next* record is found, that way we can easily stamp the last response with DONE
|
||||
if (sendDone>0)
|
||||
respondSimple(hlr_sid,ACTION_DATA,data,dlen,
|
||||
transaction_id,recvttl,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
struct response r;
|
||||
|
||||
dlen=0;
|
||||
|
||||
if (packageVariableSegment(data,&dlen,h,offset,MAX_DATA_BYTES+16))
|
||||
return setReason("packageVariableSegment() failed.");
|
||||
hlr_sid = hlrSid(hlr, ofs, hlr_sid_s);
|
||||
|
||||
sendDone++;
|
||||
}
|
||||
else
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Ignoring variable instance %d (not %d)\n",
|
||||
h->var_instance,instance);
|
||||
}
|
||||
else
|
||||
if (debug&DEBUG_HLR) fprintf(stderr,"Ignoring variable ID %d (not %d)\n",
|
||||
h->var_id,var_id);
|
||||
h=hlrentrygetent(h);
|
||||
if (found&&(instance==-1||instance==count)) {
|
||||
/* We have a matching identity/DID, now see what variable
|
||||
they want.
|
||||
VAR_DIDS and VAR_LOCATIONS are the only ones we support
|
||||
with the new keyring file format for now. */
|
||||
r.var_id=var_id;
|
||||
r.var_instance=instance;
|
||||
switch(var_id) {
|
||||
case VAR_DIDS:
|
||||
r.response=keyring->contexts[cn]->identities[in]
|
||||
->keypairs[kp]->private_key;
|
||||
r.value_len=strlen((char *)r.response);
|
||||
break;
|
||||
case VAR_LOCATIONS:
|
||||
r.response=(unsigned char *)"4000@";
|
||||
r.value_len=strlen((char *)r.response);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Advance to next record and keep searching */
|
||||
if (nextHlr(hlr,&ofs)) break;
|
||||
}
|
||||
if (sendDone)
|
||||
{
|
||||
data[dlen++]=ACTION_DONE;
|
||||
data[dlen++]=sendDone&0xff;
|
||||
respondSimple(hlr_sid,ACTION_DATA,data,dlen,transaction_id,
|
||||
recvttl,sender,CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
if (gatewayspec&&(var_id==VAR_LOCATIONS)&&did&&strlen(did))
|
||||
{
|
||||
/* We are a gateway, so offer connection via the gateway as well */
|
||||
unsigned char data[MAX_DATA_BYTES+16];
|
||||
int dlen=0;
|
||||
struct hlrentry_handle fake;
|
||||
unsigned char uri[1024];
|
||||
|
||||
/* We use asterisk to provide the gateway service,
|
||||
so we need to create a temporary extension in extensions.conf,
|
||||
ask asterisk to re-read extensions.conf, and then make sure it has
|
||||
a functional SIP gateway.
|
||||
*/
|
||||
if (!asteriskObtainGateway(sid,did,(char *)uri))
|
||||
{
|
||||
|
||||
fake.value_len=strlen((char *)uri);
|
||||
fake.var_id=var_id;
|
||||
fake.value=uri;
|
||||
|
||||
if (packageVariableSegment(data,&dlen,&fake,offset,MAX_DATA_BYTES+16))
|
||||
return setReason("packageVariableSegment() of gateway URI failed.");
|
||||
|
||||
char sid[SID_STRLEN+1];
|
||||
respondSimple(hlrSid(hlr, 0, sid),ACTION_DATA,data,dlen,
|
||||
transaction_id,recvttl,sender,
|
||||
CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For multiple packet responses, we want to tag only the
|
||||
last one with DONE, so we queue up the most recently generated
|
||||
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. */
|
||||
if (sendDone>0)
|
||||
/* Send previous packet */
|
||||
respondSimple(responding_id,ACTION_DATA,data,dlen,
|
||||
transaction_id,recvttl,sender,
|
||||
CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
/* Prepare new packet */
|
||||
dlen=0;
|
||||
if (packageVariableSegment(data,&dlen,&r,offset,
|
||||
MAX_DATA_BYTES+16))
|
||||
return setReason("packageVariableSegment() failed.");
|
||||
responding_id = keyring->contexts[cn]->identities[in];
|
||||
|
||||
/* Remember that we need to send this new packet */
|
||||
sendDone++;
|
||||
|
||||
count++;
|
||||
if (sid) in++; else kp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now, see if we have a final queued packet which needs marking with
|
||||
DONE and then sending. */
|
||||
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);
|
||||
}
|
||||
|
||||
if (gatewayspec&&(var_id==VAR_LOCATIONS)&&did&&strlen(did))
|
||||
{
|
||||
/* We are a gateway, so offer connection via the gateway as well */
|
||||
unsigned char data[MAX_DATA_BYTES+16];
|
||||
int dlen=0;
|
||||
struct response fake;
|
||||
unsigned char uri[1024];
|
||||
|
||||
/* We use asterisk to provide the gateway service,
|
||||
so we need to create a temporary extension in extensions.conf,
|
||||
ask asterisk to re-read extensions.conf, and then make sure it has
|
||||
a functional SIP gateway.
|
||||
*/
|
||||
if (!asteriskObtainGateway(sid,did,(char *)uri))
|
||||
{
|
||||
|
||||
fake.value_len=strlen((char *)uri);
|
||||
fake.var_id=var_id;
|
||||
fake.response=uri;
|
||||
|
||||
if (packageVariableSegment(data,&dlen,&fake,offset,MAX_DATA_BYTES+16))
|
||||
return setReason("packageVariableSegment() of gateway URI failed.");
|
||||
|
||||
WHY("Gateway claims to be 1st identity, when it should probably have its own identity");
|
||||
respondSimple(keyring->contexts[0]->identities[0],
|
||||
ACTION_DATA,data,dlen,
|
||||
transaction_id,recvttl,sender,
|
||||
CRYPT_CIPHERED|CRYPT_SIGNED);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Should we indicate the gateway is not available? */
|
||||
}
|
||||
}
|
||||
@ -542,7 +401,8 @@ int processRequest(unsigned char *packet,int len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int respondSimple(char *sid,int action,unsigned char *action_text,int action_len,
|
||||
int respondSimple(keyring_identity *id,
|
||||
int action,unsigned char *action_text,int action_len,
|
||||
unsigned char *transaction_id,int recvttl,
|
||||
struct sockaddr *recvaddr,int cryptoFlags)
|
||||
{
|
||||
@ -570,8 +430,8 @@ int respondSimple(char *sid,int action,unsigned char *action_text,int action_len
|
||||
/* Prepare the request packet */
|
||||
if (packetMakeHeader(packet,8000,packet_len,transaction_id,cryptoFlags))
|
||||
return WHY("packetMakeHeader() failed.");
|
||||
if (sid&&sid[0])
|
||||
{ if (packetSetSid(packet,8000,packet_len,sid))
|
||||
if (id)
|
||||
{ if (packetSetSidFromId(packet,8000,packet_len,id))
|
||||
return setReason("invalid SID in reply"); }
|
||||
else
|
||||
{ if (packetSetDid(packet,8000,packet_len,""))
|
||||
|
Loading…
x
Reference in New Issue
Block a user