File: sasl_test.go

package info (click to toggle)
coyim 0.3.7-3
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 4,064 kB
  • ctags: 4,528
  • sloc: xml: 5,120; sh: 328; python: 286; makefile: 235; ruby: 51
file content (167 lines) | stat: -rw-r--r-- 6,063 bytes parent folder | download
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package xmpp

import (
	"encoding/xml"

	"github.com/twstrike/coyim/xmpp/data"
	"github.com/twstrike/coyim/xmpp/errors"

	. "gopkg.in/check.v1"
)

type SaslXmppSuite struct{}

var _ = Suite(&SaslXmppSuite{})

func (s *SaslXmppSuite) Test_authenticate_failsIfPlainIsNotAnOption(c *C) {
	conn := conn{}

	err := conn.Authenticate("", "")
	c.Assert(err, Equals, errUnsupportedSASLMechanism)
}

func (s *SaslXmppSuite) Test_authenticate_authenticatesWithUsernameAndPassword(c *C) {
	out := &mockConnIOReaderWriter{}
	mockIn := &mockConnIOReaderWriter{read: []byte("<sasl:success xmlns:sasl='urn:ietf:params:xml:ns:xmpp-sasl'></sasl:success>")}
	conn := conn{
		rawOut: out,
		in:     xml.NewDecoder(mockIn),
		features: data.StreamFeatures{
			Mechanisms: data.SaslMechanisms{
				Mechanism: []string{"FOO", "PLAIN"},
			},
		},
	}

	e := conn.Authenticate("foo", "bar")
	c.Assert(e, IsNil)
	c.Assert(string(out.write), Equals, "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>AGZvbwBiYXI=</auth>\n")
}

func (s *SaslXmppSuite) Test_authenticate_handlesFailure(c *C) {
	out := &mockConnIOReaderWriter{}
	mockIn := &mockConnIOReaderWriter{read: []byte("<sasl:failure xmlns:sasl='urn:ietf:params:xml:ns:xmpp-sasl'><foobar></foobar></sasl:failure>")}
	conn := conn{
		rawOut: out,
		in:     xml.NewDecoder(mockIn),
		features: data.StreamFeatures{
			Mechanisms: data.SaslMechanisms{
				Mechanism: []string{"FOO", "PLAIN"},
			},
		},
	}

	e := conn.Authenticate("foo", "bar")
	c.Assert(e.Error(), Equals, "xmpp: authentication failure: foobar")
}

func (s *SaslXmppSuite) Test_authenticate_handlesWrongResponses(c *C) {
	out := &mockConnIOReaderWriter{}
	mockIn := &mockConnIOReaderWriter{read: []byte("<sasl:something xmlns:sasl='urn:ietf:params:xml:ns:xmpp-sasl'></sasl:something>")}
	conn := conn{
		rawOut: out,
		in:     xml.NewDecoder(mockIn),
		features: data.StreamFeatures{
			Mechanisms: data.SaslMechanisms{
				Mechanism: []string{"FOO", "PLAIN"},
			},
		},
	}

	e := conn.Authenticate("foo", "bar")
	c.Assert(e, Equals, errors.ErrAuthenticationFailed)
}

func (s *SaslXmppSuite) Test_digestMD5_authenticatesWithUsernameAndPassword(c *C) {
	out := &mockConnIOReaderWriter{}
	mockIn := &mockConnIOReaderWriter{read: []byte(
		"<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>cmVhbG09ImNveS5pbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9ImF1dGgiLGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNz</challenge>\n" +
			"<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>cnNwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJhYmNkZmZmZA==</challenge>\n" +
			"<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>\n",
	)}

	mockRand := &mockConnIOReaderWriter{read: []byte{
		0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
	}}

	conn := conn{
		rawOut: out,
		in:     xml.NewDecoder(mockIn),
		rand:   mockRand,
		features: data.StreamFeatures{
			Mechanisms: data.SaslMechanisms{
				Mechanism: []string{"DIGEST-MD5"},
			},
		},
	}

	expectedOut := "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'></auth>\n" +
		"<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>Y2hhcnNldD11dGYtOCx1c2VybmFtZT0iZm9vIixyZWFsbT0iY295LmltIixub25jZT0iT0E2TUc5dEVRR20yaGgiLG5jPTAwMDAwMDAxLGNub25jZT0iMDEwMjAzMDQwNTA2MDciLGRpZ2VzdC11cmk9InhtcHAvY295LmltIixyZXNwb25zZT00ZGVlODYyNjkxOTZiNmUxNGI5Zjc2OWZhYmQ5OTdiZCxxb3A9YXV0aA==</response>\n" +
		"<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'></response>\n"

	e := conn.Authenticate("foo", "bar")
	c.Assert(e, IsNil)
	c.Assert(string(out.write), Equals, expectedOut)
}

