summaryrefslogtreecommitdiff
path: root/appl/cmd/ssh/authtis.b
blob: f06c10f16d6d2e06dba4fa23291c4f881f1a1692 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
implement Auth;

# TO DO: add chal/resp to Factotum

include "sys.m";
	sys: Sys;

include "keyring.m";
	kr: Keyring;
	IPint: import kr;

include "factotum.m";
	factotum: Factotum;
	Attr: import factotum;
	findattrval: import factotum;

include "sshio.m";
	sshio: Sshio;
	Conn, Msg: import sshio;
	debug: import sshio;

id(): int
{
	return SSH_AUTH_TIS;
}

init(mod: Sshio)
{
	sshio = mod;
	sys = load Sys Sys->PATH;
	kr = load Keyring Keyring->PATH;
	factotum = load Factotum Factotum->PATH;
	factotum->init();
}

firstmsg(): int
{
	return SSH_CMSG_AUTH_TIS;
}

authsrv(conn: ref Conn, nil: ref Msg): ref AuthInfo
{
	if((c := factotum->challenge(sys->sprint("proto=p9cr user=%q role=server", conn.user))) == nil){
#		sshlog("auth_challenge failed for %s", conn.user);
		return nil;
	}
	s := sys->sprint("Challenge: %s\nResponse: ", c.chal);
	m := Msg.mk(SSH_SMSG_AUTH_TIS_CHALLENGE, 4+len s);
	m.putstring(s);
	conn.out <-= m;

	m = sshio->recvmsg(conn, 0);
	if(m == nil)
		return nil;
	if(m.mtype != SSH_CMSG_AUTH_TIS_RESPONSE){
		#
		# apparently you can just give up on
		# this protocol and start a new one.
		#
		sshio->unrecvmsg(conn, m);
		return nil;
	}

	ai := factotum->response(c, m.getstring());
	if(ai == nil){
		debug(DBG_AUTH, sys->sprint("response rejected: %r\n"));
		return nil;
	}
	return ref AuthInfo(ai.cuid, ai.cap);
}

auth(c: ref Conn): int
{
	if(!c.interactive)
		return -1;

	debug(DBG_AUTH, "try TIS\n");
	c.out <-= Msg.mk(SSH_CMSG_AUTH_TIS, 0);

	m := sshio->recvmsg(c, -1);
	case m.mtype {
	SSH_SMSG_FAILURE =>
		return -1;
	SSH_SMSG_AUTH_TIS_CHALLENGE =>
		;
	* =>
		sshio->badmsg(m, SSH_SMSG_AUTH_TIS_CHALLENGE, nil);
	}

	chal := m.getstring();

	if((fd := sys->open("/dev/cons", Sys->ORDWR)) == nil)
		sshio->error(sys->sprint("can't open /dev/cons: %r"));

	sys->fprint(fd, "TIS Authentication\n%s", chal);
	resp := array[256] of byte;
	n := sys->read(fd, resp, len resp);
	if(n <= 0 || resp[0] == byte '\n')
		return -1;

	m = Msg.mk(SSH_CMSG_AUTH_TIS_RESPONSE, 4+n);
	m.put4(len resp);
	m.putbytes(resp, n);
	c.out <-= m;
	
	m = sshio->recvmsg(c, -1);
	case m.mtype {
	SSH_SMSG_SUCCESS =>
		return 0;
	SSH_SMSG_FAILURE =>
		return -1;
	* =>
		sshio->badmsg(m, 0, nil);
		return -1;
	}
}