# HG changeset patch # User Paul Fisher # Date 1446168312 14400 # Node ID 1c194fa9bbf4867ae7305ab902747ef3cada3b72 # Parent e246c8a4d28e37fc35d476097604778f31ec460a Fix auth tests. diff -r e246c8a4d28e -r 1c194fa9bbf4 auth/auth.go --- a/auth/auth.go Sun Oct 25 11:48:53 2015 -0400 +++ b/auth/auth.go Thu Oct 29 21:25:12 2015 -0400 @@ -18,7 +18,7 @@ bcryptCost = 12 // we only generate passwords from lowercases for non-ambiguity lowercases = "abcdefghijklmnopqrstuvwxyz" - template = "____-____-____-____" + template = "????-????-????-????" ) var ( @@ -27,7 +27,7 @@ ) var ( - ShortEntryError error = errors.New("multipass/auth: password entry must have 3 or more fields") + WrongLengthError error = errors.New("multipass/auth: password entry must have 3 fields") BadIDError = errors.New("multipass/auth: ID field invalid") Base64Error = errors.New("multipass/auth: can't decode base64 data") LongDescriptionError = errors.New("multipass/auth: description must be less than 255 bytes") @@ -43,15 +43,14 @@ id uint64 hash string description string - rest []string } // EntryFromShadow creates a new entry from a line in a multipass shadow file. // The line should not end in a newline. func EntryFromShadow(shadow string) (*Entry, error) { segments := strings.Split(shadow, ":") - if len(segments) < 2 { - return nil, ShortEntryError + if len(segments) != 3 { + return nil, WrongLengthError } entry := new(Entry) id, err := strconv.ParseUint(segments[0], 10, 64) @@ -60,14 +59,11 @@ } entry.id = id entry.hash = segments[1] - if len(segments) > 2 { - description, err := base64.StdEncoding.DecodeString(segments[2]) - if err != nil { - return nil, Base64Error - } - entry.description = string(description) - entry.rest = segments[3:] + description, err := base64.StdEncoding.DecodeString(segments[2]) + if err != nil { + return nil, Base64Error } + entry.description = string(description) return entry, nil } @@ -114,16 +110,14 @@ e.hash, base64.StdEncoding.EncodeToString([]byte(e.description)), } - segments = append(segments, e.rest...) return strings.Join(segments, ":") } func genPassword() []byte { password := []byte(template) - for group := 0; group < 4; group++ { - base := group * 5 - for chr := 0; chr < 4; chr++ { - password[base+chr] = randChr() + for i, chr := range password { + if chr == '?' { + password[i] = randChr() } } return password diff -r e246c8a4d28e -r 1c194fa9bbf4 auth/auth_test.go --- a/auth/auth_test.go Sun Oct 25 11:48:53 2015 -0400 +++ b/auth/auth_test.go Thu Oct 29 21:25:12 2015 -0400 @@ -7,8 +7,8 @@ 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" +const basicShadow = "9999:$2a$12$tcv2MrtXgibAJHsSwVfHiOevXBFmiGy0HTNoOB8QzIhEh46iWS1uC:YW55dGhpbmcgbW9yZSB0aGFuIDUgcmVwcyBpcyBjYXJkaW8=" +const anotherShadow = "1:$2a$12$lINQdYWHOcLKoqhNOr3mNOpZSAu5JOBS2F7T/VDfYn2rvv6qUJehG:" func TestEntryFromShadow(t *testing.T) { cases := []struct { @@ -21,39 +21,39 @@ rest []string }{ { - shadow: "pfish:1234:$2a$12$apFtWGXKtWBavVy5eo.22Ohs43GudT5IYTqyQkIBX9LpS7YtvKBpa", - username: "pfish", + shadow: "1234:$2a$12$apFtWGXKtWBavVy5eo.22Ohs43GudT5IYTqyQkIBX9LpS7YtvKBpa:", 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", + shadow: anotherShadow, id: 1, hash: "$2a$12$lINQdYWHOcLKoqhNOr3mNOpZSAu5JOBS2F7T/VDfYn2rvv6qUJehG", - rest: []string{"additional", "fields"}, }, { - shadow: "user:one:bogushash", + shadow: "one:bogushash:", wantErr: true, }, { - shadow: "user:-1:bogushash", + shadow: "-1:bogushash:", wantErr: true, }, { - shadow: "tooshort", + shadow: "0:tooshort", wantErr: true, }, { - shadow: "test:0:bogushash:invalid base64", + shadow: "0:bogushash:invalid base64", + wantErr: true, + }, + { + shadow: "1:bogushash::more things", wantErr: true, }, } @@ -68,8 +68,8 @@ 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.id != entry.id { + t.Errorf("EntryFromShadow(%q).id = %q; want %q", c.shadow, entry.id, c.id) } if c.hash != string(entry.hash) { t.Errorf("EntryFromShadow(%q).password = %q; want %q", c.shadow, entry.hash, c.hash) @@ -77,62 +77,43 @@ 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}, + {"one", false}, + {"the other", false}, + {string(make([]byte, 1000)), true}, } for _, c := range cases { - entry, password, err := NewEntry(c.username, c.description) + entry, password, err := NewEntry(c.description) if c.wantErr { if err == nil { - t.Errorf("NewEntry(%q, %q) = _, _, nil; want non-nil err", c.username, c.description) + t.Errorf("NewEntry(%q) = _, _, nil; want non-nil err", 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) + t.Errorf("NewEntry(%q) = _, _, %q; want nil err", c.description, err) } if entry.id == 0 { // This test has a 1/(2**64) chance of failing! :o - t.Errorf("NewEntry(_, _).id == 0, want nonzero") + 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) + t.Errorf("NewEntry(%q).description = %q, want %q", + c.description, entry.description, c.description) } if !passPattern.MatchString(password) { - t.Errorf("NewEntry(_, _) = _, %q, _; wanted to match xxxx-xxxx-xxxx-xxxx", 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) + if !entry.Authenticate(password) { + t.Errorf("NewEntry(%q).Authenticate(%q, %q) failed", + c.description, password) } } } @@ -145,26 +126,24 @@ } func TestAuthenticate(t *testing.T) { - entry, password, err := NewEntry("pfish", "") + entry, password, err := NewEntry("") if err != nil { t.Errorf("Error building entry") } type testcase struct { - username, password string + password string want bool } cases := []testcase{ - {"pfish", password, true}, - {"jhh", password, false}, - {"pfish", "not the password", false}, - {"jhh", "not the password", false}, + {password, true}, + {"not the password", false}, } for _, c := range cases { - got := entry.Authenticate(c.username, c.password) + got := entry.Authenticate(c.password) if got != c.want { - t.Errorf("entry.Authenticate(%q, %q) == %q, want %q", - c.username, c.password, got, c.want) + t.Errorf("entry.Authenticate(%q) == %q, want %q", + c.password, got, c.want) } } @@ -174,40 +153,14 @@ } cases = []testcase{ - {"jhh", "nocardio", true}, - {"pfish", "nocardio", false}, - {"jhh", "not the password", false}, - {"pfish", "not the password", false}, + {"nocardio", true}, + {"not the password", false}, } for _, c := range cases { - got := entry.Authenticate(c.username, c.password) + got := entry.Authenticate(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) + c.password, got, c.want) } } } @@ -218,7 +171,7 @@ if err != nil { t.Errorf("Error loading valid shadow") } - extraShadowed, err := EntryFromShadow(extraDataShadow) + anotherShadowed, err := EntryFromShadow(anotherShadow) if err != nil { t.Errorf("Error loading valid shadow") } @@ -228,25 +181,14 @@ }{ { &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", + "6775:bogushash:c29tZXRoaW5n", }, {shadowed, basicShadow}, - {extraShadowed, extraDataShadow}, + {anotherShadowed, anotherShadow}, } for _, c := range cases { got := string(c.entry.Encode())