mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-19 05:07:56 +00:00
208 lines
5.4 KiB
C
208 lines
5.4 KiB
C
/*
|
|
Copyright (C) 2010-2012 Paul Gardner-Stephen, Serval Project.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "serval.h"
|
|
|
|
|
|
/*
|
|
Open keyring file, read BAM and create initial context using the
|
|
stored salt. */
|
|
keyring_file *keyring_open(char *file)
|
|
{
|
|
/* Allocate structure */
|
|
keyring_file *k=calloc(sizeof(keyring_file),1);
|
|
if (!k) { WHY("calloc() failed"); return NULL; }
|
|
|
|
/* Open keyring file read-write if we can, else use it read-only */
|
|
k->file=fopen(file,"r+");
|
|
if (!k->file) k->file=fopen(file,"r");
|
|
if (!k->file) {
|
|
WHY("Could not open keyring file");
|
|
keyring_free(k);
|
|
return NULL;
|
|
}
|
|
if (fseeko(k->file,0,SEEK_END))
|
|
{
|
|
WHY("Could not seek to end of keyring file");
|
|
keyring_free(k);
|
|
return NULL;
|
|
}
|
|
k->file_size=ftello(k->file);
|
|
|
|
/* Read BAMs for each slab in the file */
|
|
keyring_bam **b=&k->bam;
|
|
off_t offset=0;
|
|
while(offset<k->file_size) {
|
|
/* Read bitmap from slab.
|
|
Also, if offset is zero, read the salt */
|
|
if (fseeko(k->file,offset,SEEK_SET))
|
|
{
|
|
WHY("Could not seek to BAM in keyring file");
|
|
keyring_free(k);
|
|
return NULL;
|
|
}
|
|
*b=calloc(sizeof(keyring_bam),1);
|
|
if (!(*b))
|
|
{
|
|
WHY("Could not allocate keyring_bam structure for key ring file");
|
|
keyring_free(k);
|
|
return NULL;
|
|
}
|
|
(*b)->file_offset=offset;
|
|
/* Read bitmap */
|
|
int r=fread(&(*b)->bitmap[0],KEYRING_BAM_BYTES,1,k->file);
|
|
if (r!=1)
|
|
{
|
|
WHY("Could not read BAM from keyring file");
|
|
keyring_free(k);
|
|
return NULL;
|
|
}
|
|
|
|
/* Read salt if this is the first bitmap block.
|
|
We setup a context for this self-supplied key-ring salt.
|
|
(other keyring salts may be provided later on, resulting in
|
|
multiple contexts being loaded) */
|
|
if (!offset) {
|
|
k->contexts[0]=calloc(sizeof(keyring_context),1);
|
|
if (!k->contexts[0])
|
|
{
|
|
WHY("Could not allocate keyring_context for keyring file");
|
|
keyring_free(k);
|
|
return NULL;
|
|
}
|
|
k->contexts[0]->KeyRingSaltLen=KEYRING_PAGE_SIZE-KEYRING_BAM_BYTES;
|
|
k->contexts[0]->KeyRingSalt=malloc(k->contexts[0]->KeyRingSaltLen);
|
|
if (!k->contexts[0]->KeyRingSalt)
|
|
{
|
|
WHY("Could not allocate keyring_context->salt for keyring file");
|
|
keyring_free(k);
|
|
return NULL;
|
|
}
|
|
|
|
r=fread(&k->contexts[0]->KeyRingSalt[0],k->contexts[0]->KeyRingSaltLen,1,k->file);
|
|
if (r!=1)
|
|
{
|
|
WHY("Could not read salt from keyring file");
|
|
keyring_free(k);
|
|
return NULL;
|
|
}
|
|
k->context_count=1;
|
|
}
|
|
|
|
/* Skip to next slab, and find next bam pointer. */
|
|
offset+=KEYRING_PAGE_SIZE*(KEYRING_BAM_BYTES<<3);
|
|
b=&(*b)->next;
|
|
}
|
|
|
|
return k;
|
|
}
|
|
|
|
void keyring_free(keyring_file *k)
|
|
{
|
|
int i;
|
|
if (!k) return;
|
|
|
|
/* Close keyring file handle */
|
|
if (k->file) fclose(k->file);
|
|
k->file=NULL;
|
|
|
|
/* Free BAMs (no substructure, so easy) */
|
|
keyring_bam *b=k->bam;
|
|
while(b) {
|
|
keyring_bam *last_bam=b;
|
|
b=b->next;
|
|
/* Clear out any private data */
|
|
bzero(last_bam,sizeof(keyring_bam));
|
|
/* release structure */
|
|
free(last_bam);
|
|
}
|
|
|
|
/* Free contexts (including subordinate identities and dynamically allocated salt strings).
|
|
Don't forget to overwrite any private data. */
|
|
for(i=0;i<KEYRING_MAX_CONTEXTS;i++)
|
|
if (k->contexts[i]) {
|
|
keyring_free_context(k->contexts[i]);
|
|
k->contexts[i]=NULL;
|
|
}
|
|
|
|
/* Wipe everything, just to be sure. */
|
|
bzero(k,sizeof(keyring_file));
|
|
|
|
return;
|
|
}
|
|
|
|
void keyring_free_context(keyring_context *c)
|
|
{
|
|
int i;
|
|
if (!c) return;
|
|
|
|
if (c->KeyRingPin) {
|
|
/* Wipe pin before freeing (slightly tricky since this is a variable length string */
|
|
for(i=0;c->KeyRingPin[i];i++) c->KeyRingPin[i]=' '; i=0;
|
|
free(c->KeyRingPin); c->KeyRingPin=NULL;
|
|
}
|
|
if (c->KeyRingSalt) {
|
|
bzero(c->KeyRingSalt,c->KeyRingSaltLen);
|
|
c->KeyRingSalt=NULL;
|
|
c->KeyRingSaltLen=0;
|
|
}
|
|
|
|
/* Wipe out any loaded identities */
|
|
for(i=0;i<KEYRING_MAX_IDENTITIES;i++)
|
|
if (c->identities[i]) keyring_free_identity(c->identities[i]);
|
|
|
|
/* Make sure any private data is wiped out */
|
|
bzero(c,sizeof(keyring_context));
|
|
|
|
return;
|
|
}
|
|
|
|
void keyring_free_identity(keyring_identity *id)
|
|
{
|
|
int i;
|
|
if (id->PKRPin) {
|
|
/* Wipe pin before freeing (slightly tricky since this is a variable length string */
|
|
for(i=0;id->PKRPin[i];i++) id->PKRPin[i]=' '; i=0;
|
|
free(id->PKRPin); id->PKRPin=NULL;
|
|
}
|
|
|
|
for(i=0;i<PKR_MAX_KEYPAIRS;i++)
|
|
if (id->keypairs[i])
|
|
keyring_free_keypair(id->keypairs[i]);
|
|
|
|
bzero(id,sizeof(keyring_identity));
|
|
return;
|
|
}
|
|
|
|
void keyring_free_keypair(keypair *kp)
|
|
{
|
|
if (kp->private_key) {
|
|
bzero(kp->private_key,kp->private_key_len);
|
|
free(kp->private_key);
|
|
kp->private_key=NULL;
|
|
}
|
|
if (kp->public_key) {
|
|
bzero(kp->public_key,kp->public_key_len);
|
|
free(kp->public_key);
|
|
kp->public_key=NULL;
|
|
}
|
|
|
|
bzero(kp,sizeof(keypair));
|
|
return;
|
|
}
|