Mercurial > go > multipass
comparison auth/auth_test.go @ 0:c18bc7b9d1d9
Basic binaries. checkpassword doesn't yet work.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Sat, 24 Oct 2015 21:32:03 -0400 |
parents | |
children | 1c194fa9bbf4 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c18bc7b9d1d9 |
---|---|
1 package auth | |
2 | |
3 import ( | |
4 "regexp" | |
5 "testing" | |
6 ) | |
7 | |
8 var passPattern *regexp.Regexp = regexp.MustCompile(`^(?:[a-z]{4}-){3}[a-z]{4}$`) | |
9 | |
10 const basicShadow = "jhh:9999:$2a$12$tcv2MrtXgibAJHsSwVfHiOevXBFmiGy0HTNoOB8QzIhEh46iWS1uC:YW55dGhpbmcgbW9yZSB0aGFuIDUgcmVwcyBpcyBjYXJkaW8=" | |
11 const extraDataShadow = "skw:1:$2a$12$lINQdYWHOcLKoqhNOr3mNOpZSAu5JOBS2F7T/VDfYn2rvv6qUJehG::additional:fields" | |
12 | |
13 func TestEntryFromShadow(t *testing.T) { | |
14 cases := []struct { | |
15 shadow string | |
16 wantErr bool | |
17 username string | |
18 id uint64 | |
19 hash string | |
20 description string | |
21 rest []string | |
22 }{ | |
23 { | |
24 shadow: "pfish:1234:$2a$12$apFtWGXKtWBavVy5eo.22Ohs43GudT5IYTqyQkIBX9LpS7YtvKBpa", | |
25 username: "pfish", | |
26 id: 1234, | |
27 hash: "$2a$12$apFtWGXKtWBavVy5eo.22Ohs43GudT5IYTqyQkIBX9LpS7YtvKBpa", | |
28 }, | |
29 { | |
30 shadow: basicShadow, | |
31 username: "jhh", | |
32 id: 9999, | |
33 hash: "$2a$12$tcv2MrtXgibAJHsSwVfHiOevXBFmiGy0HTNoOB8QzIhEh46iWS1uC", | |
34 description: "anything more than 5 reps is cardio", | |
35 }, | |
36 { | |
37 shadow: extraDataShadow, | |
38 username: "skw", | |
39 id: 1, | |
40 hash: "$2a$12$lINQdYWHOcLKoqhNOr3mNOpZSAu5JOBS2F7T/VDfYn2rvv6qUJehG", | |
41 rest: []string{"additional", "fields"}, | |
42 }, | |
43 { | |
44 shadow: "user:one:bogushash", | |
45 wantErr: true, | |
46 }, | |
47 { | |
48 shadow: "user:-1:bogushash", | |
49 wantErr: true, | |
50 }, | |
51 { | |
52 shadow: "tooshort", | |
53 wantErr: true, | |
54 }, | |
55 { | |
56 shadow: "test:0:bogushash:invalid base64", | |
57 wantErr: true, | |
58 }, | |
59 } | |
60 for _, c := range cases { | |
61 entry, err := EntryFromShadow(c.shadow) | |
62 if c.wantErr { | |
63 if err == nil { | |
64 t.Errorf("EntryFromShadow(%q) == _, nil; want non-nil err", c.shadow) | |
65 } | |
66 continue | |
67 } | |
68 if err != nil { | |
69 t.Errorf("EntryFromShadow(%q) == _, %q; want nil err", c.shadow, err) | |
70 } | |
71 if c.username != entry.username { | |
72 t.Errorf("EntryFromShadow(%q).username = %q; want %q", c.shadow, entry.username, c.username) | |
73 } | |
74 if c.hash != string(entry.hash) { | |
75 t.Errorf("EntryFromShadow(%q).password = %q; want %q", c.shadow, entry.hash, c.hash) | |
76 } | |
77 if c.description != entry.description { | |
78 t.Errorf("EntryFromShadow(%q).description = %q; want %q", c.shadow, entry.description, c.description) | |
79 } | |
80 restEqual := false | |
81 if len(c.rest) == len(entry.rest) { | |
82 restEqual = true | |
83 for i := range c.rest { | |
84 if c.rest[i] != entry.rest[i] { | |
85 restEqual = false | |
86 break | |
87 } | |
88 } | |
89 } | |
90 if !restEqual { | |
91 t.Errorf("EntryFromShadow(%q).rest = %q; want %q", c.shadow, entry.rest, c.rest) | |
92 } | |
93 } | |
94 } | |
95 | |
96 func TestNewEntry(t *testing.T) { | |
97 cases := []struct { | |
98 username string | |
99 description string | |
100 wantErr bool | |
101 }{ | |
102 {"pfish", "one", false}, | |
103 {"pfish", "the other", false}, | |
104 {"with:colons", "", true}, | |
105 {"pfish", string(make([]byte, 1000)), true}, | |
106 } | |
107 for _, c := range cases { | |
108 entry, password, err := NewEntry(c.username, c.description) | |
109 if c.wantErr { | |
110 if err == nil { | |
111 t.Errorf("NewEntry(%q, %q) = _, _, nil; want non-nil err", c.username, c.description) | |
112 } | |
113 continue | |
114 } | |
115 if err != nil { | |
116 t.Errorf("NewEntry(%q, %q) = _, _, %q; want nil err", c.username, c.description, err) | |
117 } | |
118 if c.username != entry.username { | |
119 t.Errorf("NewEntry(%q, %q).username = %q, want %q", | |
120 c.username, c.description, entry.username, c.username) | |
121 } | |
122 if entry.id == 0 { | |
123 // This test has a 1/(2**64) chance of failing! :o | |
124 t.Errorf("NewEntry(_, _).id == 0, want nonzero") | |
125 } | |
126 if c.description != entry.description { | |
127 t.Errorf("NewEntry(%q, %q).description = %q, want %q", | |
128 c.username, c.description, entry.description, c.description) | |
129 } | |
130 if !passPattern.MatchString(password) { | |
131 t.Errorf("NewEntry(_, _) = _, %q, _; wanted to match xxxx-xxxx-xxxx-xxxx", password) | |
132 } | |
133 if !entry.Authenticate(c.username, password) { | |
134 t.Errorf("NewEntry(%q, %q).Authenticate(%q, %q) failed", | |
135 c.username, c.description, c.username, password) | |
136 } | |
137 } | |
138 } | |
139 | |
140 func TestGenPassword(t *testing.T) { | |
141 p := genPassword() | |
142 if !passPattern.MatchString(string(p)) { | |
143 t.Errorf("genPassword() = %q; wanted to match xxxx-xxxx-xxxx-xxxx", p) | |
144 } | |
145 } | |
146 | |
147 func TestAuthenticate(t *testing.T) { | |
148 entry, password, err := NewEntry("pfish", "") | |
149 if err != nil { | |
150 t.Errorf("Error building entry") | |
151 } | |
152 type testcase struct { | |
153 username, password string | |
154 want bool | |
155 } | |
156 | |
157 cases := []testcase{ | |
158 {"pfish", password, true}, | |
159 {"jhh", password, false}, | |
160 {"pfish", "not the password", false}, | |
161 {"jhh", "not the password", false}, | |
162 } | |
163 for _, c := range cases { | |
164 got := entry.Authenticate(c.username, c.password) | |
165 if got != c.want { | |
166 t.Errorf("entry.Authenticate(%q, %q) == %q, want %q", | |
167 c.username, c.password, got, c.want) | |
168 } | |
169 } | |
170 | |
171 entry, err = EntryFromShadow(basicShadow) | |
172 if err != nil { | |
173 t.Errorf("Error loading valid shadow") | |
174 } | |
175 | |
176 cases = []testcase{ | |
177 {"jhh", "nocardio", true}, | |
178 {"pfish", "nocardio", false}, | |
179 {"jhh", "not the password", false}, | |
180 {"pfish", "not the password", false}, | |
181 } | |
182 for _, c := range cases { | |
183 got := entry.Authenticate(c.username, c.password) | |
184 if got != c.want { | |
185 t.Errorf("entry.Authenticate(%q, %q) == %q, want %q", | |
186 c.username, c.password, got, c.want) | |
187 } | |
188 } | |
189 } | |
190 | |
191 func testMatchesID(t *testing.T) { | |
192 entry, err := EntryFromShadow(basicShadow) | |
193 if err != nil { | |
194 t.Errorf("Error loading valid shadow") | |
195 } | |
196 cases := []struct { | |
197 username string | |
198 id uint64 | |
199 want bool | |
200 }{ | |
201 {"jhh", 1234, true}, | |
202 {"pfish", 1234, false}, | |
203 {"jhh", 9999, false}, | |
204 {"pfish", 9999, false}, | |
205 } | |
206 for _, c := range cases { | |
207 got := entry.MatchesID(c.username, c.id) | |
208 if got != c.want { | |
209 t.Errorf("entry.MatchesID(%q, %q) == %q, want %q", | |
210 c.username, c.id, got, c.want) | |
211 } | |
212 } | |
213 } | |
214 | |
215 func TestEncode(t *testing.T) { | |
216 // Crafted entry | |
217 shadowed, err := EntryFromShadow(basicShadow) | |
218 if err != nil { | |
219 t.Errorf("Error loading valid shadow") | |
220 } | |
221 extraShadowed, err := EntryFromShadow(extraDataShadow) | |
222 if err != nil { | |
223 t.Errorf("Error loading valid shadow") | |
224 } | |
225 cases := []struct { | |
226 entry *Entry | |
227 want string | |
228 }{ | |
229 { | |
230 &Entry{ | |
231 username: "testuser", | |
232 id: 6775, | |
233 hash: "bogushash", | |
234 description: "something", | |
235 }, | |
236 "testuser:6775:bogushash:c29tZXRoaW5n", | |
237 }, | |
238 { | |
239 &Entry{ | |
240 username: "testuser", | |
241 id: 6775, | |
242 hash: "bogushash", | |
243 description: "something", | |
244 rest: []string{"a", "B"}, | |
245 }, | |
246 "testuser:6775:bogushash:c29tZXRoaW5n:a:B", | |
247 }, | |
248 {shadowed, basicShadow}, | |
249 {extraShadowed, extraDataShadow}, | |
250 } | |
251 for _, c := range cases { | |
252 got := string(c.entry.Encode()) | |
253 if got != c.want { | |
254 t.Errorf("entry.Encode() = %q, want %q", got, c.want) | |
255 } | |
256 } | |
257 } |