1package ssh
2
3import (
4	"fmt"
5	"testing"
6)
7
8func TestParseGSSAPIPayload(t *testing.T) {
9	payload := []byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x06, 0x09,
10		0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02}
11	res, err := parseGSSAPIPayload(payload)
12	if err != nil {
13		t.Fatal(err)
14	}
15	if ok := res.OIDS[0].Equal(krb5Mesh); !ok {
16		t.Fatalf("got %v, want %v", res, krb5Mesh)
17	}
18}
19
20func TestBuildMIC(t *testing.T) {
21	sessionID := []byte{134, 180, 134, 194, 62, 145, 171, 82, 119, 149, 254, 196, 125, 173, 177, 145, 187, 85, 53,
22		183, 44, 150, 219, 129, 166, 195, 19, 33, 209, 246, 175, 121}
23	username := "testuser"
24	service := "ssh-connection"
25	authMethod := "gssapi-with-mic"
26	expected := []byte{0, 0, 0, 32, 134, 180, 134, 194, 62, 145, 171, 82, 119, 149, 254, 196, 125, 173, 177, 145, 187, 85, 53, 183, 44, 150, 219, 129, 166, 195, 19, 33, 209, 246, 175, 121, 50, 0, 0, 0, 8, 116, 101, 115, 116, 117, 115, 101, 114, 0, 0, 0, 14, 115, 115, 104, 45, 99, 111, 110, 110, 101, 99, 116, 105, 111, 110, 0, 0, 0, 15, 103, 115, 115, 97, 112, 105, 45, 119, 105, 116, 104, 45, 109, 105, 99}
27	result := buildMIC(string(sessionID), username, service, authMethod)
28	if string(result) != string(expected) {
29		t.Fatalf("buildMic: got %v, want %v", result, expected)
30	}
31}
32
33type exchange struct {
34	outToken      string
35	expectedToken string
36}
37
38type FakeClient struct {
39	exchanges []*exchange
40	round     int
41	mic       []byte
42	maxRound  int
43}
44
45func (f *FakeClient) InitSecContext(target string, token []byte, isGSSDelegCreds bool) (outputToken []byte, needContinue bool, err error) {
46	if token == nil {
47		if f.exchanges[f.round].expectedToken != "" {
48			err = fmt.Errorf("got empty token, want %q", f.exchanges[f.round].expectedToken)
49		} else {
50			outputToken = []byte(f.exchanges[f.round].outToken)
51		}
52	} else {
53		if string(token) != string(f.exchanges[f.round].expectedToken) {
54			err = fmt.Errorf("got %q, want token %q", token, f.exchanges[f.round].expectedToken)
55		} else {
56			outputToken = []byte(f.exchanges[f.round].outToken)
57		}
58	}
59	f.round++
60	needContinue = f.round < f.maxRound
61	return
62}
63
64func (f *FakeClient) GetMIC(micField []byte) ([]byte, error) {
65	return f.mic, nil
66}
67
68func (f *FakeClient) DeleteSecContext() error {
69	return nil
70}
71
72type FakeServer struct {
73	exchanges   []*exchange
74	round       int
75	expectedMIC []byte
76	srcName     string
77	maxRound    int
78}
79
80func (f *FakeServer) AcceptSecContext(token []byte) (outputToken []byte, srcName string, needContinue bool, err error) {
81	if token == nil {
82		if f.exchanges[f.round].expectedToken != "" {
83			err = fmt.Errorf("got empty token, want %q", f.exchanges[f.round].expectedToken)
84		} else {
85			outputToken = []byte(f.exchanges[f.round].outToken)
86		}
87	} else {
88		if string(token) != string(f.exchanges[f.round].expectedToken) {
89			err = fmt.Errorf("got %q, want token %q", token, f.exchanges[f.round].expectedToken)
90		} else {
91			outputToken = []byte(f.exchanges[f.round].outToken)
92		}
93	}
94	f.round++
95	needContinue = f.round < f.maxRound
96	srcName = f.srcName
97	return
98}
99
100func (f *FakeServer) VerifyMIC(micField []byte, micToken []byte) error {
101	if string(micToken) != string(f.expectedMIC) {
102		return fmt.Errorf("got MICToken %q, want %q", micToken, f.expectedMIC)
103	}
104	return nil
105}
106
107func (f *FakeServer) DeleteSecContext() error {
108	return nil
109}
110