Mercurial > go > multipass
view 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 |
line wrap: on
line source
package auth import ( "regexp" "testing" ) var passPattern *regexp.Regexp = regexp.MustCompile(`^(?:[a-z]{4}-){3}[a-z]{4}$`) const basicShadow = "jhh:9999:$2a$12$tcv2MrtXgibAJHsSwVfHiOevXBFmiGy0HTNoOB8QzIhEh46iWS1uC:YW55dGhpbmcgbW9yZSB0aGFuIDUgcmVwcyBpcyBjYXJkaW8=" const extraDataShadow = "skw:1:$2a$12$lINQdYWHOcLKoqhNOr3mNOpZSAu5JOBS2F7T/VDfYn2rvv6qUJehG::additional:fields" func TestEntryFromShadow(t *testing.T) { cases := []struct { shadow string wantErr bool username string id uint64 hash string description string rest []string }{ { shadow: "pfish:1234:$2a$12$apFtWGXKtWBavVy5eo.22Ohs43GudT5IYTqyQkIBX9LpS7YtvKBpa", username: "pfish", id: 1234, hash: "$2a$12$apFtWGXKtWBavVy5eo.22Ohs43GudT5IYTqyQkIBX9LpS7YtvKBpa", }, { shadow: basicShadow, username: "jhh", id: 9999, hash: "$2a$12$tcv2MrtXgibAJHsSwVfHiOevXBFmiGy0HTNoOB8QzIhEh46iWS1uC", description: "anything more than 5 reps is cardio", }, { shadow: extraDataShadow, username: "skw", id: 1, hash: "$2a$12$lINQdYWHOcLKoqhNOr3mNOpZSAu5JOBS2F7T/VDfYn2rvv6qUJehG", rest: []string{"additional", "fields"}, }, { shadow: "user:one:bogushash", wantErr: true, }, { shadow: "user:-1:bogushash", wantErr: true, }, { shadow: "tooshort", wantErr: true, }, { shadow: "test:0:bogushash:invalid base64", wantErr: true, }, } for _, c := range cases { entry, err := EntryFromShadow(c.shadow) if c.wantErr { if err == nil { t.Errorf("EntryFromShadow(%q) == _, nil; want non-nil err", c.shadow) } continue } if err != nil { t.Errorf("EntryFromShadow(%q) == _, %q; want nil err", c.shadow, err) } if c.username != entry.username { t.Errorf("EntryFromShadow(%q).username = %q; want %q", c.shadow, entry.username, c.username) } if c.hash != string(entry.hash) { t.Errorf("EntryFromShadow(%q).password = %q; want %q", c.shadow, entry.hash, c.hash) } if c.description != entry.description { t.Errorf("EntryFromShadow(%q).description = %q; want %q", c.shadow, entry.description, c.description) } restEqual := false if len(c.rest) == len(entry.rest) { restEqual = true for i := range c.rest { if c.rest[i] != entry.rest[i] { restEqual = false break } } } if !restEqual { t.Errorf("EntryFromShadow(%q).rest = %q; want %q", c.shadow, entry.rest, c.rest) } } } func TestNewEntry(t *testing.T) { cases := []struct { username string description string wantErr bool }{ {"pfish", "one", false}, {"pfish", "the other", false}, {"with:colons", "", true}, {"pfish", string(make([]byte, 1000)), true}, } for _, c := range cases { entry, password, err := NewEntry(c.username, c.description) if c.wantErr { if err == nil { t.Errorf("NewEntry(%q, %q) = _, _, nil; want non-nil err", c.username, c.description) } continue } if err != nil { t.Errorf("NewEntry(%q, %q) = _, _, %q; want nil err", c.username, c.description, err) } if c.username != entry.username { t.Errorf("NewEntry(%q, %q).username = %q, want %q", c.username, c.description, entry.username, c.username) } if entry.id == 0 { // This test has a 1/(2**64) chance of failing! :o t.Errorf("NewEntry(_, _).id == 0, want nonzero") } if c.description != entry.description { t.Errorf("NewEntry(%q, %q).description = %q, want %q", c.username, c.description, entry.description, c.description) } if !passPattern.MatchString(password) { t.Errorf("NewEntry(_, _) = _, %q, _; wanted to match xxxx-xxxx-xxxx-xxxx", password) } if !entry.Authenticate(c.username, password) { t.Errorf("NewEntry(%q, %q).Authenticate(%q, %q) failed", c.username, c.description, c.username, password) } } } func TestGenPassword(t *testing.T) { p := genPassword() if !passPattern.MatchString(string(p)) { t.Errorf("genPassword() = %q; wanted to match xxxx-xxxx-xxxx-xxxx", p) } } func TestAuthenticate(t *testing.T) { entry, password, err := NewEntry("pfish", "") if err != nil { t.Errorf("Error building entry") } type testcase struct { username, password string want bool } cases := []testcase{ {"pfish", password, true}, {"jhh", password, false}, {"pfish", "not the password", false}, {"jhh", "not the password", false}, } for _, c := range cases { got := entry.Authenticate(c.username, c.password) if got != c.want { t.Errorf("entry.Authenticate(%q, %q) == %q, want %q", c.username, c.password, got, c.want) } } entry, err = EntryFromShadow(basicShadow) if err != nil { t.Errorf("Error loading valid shadow") } cases = []testcase{ {"jhh", "nocardio", true}, {"pfish", "nocardio", false}, {"jhh", "not the password", false}, {"pfish", "not the password", false}, } for _, c := range cases { got := entry.Authenticate(c.username, c.password) if got != c.want { t.Errorf("entry.Authenticate(%q, %q) == %q, want %q", c.username, c.password, got, c.want) } } } func testMatchesID(t *testing.T) { entry, err := EntryFromShadow(basicShadow) if err != nil { t.Errorf("Error loading valid shadow") } cases := []struct { username string id uint64 want bool }{ {"jhh", 1234, true}, {"pfish", 1234, false}, {"jhh", 9999, false}, {"pfish", 9999, false}, } for _, c := range cases { got := entry.MatchesID(c.username, c.id) if got != c.want { t.Errorf("entry.MatchesID(%q, %q) == %q, want %q", c.username, c.id, got, c.want) } } } func TestEncode(t *testing.T) { // Crafted entry shadowed, err := EntryFromShadow(basicShadow) if err != nil { t.Errorf("Error loading valid shadow") } extraShadowed, err := EntryFromShadow(extraDataShadow) if err != nil { t.Errorf("Error loading valid shadow") } cases := []struct { entry *Entry want string }{ { &Entry{ username: "testuser", id: 6775, hash: "bogushash", description: "something", }, "testuser:6775:bogushash:c29tZXRoaW5n", }, { &Entry{ username: "testuser", id: 6775, hash: "bogushash", description: "something", rest: []string{"a", "B"}, }, "testuser:6775:bogushash:c29tZXRoaW5n:a:B", }, {shadowed, basicShadow}, {extraShadowed, extraDataShadow}, } for _, c := range cases { got := string(c.entry.Encode()) if got != c.want { t.Errorf("entry.Encode() = %q, want %q", got, c.want) } } }