X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=privcache.c;h=d790c30ad07402a1325c8340a3fdd169618bcaa7;hb=564022994befb8f71b89ae015751b22c34ae3ee8;hp=790281df61fa4e48608fceb7f9335f135a7116db;hpb=8c324896acdd5e38207cce993afb8657aae52a8e;p=secnet.git diff --git a/privcache.c b/privcache.c index 790281d..d790c30 100644 --- a/privcache.c +++ b/privcache.c @@ -21,6 +21,7 @@ #include "util.h" #define DEFAULT_SIZE 5 +#define DEFAULT_MAXPRIV_BYTES 4095 struct ent { struct sigkeyid id; @@ -34,84 +35,106 @@ struct privcache { struct pathprefix_template path; struct ent *ents; struct buffer_if databuf; - struct hash_if *defhash; }; +static bool_t uncached_load_file( + const struct sigscheme_info *scheme, + const char *path, + struct buffer_if *databuf, + struct sigprivkey_if **sigpriv_r, + closure_t **closure_r, + struct log_if *log); + static struct sigprivkey_if *uncached_get(struct privcache *st, const struct sigkeyid *id, struct log_if *log) +{ + sprintf(st->path.write_here, SIGKEYID_PR_FMT, SIGKEYID_PR_VAL(id)); + + const char *path=st->path.buffer; + const struct sigscheme_info *scheme; + for (scheme=sigschemes; + scheme->name; + scheme++) + if (scheme->algid == id->b[GRPIDSZ]) + goto found; + + slilog(log,M_ERR,"private key file %s not loaded (unknown algid)", + path); + return 0; + + found:; + struct sigprivkey_if *sigpriv; + closure_t *cl; + bool_t ok=uncached_load_file(scheme, + path, + &st->databuf, + &sigpriv, + &cl, + log); + return ok ? sigpriv : 0; +} + +static bool_t uncached_load_file( + const struct sigscheme_info *scheme, + const char *path, + struct buffer_if *databuf, + struct sigprivkey_if **sigpriv_r, + closure_t **closure_r, + struct log_if *log) { bool_t ok=False; FILE *f=0; + struct sigprivkey_if *sigpriv=0; - sprintf(st->path.write_here, SIGKEYID_PR_FMT, SIGKEYID_PR_VAL(id)); - - f = fopen(st->path.buffer,"rb"); + f=fopen(path,"rb"); if (!f) { if (errno == ENOENT) { slilog(log,M_DEBUG,"private key %s not found", - st->path.buffer); + path); } else { slilog(log,M_ERR,"failed to open private key file %s", - st->path.buffer); + path); } - goto out; + goto error_out; } setbuf(f,0); - buffer_init(&st->databuf,0); - ssize_t got=fread(st->databuf.base,1,st->databuf.alloclen,f); + buffer_init(databuf,0); + ssize_t got=fread(databuf->base,1,databuf->alloclen,f); if (ferror(f)) { slilog(log,M_ERR,"failed to read private-key file %s", - st->path.buffer); - goto out; + path); + goto error_out; } if (!feof(f)) { slilog(log,M_ERR,"private key file %s longer than max %d", - st->path.buffer, (int)st->databuf.alloclen); - goto out; + path, (int)databuf->alloclen); + goto error_out; } fclose(f); f=0; - struct sigprivkey_if *sigpriv=0; - const struct sigscheme_info *scheme; - for (scheme=sigschemes; - scheme->name; - scheme++) - if (scheme->algid == id->b[GRPIDSZ]) - goto found; + databuf->start=databuf->base; + databuf->size=got; + struct cloc loc = { .file=path, .line=0 }; + ok=scheme->loadpriv(scheme, databuf, &sigpriv, closure_r, log, loc); + if (!ok) goto error_out; /* loadpriv will have logged */ - slilog(log,M_ERR,"private key file %s not loaded (unknown algid)", - st->path.buffer); - goto out; - - found: - st->databuf.start=st->databuf.base; - st->databuf.size=got; - struct cloc loc = { .file=st->path.buffer, .line=0 }; - ok=scheme->loadpriv(scheme, &st->databuf, &sigpriv, log, loc); - if (!ok) goto out; /* loadpriv will have logged */ - - if (sigpriv->sethash) { - if (!st->defhash) { - slilog(log,M_ERR, - "private key %s requires `hash' config key for privcache to load", - st->path.buffer); - sigpriv->dispose(sigpriv->st); - sigpriv=0; - goto out; - } - sigpriv->sethash(sigpriv->st,st->defhash); - } + *sigpriv_r=sigpriv; out: if (f) fclose(f); - return ok ? sigpriv : 0; + return ok; + + error_out: + if (sigpriv) sigpriv->dispose(sigpriv->st); + ok=False; + goto out; } static struct sigprivkey_if *privcache_lookup(void *sst, const struct sigkeyid *id, struct log_if *log) { - struct privcache *st = sst; + struct privcache *st=sst; int was; struct ent result; @@ -123,10 +146,10 @@ static struct sigprivkey_if *privcache_lookup(void *sst, } if (st->used < st->alloc) { - was = st->used; + was=st->used; st->used++; } else { - was = st->used-1; + was=st->used-1; if (st->ents[was].sigpriv) { st->ents[was].sigpriv->dispose(st->ents[was].sigpriv->st); } @@ -137,7 +160,7 @@ static struct sigprivkey_if *privcache_lookup(void *sst, found: memmove(&st->ents[1], &st->ents[0], sizeof(st->ents[0]) * was); - st->ents[0] = result; + st->ents[0]=result; return result.sigpriv; } @@ -158,7 +181,6 @@ static list_t *privcache_apply(closure_t *self, struct cloc loc, st->ents=0; st->path.buffer=0; st->used=st->alloc=0; - st->defhash=0; item=list_elem(args,0); if (!item || item->type!=t_dict) @@ -172,18 +194,45 @@ static list_t *privcache_apply(closure_t *self, struct cloc loc, st->used=0; int32_t buflen=dict_read_number(dict,"privkey-max",False,"privcache",loc, - 4095); + DEFAULT_MAXPRIV_BYTES); buffer_new(&st->databuf,buflen+1); const char *path=dict_read_string(dict,"privkeys",True,"privcache",loc); pathprefix_template_init(&st->path,path,KEYIDSZ*2); - st->defhash=find_cl_if(dict,"hash",CL_HASH,False,"site",loc); - return new_closure(&st->cl); } +static list_t *loadprivate_apply(closure_t *self, struct cloc loc, + dict_t *context, list_t *args) +{ + CL_GET_STR_ARG(0,algname,"algorithm name"); + CL_GET_STR_ARG(1,path,"private key path"); + + const struct sigscheme_info *sch=sigscheme_lookup(algname); + if (!sch) cfgfatal(algname_i->loc,"load-private", + "unknown algorithm `%s'",algname); + + struct buffer_if databuf; + buffer_new(&databuf,DEFAULT_MAXPRIV_BYTES); + BUF_ALLOC(&databuf,"load-private data buf"); + + struct cfgfile_log log; + cfgfile_log_init(&log,loc,"load-private"); + + struct sigprivkey_if *sigpriv; + closure_t *cl; + bool_t ok= + uncached_load_file(sch,path,&databuf,&sigpriv,&cl,&log.log); + if (!ok) cfgfatal(loc,"load-private","private key loading failed"); + + BUF_FREE(&databuf); + buffer_destroy(&databuf); + return new_closure(cl); +} + void privcache_module(dict_t *dict) { add_closure(dict,"priv-cache",privcache_apply); + add_closure(dict,"load-private",loadprivate_apply); }