xref: /inferno-os/appl/cmd/getauthinfo.b (revision d04a1cabb498e244b802f08427847789c1ce95f0)
1implement Getauthinfo;
2
3#
4# get and save a certificate from a signer in exchange for a valid secret
5#
6
7include "sys.m";
8	sys: Sys;
9	stdin, stdout, stderr: ref Sys->FD;
10
11include "draw.m";
12
13include "keyring.m";
14	kr: Keyring;
15
16include "security.m";
17	login: Login;
18
19include "string.m";
20	str: String;
21
22include "promptstring.b";
23
24Getauthinfo: module
25{
26	init:	fn(ctxt: ref Draw->Context, argv: list of string);
27};
28
29usage()
30{
31	sys->fprint(stderr, "usage: getauthinfo {net!hostname | default | /file}\n");
32	raise "fail:usage";
33}
34
35init(nil: ref Draw->Context, argv: list of string)
36{
37	sys = load Sys Sys->PATH;
38	stdin = sys->fildes(0);
39	stdout = sys->fildes(1);
40	stderr = sys->fildes(2);
41
42	# Disable echoing in RAWON mode
43	RAWON_STR = nil;
44
45	argv = tl argv;
46	if(argv == nil)
47		usage();
48	keyname := hd argv;
49	if(keyname == nil)
50		usage();
51
52	kr = load Keyring Keyring->PATH;
53	if(kr == nil)
54		nomod(Keyring->PATH);
55
56	str = load String String->PATH;
57	if(str == nil)
58		nomod(String->PATH);
59
60	login = load Login Login->PATH;
61	if(login == nil)
62		nomod(Login->PATH);
63
64	user := user();
65	path := keyname;
66	if(path[0] != '/' && (len path < 2 || path[0:2] != "./"))
67		path = "/usr/" + user + "/keyring/" + keyname;
68
69	signer := defaultsigner();
70	if(signer == nil){
71		sys->fprint(stderr, "getauthinfo: warning: can't get default signer server name\n");
72		signer = "$SIGNER";
73	}
74
75	passwd := "";
76	save := "yes";
77	for(;;) {
78		signer = promptstring("use signer", signer, RAWOFF);
79		user = promptstring("remote user name", user, RAWOFF);
80		passwd = promptstring("password", passwd, RAWON);
81
82		info := logon(user, passwd, signer, path, save);
83		if(info != nil)
84			break;
85	}
86}
87
88logon(user, passwd, server, path, save: string): ref Keyring->Authinfo
89{
90	(err, info) := login->login(user, passwd, "net!"+server+"!inflogin");
91	if(err != nil){
92		sys->fprint(stderr, "getauthinfo: failed to authenticate: %s\n", err);
93		return nil;
94	}
95
96	# save the info somewhere for later access
97	save = promptstring("save in file", save, RAWOFF);
98	if(save[0] != 'y'){
99		(dir, file) := str->splitr(path, "/");
100		if(sys->bind("#s", dir, Sys->MBEFORE) < 0){
101			sys->fprint(stderr, "getauthinfo: can't bind file channel on %s: %r\n", dir);
102			return nil;
103		}
104		filio := sys->file2chan(dir, file);
105		if(filio == nil) {
106			sys->fprint(stderr, "getauthinfo: can't make file2chan %s: %r\n", path);
107			return nil;
108		}
109		sync := chan of int;
110		spawn infofile(filio, sync);
111		<-sync;
112	}
113
114	if(kr->writeauthinfo(path, info) < 0) {
115		sys->fprint(stderr, "getauthinfo: can't write certificate to %s: %r\n", path);
116		return nil;
117	}
118
119	return info;
120}
121
122user(): string
123{
124	sys = load Sys Sys->PATH;
125
126	fd := sys->open("/dev/user", sys->OREAD);
127	if(fd == nil)
128		return "";
129
130	buf := array[128] of byte;
131	n := sys->read(fd, buf, len buf);
132	if(n < 0)
133		return "";
134
135	return string buf[0:n];
136}
137
138infofile(fileio: ref Sys->FileIO, sync: chan of int)
139{
140	infodata := array[0] of byte;
141
142	sys->pctl(Sys->NEWPGRP|Sys->NEWFD, nil);
143	sync <-= 1;
144
145	for(;;) alt {
146	(off, nbytes, nil, rc) := <-fileio.read =>
147		if(rc == nil)
148			break;
149		if(off > len infodata){
150			rc <-= (nil, nil);
151		} else {
152			if(off + nbytes > len infodata)
153				nbytes = len infodata - off;
154			rc <-= (infodata[off:off+nbytes], nil);
155		}
156
157	(off, data, nil, wc) := <-fileio.write =>
158		if(wc == nil)
159			break;
160
161		if(off != len infodata){
162			wc <-= (0, "cannot be rewritten");
163		} else {
164			nid := array[len infodata+len data] of byte;
165			nid[0:] = infodata;
166			nid[len infodata:] = data;
167			infodata = nid;
168			wc <-= (len data, nil);
169		}
170		data = nil;
171	}
172}
173
174# get default signer server name
175defaultsigner(): string
176{
177	return "$SIGNER";
178}
179
180nomod(s: string)
181{
182	sys->fprint(stderr, "getauthinfo: can't load %s: %r\n", s);
183	raise "fail:load";
184}
185