X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=privcache.c;h=5377c9049452500d36ce409cdee35fdcfc575f31;hb=851164246d09c84c7dd8d9c26d8cb90f0fdf3cea;hp=319732973624e5361a1fde039ec7be975e115d77;hpb=0037d80883eb0e4bde85537da04ab76dc747389a;p=secnet.git diff --git a/privcache.c b/privcache.c index 3197329..5377c90 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; @@ -37,17 +38,59 @@ struct privcache { struct hash_if *defhash; }; +static bool_t uncached_load_file( + const struct sigscheme_info *scheme, + const char *path, + struct buffer_if *databuf, + struct hash_if *defhash, + 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) { - bool_t ok=False; - FILE *f=0; - 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, + st->defhash, + &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 hash_if *defhash, + 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; - f = fopen(path,"rb"); + f=fopen(path,"rb"); if (!f) { if (errno == ENOENT) { slilog(log,M_DEBUG,"private key %s not found", @@ -56,64 +99,55 @@ static struct sigprivkey_if *uncached_get(struct privcache *st, slilog(log,M_ERR,"failed to open private key file %s", 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", path); - goto out; + goto error_out; } if (!feof(f)) { slilog(log,M_ERR,"private key file %s longer than max %d", - path, (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; - - slilog(log,M_ERR,"private key file %s not loaded (unknown algid)", - path); - goto out; - - found: - st->databuf.start=st->databuf.base; - st->databuf.size=got; + databuf->start=databuf->base; + databuf->size=got; struct cloc loc = { .file=path, .line=0 }; - ok=scheme->loadpriv(scheme, &st->databuf, &sigpriv, log, loc); - if (!ok) goto out; /* loadpriv will have logged */ + ok=scheme->loadpriv(scheme, databuf, &sigpriv, closure_r, log, loc); + if (!ok) goto error_out; /* loadpriv will have logged */ if (sigpriv->sethash) { - if (!st->defhash) { + if (!defhash) { slilog(log,M_ERR, - "private key %s requires `hash' config key for privcache to load", + "private key %s requires `hash' config key to load", path); - sigpriv->dispose(sigpriv->st); - sigpriv=0; - goto out; + goto error_out; } - sigpriv->sethash(sigpriv->st,st->defhash); + sigpriv->sethash(sigpriv->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; @@ -125,10 +159,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); } @@ -139,7 +173,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; } @@ -174,7 +208,7 @@ 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); @@ -185,7 +219,39 @@ static list_t *privcache_apply(closure_t *self, struct cloc 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 hash_if *defhash= + find_cl_if(context,"hash",CL_HASH,False,"load-private",loc); + + 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,defhash,&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); }