X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=privcache.c;h=d790c30ad07402a1325c8340a3fdd169618bcaa7;hb=147b444d6faa9a621e33d653b7a72c29724203c3;hp=ba756ffda8d38117ff766935103e86221b501c7d;hpb=e0e1a01632cf95c0df96933b3c9b8ee67b76a311;p=secnet.git diff --git a/privcache.c b/privcache.c index ba756ff..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,22 +35,22 @@ 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) { - 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; - struct hash_if *defhash=st->defhash; - struct buffer_if *databuf=&st->databuf; - - struct sigprivkey_if *sigpriv=0; const struct sigscheme_info *scheme; for (scheme=sigschemes; scheme->name; @@ -59,10 +60,33 @@ static struct sigprivkey_if *uncached_get(struct privcache *st, slilog(log,M_ERR,"private key file %s not loaded (unknown algid)", path); - goto out; + 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; +} - found: - f = fopen(path,"rb"); +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; + + f=fopen(path,"rb"); if (!f) { if (errno == ENOENT) { slilog(log,M_DEBUG,"private key %s not found", @@ -71,7 +95,7 @@ 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); @@ -80,42 +104,37 @@ static struct sigprivkey_if *uncached_get(struct privcache *st, 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)databuf->alloclen); - goto out; + goto error_out; } fclose(f); f=0; databuf->start=databuf->base; databuf->size=got; struct cloc loc = { .file=path, .line=0 }; - ok=scheme->loadpriv(scheme, 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 (!defhash) { - slilog(log,M_ERR, - "private key %s requires `hash' config key for privcache to load", - path); - sigpriv->dispose(sigpriv->st); - sigpriv=0; - goto out; - } - 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; @@ -127,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); } @@ -141,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; } @@ -162,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) @@ -176,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); }