#include <u.h>
#include <libc.h>
#include <bio.h>
#include <auth.h>
#include <mp.h>
#include <libsec.h>
enum{ ThumbTab = 1<<10 };
static Thumbprint*
tablehead(uchar *sum, Thumbprint *table)
{
return &table[((sum[0]<<8) + sum[1]) & (ThumbTab-1)];
}
void
freeThumbprints(Thumbprint *table)
{
Thumbprint *hd, *p, *q;
if(table == nil)
return;
for(hd = table; hd < table+ThumbTab; hd++){
for(p = hd->next; p && p != hd; p = q){
q = p->next;
free(p);
}
}
free(table);
}
int
okThumbprint(uchar *sum, Thumbprint *table)
{
Thumbprint *hd, *p;
if(table == nil)
return 0;
hd = tablehead(sum, table);
for(p = hd->next; p; p = p->next){
if(memcmp(sum, p->sha1, SHA1dlen) == 0)
return 1;
if(p == hd)
break;
}
return 0;
}
static int
loadThumbprints(char *file, Thumbprint *table, Thumbprint *crltab)
{
Thumbprint *hd, *entry;
char *line, *field[50];
uchar sum[SHA1dlen];
Biobuf *bin;
if(access(file, AEXIST) < 0)
return 0; /* not an error */
if((bin = Bopen(file, OREAD)) == nil)
return -1;
for(; (line = Brdstr(bin, '\n', 1)) != nil; free(line)){
if(tokenize(line, field, nelem(field)) < 2)
continue;
if(strcmp(field[0], "#include") == 0){
if(loadThumbprints(field[1], table, crltab) < 0)
goto err;
continue;
}
if(strcmp(field[0], "x509") != 0 || strncmp(field[1], "sha1=", 5) != 0)
continue;
field[1] += 5;
if(dec16(sum, SHA1dlen, field[1], strlen(field[1])) != SHA1dlen){
werrstr("malformed x509 entry in %s: %s", file, field[1]);
goto err;
}
if(crltab && okThumbprint(sum, crltab))
continue;
hd = tablehead(sum, table);
if(hd->next == nil)
entry = hd;
else {
if((entry = malloc(sizeof(*entry))) == nil)
goto err;
entry->next = hd->next;
}
hd->next = entry;
memcpy(entry->sha1, sum, SHA1dlen);
}
Bterm(bin);
return 0;
err:
free(line);
Bterm(bin);
return -1;
}
Thumbprint *
initThumbprints(char *ok, char *crl)
{
Thumbprint *table, *crltab;
table = crltab = nil;
if(crl){
if((crltab = malloc(ThumbTab * sizeof(*crltab))) == nil)
goto err;
memset(crltab, 0, ThumbTab * sizeof(*crltab));
if(loadThumbprints(crl, crltab, nil) < 0)
goto err;
}
if((table = malloc(ThumbTab * sizeof(*table))) == nil)
goto err;
memset(table, 0, ThumbTab * sizeof(*table));
if(loadThumbprints(ok, table, crltab) < 0){
freeThumbprints(table);
table = nil;
}
err:
freeThumbprints(crltab);
return table;
}
|