|
|
@ -2,7 +2,6 @@ |
|
|
|
package htpasswd |
|
|
|
package htpasswd |
|
|
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
import ( |
|
|
|
"errors" |
|
|
|
|
|
|
|
"fmt" |
|
|
|
"fmt" |
|
|
|
"os" |
|
|
|
"os" |
|
|
|
"strings" |
|
|
|
"strings" |
|
|
@ -36,29 +35,29 @@ func Parse(htpasswdBytes []byte) (Passwds, error) { |
|
|
|
var err error |
|
|
|
var err error |
|
|
|
|
|
|
|
|
|
|
|
for lineNumber, line := range lines { |
|
|
|
for lineNumber, line := range lines { |
|
|
|
line = strings.Trim(line, " ") |
|
|
|
line = strings.TrimSpace(line) |
|
|
|
if len(line) == 0 { |
|
|
|
if len(line) == 0 { |
|
|
|
// skipping empty lines
|
|
|
|
// skipping empty lines
|
|
|
|
continue |
|
|
|
continue |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
parts := strings.Split(line, ":") |
|
|
|
user, password, err := splitLine(line, lineNumber) |
|
|
|
if ok, err := validLine(parts, lineNumber, line); !ok { |
|
|
|
if err != nil { |
|
|
|
return passwords, err |
|
|
|
return passwords, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
parts = trimParts(parts) |
|
|
|
_, exists := passwords[user] |
|
|
|
_, exists := passwords[parts[0]] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if exists { |
|
|
|
if exists { |
|
|
|
err = &UserError{ |
|
|
|
err = &UserError{ |
|
|
|
Name: parts[0], |
|
|
|
Name: user, |
|
|
|
Err: ErrExists, |
|
|
|
Err: ErrExists, |
|
|
|
} |
|
|
|
} |
|
|
|
return passwords, err |
|
|
|
return passwords, err |
|
|
|
} |
|
|
|
} |
|
|
|
passwords[parts[0]] = parts[1] |
|
|
|
|
|
|
|
|
|
|
|
passwords[user] = password |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return passwords, err |
|
|
|
return passwords, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -218,20 +217,18 @@ func identifyHash(h string) Hasher { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func validLine(parts []string, lineNumber int, line string) (bool, error) { |
|
|
|
func splitLine(line string, lineNumber int) (user, password string, err error) { |
|
|
|
var err error |
|
|
|
user, password, ok := strings.Cut(line, ":") |
|
|
|
if len(parts) != 2 { |
|
|
|
if !ok { |
|
|
|
err = errors.New(fmt.Sprintln("invalid line", lineNumber+1, |
|
|
|
return "", "", fmt.Errorf("invalid line %v", lineNumber+1) |
|
|
|
"unexpected number of parts split by", ":", len(parts), |
|
|
|
|
|
|
|
"instead of 2 in\"", line, "\"")) |
|
|
|
|
|
|
|
return false, err |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return true, nil |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func trimParts(parts []string) []string { |
|
|
|
user = strings.TrimSpace(user) |
|
|
|
for i, part := range parts { |
|
|
|
password = strings.TrimSpace(password) |
|
|
|
parts[i] = strings.Trim(part, " ") |
|
|
|
|
|
|
|
|
|
|
|
if h := identifyHash(password); h != nil { |
|
|
|
|
|
|
|
return "", "", fmt.Errorf("invalid algorithm on line %v", lineNumber+1) |
|
|
|
} |
|
|
|
} |
|
|
|
return parts |
|
|
|
|
|
|
|
|
|
|
|
return user, password, nil |
|
|
|
} |
|
|
|
} |
|
|
|