Plan 9 from Bell Labs’s /usr/web/sources/contrib/rog/infauth/unpacked/appl/authsrc/getauthinfo.b

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


implement Getauthinfo;

#
# get and save a certificate from a signer in exchange for a valid secret
#

include "sys.m";
	sys: Sys;
	stderr: ref Sys->FD;
include "draw.m";
include "keyring.m";
	keyring: Keyring;
	IPint: import keyring;
include "security.m";
	login: Login;
include "sexprs.m";
	sexprs: Sexprs;
	Sexp: import sexprs;
include "string.m";
	str: String;
include "arg.m";
include "bufio.m";

Getauthinfo: module
{
	init:	fn(ctxt: ref Draw->Context, argv: list of string);
};

init(nil: ref Draw->Context, argv: list of string)
{
	sys = load Sys Sys->PATH;
	stderr = sys->fildes(2);
	arg := load Arg Arg->PATH;
	if (arg == nil)
		nomod(Arg->PATH);
	keyring = load Keyring Keyring->PATH;
	if(keyring == nil)
		nomod(Keyring->PATH);
	str = load String String->PATH;
	if(str == nil)
		nomod(String->PATH);
	login = load Login Login->PATH;
	if(login == nil)
		nomod(Login->PATH);
	sexprs = load Sexprs Sexprs->PATH;
	if(sexprs == nil)
		nomod(Sexprs->PATH);
	sexprs->init();
	signer := "$SIGNER";
	authname := user();
	password := "";
	havepw := 0;
	factotum := 0;
	showkey := 0;
	attrs: string;
	keyfile: string;

	arg->init(argv);
	arg->setusage("getauthinfo [-fF] [-s signer] [-u user] [-p password] [-k attrs] [keyfile]");
	while ((opt := arg->opt()) != 0){
		case opt {
		's' =>
			signer = arg->earg();
		'u' =>
			authname = arg->earg();
		'p' =>
			password = arg->earg();
			havepw = 1;
		'f' =>
			factotum = 1;
		'F' =>
			factotum = 1;
			showkey = 1;
		'k' =>
			attrs = arg->earg();
		* =>
			arg->usage();
		}
	}
	facfd: ref Sys->FD;
	argv = arg->argv();
	if (argv != nil && factotum || len argv != 1 && !factotum)
		arg->usage();

	if (factotum){
		if(showkey)
			facfd = sys->fildes(1);
		else if((facfd = sys->open("/mnt/factotum/ctl", Sys->OWRITE)) == nil)
			sys->fprint(stderr, "getauthinfo: cannot open factotum: %r\n");
	}else
		keyfile = hd argv;

	if(!havepw)
		password = readpassword();
	(err, info) := login->login(authname, password, netmkaddr(signer, "net", "inflogin"));
	if(err != nil){
		sys->fprint(stderr, "getauthinfo: failed to authenticate: %s\n", err);
		raise "fail:login failed";
	}
	if(factotum){
		if(sys->fprint(facfd, "key proto=infauth role=client !authinfo=%s user=%s signer=%s %s\n",
				authinfotostr(info), authname, signer, attrs) == -1){
			sys->fprint(stderr, "getauthinfo: cannot write key to factotum: %r\n");
			raise "fail:cannot write key";
		}
		if(sys->fprint(facfd, "key proto=infauth role=server !authinfo=%s user=%s signer=%s %s\n",
				authinfotostr(info), authname, signer, attrs) == -1){
			sys->fprint(stderr, "getauthinfo: cannot write key to factotum: %r\n");
			raise "fail:cannot write key";
		}
	}else{
		if (! (keyfile[0] == '/' || (len keyfile > 2 &&  keyfile[0:2] == "./")))
			keyfile = "/usr/" + user() + "/keyring/" + keyfile;
		# write to /keyring if user directory doesn't exist.
		if(keyring->writeauthinfo(keyfile, info) < 0){
			sys->fprint(stderr, "getauthinfo: can't write certificate to %s: %r\n", keyfile);
			raise "fail:bad file";
		}
	}
}

user(): string
{
	if ((fd := sys->open("/dev/user", sys->OREAD)) == nil)
		return nil;
	buf := array[128] of byte;
	if ((n := sys->read(fd, buf, len buf)) <= 0)
		return nil;
	return string buf[0:n];	
}

nomod(s: string)
{
	sys->fprint(stderr, "getauthinfo: can't load %s: %r\n", s);
	raise "fail:load";
}

readpassword(): string
{
	bufio := load Bufio Bufio->PATH;
	Iobuf: import bufio;
	stdin := bufio->fopen(sys->fildes(0), Sys->OREAD);
	
	cfd := sys->open("/dev/consctl", Sys->OWRITE);
	if (cfd == nil || sys->fprint(cfd, "rawon") <= 0)
		sys->fprint(stderr, "getauthinfo: warning: cannot hide typed password\n");
	sys->fprint(stderr, "password: ");
	s := "";
	while ((c := stdin.getc()) >= 0 && c != '\n'){
		case c {
		'\b' =>
			if (len s > 0)
				s = s[0:len s - 1];
		8r25 =>		# ^U
			s = nil;
		* =>
			s[len s] = c;
		}
	}
	sys->fprint(stderr, "\n");
	return s;
}

netmkaddr(addr, net, svc: string): string
{
	if(net == nil)
		net = "net";
	(n, nil) := sys->tokenize(addr, "!");
	if(n <= 1){
		if(svc== nil)
			return sys->sprint("%s!%s", net, addr);
		return sys->sprint("%s!%s!%s", net, addr, svc);
	}
	if(svc == nil || n > 2)
		return addr;
	return sys->sprint("%s!%s", addr, svc);
}

authinfotostr(ai: ref Keyring->Authinfo): string
{
	return (ref Sexp.List(
		ss(keyring->pktostr(ai.spk)) ::
		ss(keyring->certtostr(ai.cert)) ::
		ss(keyring->sktostr(ai.mysk)) ::
		sb(ai.alpha.iptobytes()) ::
		sb(ai.p.iptobytes()) ::
		nil
	)).b64text();
}

ss(s: string): ref Sexp.String
{
	return ref Sexp.String(s, nil);
}

sb(d: array of byte): ref Sexp.Binary
{
	return ref Sexp.Binary(d, nil);
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.