History

20081021-2253

Charles.Forsyth committed 18 years ago

Commit 85210ff1 parent aaafc859 files · +466 −11Browse files

Unified · Split

9 files
  1. CHANGES +3 −0
  2. appl/cmd/auth/ai2key.b +144 −0
  3. appl/cmd/auth/factotum/proto/infauth.b +54 −12
  4. appl/cmd/auth/mkfile +1 −0
  5. dis/auth/ai2key.dis +0 −0
  6. dis/auth/proto/infauth.dis +0 −0
  7. libinterp/keyring.c +1 −1
  8. man/8/INDEX +3 −0
  9. man/8/ai2key +262 −0
CHANGES+3−0
@@ -1,3 +1,6 @@
1+20081021
2+ /appl/cmd/auth/ai2key.b new command to convert authinfo files to factotum keys
3+ /appl/cmd/auth/factotum/proto/infauth.b allow new key format
14 20081019
25 /appl/cmd/man2html.b implement "\ " => " "
36 /man/3/prog change way a literal " was formatted
appl/cmd/auth/ai2key.b+144−0
@@ -0,0 +1,144 @@
1+implement 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+
11+include "sys.m";
12+ sys: Sys;
13+
14+include "draw.m";
15+
16+include "keyring.m";
17+ keyring: Keyring;
18+ Certificate, IPint, PK, SK: import keyring;
19+
20+include "daytime.m";
21+ daytime: Daytime;
22+
23+include "arg.m";
24+
25+Ai2fact: module
26+{
27+ init: fn(nil: ref Draw->Context, nil: list of string);
28+};
29+
30+init(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+
78+error(e: string)
79+{
80+ sys->fprint(sys->fildes(2), "ai2key: %s\n", e);
81+ raise "fail:error";
82+}
83+
84+filename(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
94+locations(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+
110+server(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+
118+certtostr(c: ref Certificate): string
119+{
120+ return dnl(keyring->certtostr(c));
121+}
122+
123+pktostr(pk: ref PK): string
124+{
125+ return dnl(keyring->pktostr(pk));
126+}
127+
128+sktostr(sk: ref SK): string
129+{
130+ return dnl(keyring->sktostr(sk));
131+}
132+
133+dnl(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+}
appl/cmd/auth/factotum/proto/infauth.b+54−12
@@ -139,9 +139,8 @@ interaction(attrs: list of ref Attr, io: ref IO): string · 138 unmodified lines
139139 senderr(io, e);
140140 break;
141141 Error1 =>
142− senderr(io, "missing your authentication data");
143− x: string = e;
144− return "remote: "+x;
142+ senderr(io, "failed"); # acknowledge error
143+ return remote(e);
145144 }
146145
147146 {
@@ -151,8 +150,7 @@ interaction(attrs: list of ref Attr, io: ref IO): string · 3 unmodified lines
151150 Error0 =>
152151 return e;
153152 Error1 =>
154− x: string = e;
155− return "remote: "+x;
153+ return remote(e);
156154 }
157155 if(err != nil)
158156 return err;
@@ -160,13 +158,26 @@ interaction(attrs: list of ref Attr, io: ref IO): string · 1 unmodified line
160158 return negotiatecrypto(io, key, ai, rattrs);
161159 }
162160
161+remote(s: string): string
162+{
163+ # account for strange earlier interface
164+ if(len s < 6 || s[0: 6] != "remote")
165+ return "remote: "+s;
166+ return s;
167+}
168+
169+# TO DO: exchange attr/value pairs, covered by hmac (use part of secret up to hmac block size of 64 bytes)
170+# the old scheme can be distinguished either by a prefix "attrs " or simply because the string contains "=",
171+# and the server side can then reply. the hmac is to prevent tampering.
163172 negotiatecrypto(io: ref IO, key: ref Key, ai: ref Authinfo, attrs: list of ref Sexp): string
164173 {
165174 role := authio->lookattrval(key.attrs, "role");
166175 alg: string;
167176 {
168177 if(role == "client"){
169− alg = authio->lookattrval(key.attrs, "alg");
178+ alg = authio->lookattrval(key.attrs, ":alg");
179+ if(alg == nil)
180+ alg = authio->lookattrval(key.attrs, "alg"); # old way
170181 if(alg == nil)
171182 alg = "md5/rc4_256";
172183 sendmsg(io, array of byte alg);
@@ -297,7 +308,8 @@ getmsg(io: ref IO): array of byte raises (Error0, Error1) · 124 unmodified lines
297308 if(len buf != m)
298309 raise Error0("io error: (impossible?) msg length " + string m);
299310 if(h[0] == '!'){
300−sys->print("got remote error: %s, len %d\n", string buf, len string buf);
311+ if(0)
312+ sys->print("got remote error: %q, len %d\n", string buf, len string buf);
301313 raise Error1(string buf);
302314 }
303315 return buf;
@@ -318,16 +330,46 @@ senderr(io: ref IO, e: string) · 14 unmodified lines
318330 io.write(buf, len buf);
319331 }
320332
333+# both the s-expression and k=v form are interim, until all
334+# the factotum implementations can manage public keys
335+# the s-expression form was the original one used by Inferno factotum
336+# the form in which Authinfo components are separate attributes is the
337+# one now used by Plan 9 and Plan 9 Ports factotum implementations
321338 keytoauthinfo(key:ref Key): (ref Keyring->Authinfo, string)
322339 {
323− if((s := authio->lookattrval(key.secrets, "!authinfo")) == nil){
324− # XXX could look up authinfo by hash at this point
325− return (nil, "no authinfo attribute");
326− }
340+ if((s := authio->lookattrval(key.secrets, "!authinfo")) != nil)
341+ return strtoauthinfo(s);
342+ # TO DO: could look up authinfo by hash
343+ ai := ref Keyring->Authinfo;
344+ if((s = kv(key.secrets, "!sk")) == nil || (ai.mysk = keyring->strtosk(s)) == nil)
345+ return (nil, "bad secret key");
346+ if((s = kv(key.attrs, "pk")) == nil || (ai.mypk = keyring->strtopk(s)) == nil)
347+ return (nil, "bad public key");
348+ if((s = kv(key.attrs, "cert")) == nil || (ai.cert = keyring->strtocert(s)) == nil)
349+ return (nil, "bad certificate");
350+ if((s = kv(key.attrs, "spk")) == nil || (ai.spk = keyring->strtopk(s)) == nil)
351+ return (nil, "bad signer public key");
352+ if((s = kv(key.attrs, "dh-alpha")) == nil || (ai.alpha = IPint.strtoip(s, 16)) == nil)
353+ return (nil, "bad value for alpha");
354+ if((s = kv(key.attrs, "dh-p")) == nil || (ai.p = IPint.strtoip(s, 16)) == nil)
355+ return (nil, "bad value for p");
356+ return (ai, nil);
357+}
327358
328− return strtoauthinfo(s);
359+kv(a: list of ref Attr, name: string): string
360+{
361+ return rnl(authio->lookattrval(a, name));
362+}
363+
364+rnl(s: string): string
365+{
366+ for(i := 0; i < len s; i++)
367+ if(s[i] == '^')
368+ s[i] = '\n';
369+ return s;
329370 }
330371
372+# s-expression form
331373 strtoauthinfo(s: string): (ref Keyring->Authinfo, string)
332374 {
333375 (se, err, nil) := Sexp.parse(s);
appl/cmd/auth/mkfile+1−0
@@ -5,6 +5,7 @@ DIRS=\ · 4 unmodified lines
55
66 TARG=\
77 aescbc.dis\
8+ ai2key.dis\
89 changelogin.dis\
910 countersigner.dis\
1011 convpasswd.dis\
dis/auth/ai2key.dis+0−0

Binary file not shown.

dis/auth/proto/infauth.dis+0−0

Binary file not shown.

libinterp/keyring.c+1−1
@@ -1696,7 +1696,7 @@ if(0)print("Y"); · 1695 unmodified lines
16961696 buf[n] = 0;
16971697 hiscert = strtocert(buf);
16981698 if(hiscert == H){
1699− err = "bad certificate";
1699+ err = "bad certificate syntax";
17001700 goto out;
17011701 }
17021702 certimmutable(hiscert); /* hide from the garbage collector */
man/8/INDEX+3−0
@@ -1,4 +1,5 @@
11 intro 0intro
2+ai2key ai2key
23 applylog applylog
34 updatelog applylog
45 bootpd bootpd
@@ -15,6 +16,7 @@ csquery cs · 10 unmodified lines
1516 dhcp dhcp
1617 dns dns
1718 dnsquery dns
19+dsagen ai2key
1820 fpgaload fpgaload
1921 ftl ftl
2022 getauthinfo getauthinfo
@@ -39,6 +41,7 @@ prep prep · 18 unmodified lines
3941 rdbgsrv rdbgsrv
4042 register register
4143 rip rip
44+rsagen ai2key
4245 rstyxd rstyxd
4346 styxd rstyxd
4447 shutdown shutdown
man/8/ai2key+262−0
@@ -0,0 +1,262 @@
1+.TH AI2KEY 8
2+.SH NAME
3+ai2key, dsagen, rsagen \- generate and reformat public keys
4+.SH SYNOPSIS
5+.B ai2key
6+[
7+.BI -t " tag"
8+]
9+.I keyfile
10+...
11+.P
12+.B dsagen
13+[
14+.BI -t " tag"
15+]
16+.PP
17+.B rsagen
18+[
19+.BI -b " nbits"
20+] [
21+.BI -t " tag"
22+]
23+.SH DESCRIPTION
24+.IR Factotum (4)
25+represents public keys as lists of attribute-value pairs, each key on a single line prefixed with the string
26+.BR key .
27+.PP
28+.I Ai2key
29+converts the original Inferno representation of authentication data,
30+in the format defined for
31+.B authinfo
32+by
33+.IR keytext (6),
34+to an attribute-value format accepted by
35+.IR factotum (4)
36+for the
37+.B infauth
38+authentication protocol.
39+For each
40+.I keyfile
41+it writes a single line on standard output, containing
42+the following fields:
43+.IP
44+.EX
45+.fi
46+.ti -3n
47+key proto=infauth
48+[
49+.I tag
50+]
51+.BI "sigalg=" pkalg - hashalg
52+[
53+.BI dom= host
54+]
55+.BI server= host
56+[
57+.BI service= svc
58+]
59+.BI "user=" name
60+.BI "signer=" name
61+.BI "pk=" pk
62+.BI "!sk=" sk
63+.BI spk= pk
64+.BI cert= cert
65+.BI dh-alpha= hex
66+.BI dh-p= hex
67+.EE
68+.PP
69+where
70+.RS
71+.TP 15n
72+.I pkalg
73+is
74+.BR dsa ,
75+.B elgamal
76+or
77+.BR rsa
78+.PD 0
79+.ns
80+.TP
81+.I hashalg
82+is
83+.B md5
84+or
85+.BR sha1
86+.br
87+.ns
88+.TP
89+.B user
90+is the user name associated with the key, as vouched for by the supporting
91+certificate
92+.BR cert
93+.br
94+.ns
95+.TP
96+.B signer
97+is the user name associated with the key that signed the certificate
98+.br
99+.ns
100+.TP
101+.B pk
102+is the user's public key
103+.br
104+.ns
105+.TP
106+.B !sk
107+is the user's private (secret) key
108+.br
109+.ns
110+.TP
111+.B spk
112+is the signer's public key
113+.br
114+.ns
115+.TP
116+.B cert
117+is the
118+.I certificate
119+.br
120+.ns
121+.TP
122+.BR dh-alpha ,\ dh-p
123+are the Diffie-Hellman parameters shared by the user and file servers.
124+.RE
125+.PD
126+.PP
127+The key is tagged by one or more of
128+.BR dom ,
129+.B server
130+and
131+.BR service ,
132+derived from the file name
133+.IR keyfile .
134+The server is
135+.RB ` * '
136+if
137+.I keyfile
138+is
139+.BR default .
140+Otherwise
141+.I keyfile
142+has the form
143+.IP
144+[
145+.IB net !
146+]
147+.I host
148+[
149+.BI ! srv
150+]
151+.PP
152+and
153+.B server
154+and
155+.B service
156+are set accordingly;
157+.B dom
158+is set if
159+.I host
160+looks like a domain name.
161+Key and certificate values have the form defined in
162+.IR keytext (6);
163+.I hex
164+is a large number in hexadecimal.
165+.PP
166+.I Dsagen
167+prints a randomly-generated DSA private key using the NIST-recommended algorithm.
168+If
169+.I tag
170+text is specified, it is printed after the
171+.B proto
172+attribute-value pair.
173+Typically,
174+.I tag
175+is a sequence of attribute-value comments describing the key.
176+A DSA key has the following attributes
177+.RS
178+.TP 8n
179+.B p
180+prime public modulus
181+.PD 0
182+.TP
183+.B q
184+prime group order; divides
185+.BR p -1
186+.TP
187+.B alpha
188+group generator
189+.TP
190+.B key
191+.BR alpha ^ !secret
192+mod
193+.B p
194+.TP
195+.B !secret
196+the secret exponent
197+.RE
198+.PD
199+.PP
200+.I Rsagen
201+prints a randomly generated RSA private key
202+whose
203+.B n
204+has exactly
205+.I nbits
206+(default 1024)
207+significant bits.
208+The key has the following attributes:
209+.RS
210+.TP
211+.B size
212+the number of significant bits in
213+.B n
214+.PD 0
215+.TP
216+.B ek
217+the encryption exponent
218+.TP
219+.B n
220+the product of
221+.B !p
222+and
223+.B !q
224+.TP
225+.B !dk
226+the decryption exponent
227+.TP
228+.B !p
229+a large prime
230+.TP
231+.B !q
232+another large prime
233+.TP
234+.B "!kp\fR, \fL!kq\fR, \fL!c2
235+parameters derived from the other attributes, cached to speed decryption
236+.RE
237+.PD
238+.PP
239+All the numbers in
240+.I dsagen
241+and
242+.I rsagen
243+output are in hexadecimal except RSA's
244+.BR size ,
245+which is decimal.
246+A public key omits the attributes beginning with
247+.L ! .
248+A key may have other attributes as well, for example a
249+.B service
250+attribute identifying how this key is typically used,
251+but to these utilities such attributes are merely comments.
252+They can be provided in a
253+.I tag
254+argument.
255+.SH SOURCE
256+.B /appl/cmd/auth/ai2key.b
257+.br
258+.B /appl/cmd/auth/dsagen.b
259+.br
260+.B /appl/cmd/auth/rsagen.b
261+.SH "SEE ALSO"
262+.IR factotum (4)