chiark / gitweb /
rsa: Provide dict context argument in load_ctx
[secnet.git] / privcache.c
index 1f46eb00d033c323e84e971618acd3a4b741b810..5377c9049452500d36ce409cdee35fdcfc575f31 100644 (file)
@@ -21,6 +21,7 @@
 #include "util.h"
 
 #define DEFAULT_SIZE 5
+#define DEFAULT_MAXPRIV_BYTES 4095
 
 struct ent {
     struct sigkeyid id;
@@ -37,11 +38,13 @@ struct privcache {
     struct hash_if *defhash;
 };
 
-static struct sigprivkey_if *uncached_load_file(
+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,
@@ -61,19 +64,26 @@ static struct sigprivkey_if *uncached_get(struct privcache *st,
           path);
     return 0;
 
- found:
-    return uncached_load_file(scheme,
+ 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 struct sigprivkey_if *uncached_load_file(
+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;
@@ -110,22 +120,23 @@ static struct sigprivkey_if *uncached_load_file(
     databuf->start=databuf->base;
     databuf->size=got;
     struct cloc loc = { .file=path, .line=0 };
-    ok=scheme->loadpriv(scheme, databuf, &sigpriv, log, loc);
+    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",
+ "private key %s requires `hash' config key to load",
                   path);
            goto error_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);
@@ -197,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);
@@ -208,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);
 }