xref: /inferno-os/appl/cmd/auth/ai2key.b (revision bb0454063029bcd36bb713dc95bbce4c4fa43510)
1implement Ai2fact;
2
3# authinfo to factotum key set
4#	intermediate version, for use until revised Inferno authentication is ready
5
6
7# converts an old authinfo entry in keyring directory to a key for factotum
8#
9# keys are in proto=infauth, and include the data for the signed certificate, and the diffie-helman parameters
10
11include "sys.m";
12	sys: Sys;
13
14include "draw.m";
15
16include "keyring.m";
17	keyring: Keyring;
18	Certificate, IPint, PK, SK: import keyring;
19
20include "daytime.m";
21	daytime: Daytime;
22
23include "arg.m";
24
25Ai2fact: module
26{
27	init: fn(nil: ref Draw->Context, nil: list of string);
28};
29
30init(nil: ref Draw->Context, args: list of string)
31{
32	sys = load Sys Sys->PATH;
33	keyring = load Keyring Keyring->PATH;
34	daytime = load Daytime Daytime->PATH;
35
36	arg := load Arg Arg->PATH;
37	arg->init(args);
38	arg->setusage("ai2key [-t 'attr=value attr=value ...'] keyfile ...");
39	tag: string;
40	while((o := arg->opt()) != 0)
41		case o {
42		't' =>
43			tag = arg->earg();
44		* =>
45			arg->usage();
46		}
47	args = arg->argv();
48	if(args == nil)
49		arg->usage();
50	arg = nil;
51
52	now := daytime->now();
53	for(; args != nil; args = tl args){
54		keyfile := hd args;
55		ai := keyring->readauthinfo(keyfile);
56		if(ai == nil)
57			error(sys->sprint("cannot read %s: %r", keyfile));
58		if(ai.cert.exp != 0 && ai.cert.exp <= now){
59			sys->fprint(sys->fildes(2), "ai2key: %s: certificate expired -- key ignored\n", keyfile);
60			continue;
61		}
62
63		if(ai.cert.exp != 0)
64			expires := sys->sprint(" expires=%ud", ai.cert.exp);
65		ha := ai.cert.ha;
66		if(ha == "sha")
67			ha = "sha1";
68
69		if(tag != nil)
70			tag = " "+tag;
71
72		sys->print("key proto=infauth%s %s sigalg=%s-%s user=%q signer=%q pk=%s !sk=%s spk=%s cert=%s dh-alpha=%s dh-p=%s%s\n",
73			tag, locations(filename(keyfile)), ai.cert.sa.name, ha, ai.mypk.owner, ai.spk.owner, pktostr(ai.mypk), sktostr(ai.mysk),
74			pktostr(ai.spk), certtostr(ai.cert), ai.alpha.iptostr(16), ai.p.iptostr(16), expires);
75	}
76}
77
78error(e: string)
79{
80	sys->fprint(sys->fildes(2), "ai2key: %s\n", e);
81	raise "fail:error";
82}
83
84filename(s: string): string
85{
86	(nil, fld) := sys->tokenize(s, "/");
87	for(; fld != nil && tl fld != nil; fld = tl fld){
88		# skip
89	}
90	return hd fld;
91}
92
93# guess plausible domain, server and service attributes from the file name
94locations(file: string): string
95{
96	if(file == "default")
97		return "dom=* server=*";
98	(nf, flds) := sys->tokenize(file, "!");
99	case nf {
100	* =>
101		return sys->sprint("%s", server(file));
102	2 =>
103		return sys->sprint("%s", server(hd tl flds));
104	3 =>
105		# ignore network component
106		return sys->sprint("%s service=%q", server(hd tl flds), hd tl tl flds);
107	}
108}
109
110server(name: string): string
111{
112	# if the name contains dot(s), we'll treat it as a domain name
113	if(sys->tokenize(name, ".").t0 > 1)
114		return sys->sprint("dom=%q server=%q", name, name);
115	return sys->sprint("server=%q", name);
116}
117
118certtostr(c: ref Certificate): string
119{
120	return dnl(keyring->certtostr(c));
121}
122
123pktostr(pk: ref PK): string
124{
125	return dnl(keyring->pktostr(pk));
126}
127
128sktostr(sk: ref SK): string
129{
130	return dnl(keyring->sktostr(sk));
131}
132
133dnl(s: string): string
134{
135	for(i := 0; i < len s; i++)
136		if(s[i] == '\n')
137			s[i] = '^';
138	while(--i > 0 && s[i] == '^'){
139		# skip
140	}
141	if(i != len s)
142		return s[0: i+1];
143	return s;
144}
145