func (s *SaslXmppSuite) Test_digestMD5_serverFailsToVerifyChallenge(c *C) {
	out := &mockConnIOReaderWriter{}
	mockIn := &mockConnIOReaderWriter{read: []byte(
		"<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>cmVhbG09ImNveS5pbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9ImF1dGgiLGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNz</challenge>\n" +
			"<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>",
	)}

	mockRand := &mockConnIOReaderWriter{read: []byte{
		0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
	}}

	conn := conn{
		rawOut: out,
		in:     xml.NewDecoder(mockIn),
		rand:   mockRand,
		features: data.StreamFeatures{
			Mechanisms: data.SaslMechanisms{
				Mechanism: []string{"DIGEST-MD5"},
			},
		},
	}

	expectedOut := "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'></auth>\n" +
		"<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>Y2hhcnNldD11dGYtOCx1c2VybmFtZT0iZm9vIixyZWFsbT0iY295LmltIixub25jZT0iT0E2TUc5dEVRR20yaGgiLG5jPTAwMDAwMDAxLGNub25jZT0iMDEwMjAzMDQwNTA2MDciLGRpZ2VzdC11cmk9InhtcHAvY295LmltIixyZXNwb25zZT00ZGVlODYyNjkxOTZiNmUxNGI5Zjc2OWZhYmQ5OTdiZCxxb3A9YXV0aA==</response>\n"

	e := conn.Authenticate("foo", "bar")
	c.Assert(e.Error(), Equals, "xmpp: unexpected <response> in urn:ietf:params:xml:ns:xmpp-sasl")
	c.Assert(string(out.write), Equals, expectedOut)
}

func (s *SaslXmppSuite) Test_scramSHA1Auth_authenticatesWithUsernameAndPassword(c *C) {
	out := &mockConnIOReaderWriter{}
	mockIn := &mockConnIOReaderWriter{read: []byte(
		"<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>cj03ZjI5MjhmOWRkYTU2ZDNyZmNOSFlKWTFaVnZXVnM3aixzPVFTWENSK1E2c2VrOGJmOTIsaT00MDk2</challenge>\n" +
			"<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>dj1FL1E5T3BnUWhNd1hjWEhtNGU3N3Q4b2lIT0E9</success>\n",
	)}

	mockRand := &mockConnIOReaderWriter{read: []byte{
		0x7f, 0x29, 0x28, 0xf9, 0xdd, 0xa5, 0x6d, 0xb1,
		0x60, 0x38, 0xd4, 0x6f, 0xf6, 0xa9, 0x31, 0x75,
		0xac, 0xb,
	}}

	conn := conn{
		rawOut: out,
		in:     xml.NewDecoder(mockIn),
		rand:   mockRand,
		features: data.StreamFeatures{
			Mechanisms: data.SaslMechanisms{
				Mechanism: []string{"SCRAM-SHA-1"},
			},
		},
	}

	expectedOut := "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='SCRAM-SHA-1'>biwsbj11c2VyLHI9N2YyOTI4ZjlkZGE1NmQ=</auth>\n" +
		"<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>Yz1iaXdzLHI9N2YyOTI4ZjlkZGE1NmQzcmZjTkhZSlkxWlZ2V1ZzN2oscD1KbWYrcWVpSG5jTXRaSjZ3YnJ5ZFdOQ2N4V1E9</response>\n"

	e := conn.Authenticate("user", "pencil")
	c.Assert(e, IsNil)
	c.Assert(string(out.write), Equals, expectedOut)
}