summaryrefslogtreecommitdiff
path: root/appl/cmd/auth/createsignerkey.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/cmd/auth/createsignerkey.b')
-rw-r--r--appl/cmd/auth/createsignerkey.b144
1 files changed, 144 insertions, 0 deletions
diff --git a/appl/cmd/auth/createsignerkey.b b/appl/cmd/auth/createsignerkey.b
new file mode 100644
index 00000000..90a54b6f
--- /dev/null
+++ b/appl/cmd/auth/createsignerkey.b
@@ -0,0 +1,144 @@
+implement Createsignerkey;
+
+include "sys.m";
+ sys: Sys;
+
+include "draw.m";
+
+include "daytime.m";
+
+include "keyring.m";
+ kr: Keyring;
+
+include "arg.m";
+
+# signer key never expires
+SKexpire: con 0;
+
+# size in bits of modulus for public keys
+PKmodlen: con 512;
+
+# size in bits of modulus for diffie hellman
+DHmodlen: con 512;
+
+algs := array[] of {"rsa", "elgamal"}; # first entry is default
+
+Createsignerkey: module
+{
+ init: fn(ctxt: ref Draw->Context, argv: list of string);
+};
+
+init(nil: ref Draw->Context, argv: list of string)
+{
+ err: string;
+
+ sys = load Sys Sys->PATH;
+ kr = load Keyring Keyring->PATH;
+ if(kr == nil)
+ loaderr(Keyring->PATH);
+ arg := load Arg Arg->PATH;
+ if(arg == nil)
+ loaderr(Arg->PATH);
+
+ arg->init(argv);
+ arg->setusage("createsignerkey [-a algorithm] [-f keyfile] [-e ddmmyyyy] [-b size-in-bits] name-of-owner");
+ alg := algs[0];
+ filename := "/keydb/signerkey";
+ expire := SKexpire;
+ bits := PKmodlen;
+ while((c := arg->opt()) != 0){
+ case c {
+ 'a' =>
+ alg = arg->arg();
+ if(alg == nil)
+ arg->usage();
+ for(i:=0;; i++){
+ if(i >= len algs)
+ error(sys->sprint("unknown algorithm: %s", alg));
+ else if(alg == algs[i])
+ break;
+ }
+ 'f' or 'k' =>
+ filename = arg->earg();
+ 'e' =>
+ s := arg->earg();
+ (err, expire) = checkdate(s);
+ if(err != nil)
+ error(err);
+ 'b' =>
+ s := arg->earg();
+ bits = int s;
+ if(bits < 32 || bits > 4096)
+ error("modulus must be in the range of 32 to 4096 bits");
+ * =>
+ arg->usage();
+ }
+ }
+ argv = arg->argv();
+ if(argv == nil)
+ arg->usage();
+ arg = nil;
+
+ owner := hd argv;
+
+ # generate a local key, self-signed
+ info := ref Keyring->Authinfo;
+ info.mysk = kr->genSK(alg, owner, bits);
+ if(info.mysk == nil)
+ error(sys->sprint("algorithm %s not configured in system", alg));
+ info.mypk = kr->sktopk(info.mysk);
+ info.spk = kr->sktopk(info.mysk);
+ myPKbuf := array of byte kr->pktostr(info.mypk);
+ state := kr->sha1(myPKbuf, len myPKbuf, nil, nil);
+ info.cert = kr->sign(info.mysk, expire, state, "sha1");
+ (info.alpha, info.p) = kr->dhparams(DHmodlen);
+
+ if(kr->writeauthinfo(filename, info) < 0)
+ error(sys->sprint("can't write signerkey file %s: %r", filename));
+}
+
+loaderr(s: string)
+{
+ error(sys->sprint("can't load %s: %r", s));
+}
+
+error(s: string)
+{
+ sys->fprint(sys->fildes(2), "createsignerkey: %s\n", s);
+ raise "fail:error";
+}
+
+checkdate(word: string): (string, int)
+{
+ if(len word != 8)
+ return ("!date must be in form ddmmyyyy", 0);
+
+ daytime := load Daytime Daytime->PATH;
+ if(daytime == nil)
+ loaderr(Daytime->PATH);
+
+ now := daytime->now();
+
+ tm := daytime->local(now);
+ tm.sec = 59;
+ tm.min = 59;
+ tm.hour = 24;
+
+ tm.mday = int word[0:2];
+ if(tm.mday > 31 || tm.mday < 1)
+ return ("!bad day of month", 0);
+
+ tm.mon = int word[2:4] - 1;
+ if(tm.mon > 11 || tm.mday < 0)
+ return ("!bad month", 0);
+
+ tm.year = int word[4:8] - 1900;
+ if(tm.year < 70)
+ return ("!bad year", 0);
+
+ newdate := daytime->tm2epoch(tm);
+ if(newdate < now)
+ return ("!expiration date must be in the future", 0);
+
+ return (nil, newdate);
+}