Skip to content

Commit

Permalink
Merge pull request #186 from stlaz/bcrypt_hashes
Browse files Browse the repository at this point in the history
Bug 1874322: add bcrypt as a supported hashing method for htpasswd passwords
  • Loading branch information
openshift-merge-robot committed Jun 3, 2021
2 parents 17a8d9f + e175982 commit 3fc0d89
Show file tree
Hide file tree
Showing 10 changed files with 830 additions and 11 deletions.
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -15,6 +15,7 @@ require (
github.com/openshift/library-go v0.0.0-20200918101923-1e4c94603efe
github.com/stretchr/testify v1.4.0
github.com/yhat/wsutil v0.0.0-20170731153501-1d66fa95c997
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
golang.org/x/net v0.0.0-20200904194848-62affa334b73
k8s.io/api v0.19.2
k8s.io/apimachinery v0.19.2
Expand Down
23 changes: 15 additions & 8 deletions htpasswd.go
Expand Up @@ -7,10 +7,12 @@ import (
"io"
"log"
"os"

"golang.org/x/crypto/bcrypt"
)

// lookup passwords in a htpasswd file
// The entries must have been created with -s for SHA encryption
// Lookup passwords in a htpasswd file
// Passwords must be generated with -B for bcrypt or -s for SHA1.

type HtpasswdFile struct {
Users map[string]string
Expand Down Expand Up @@ -47,14 +49,19 @@ func (h *HtpasswdFile) Validate(user string, password string) bool {
if !exists {
return false
}
if realPassword[:5] == "{SHA}" {
shaPrefix := realPassword[:5]
if shaPrefix == "{SHA}" {
shaValue := realPassword[5:]
d := sha1.New()
d.Write([]byte(password))
if realPassword[5:] == base64.StdEncoding.EncodeToString(d.Sum(nil)) {
return true
}
} else {
log.Printf("Invalid htpasswd entry for %s. Must be a SHA entry.", user)
return shaValue == base64.StdEncoding.EncodeToString(d.Sum(nil))
}

bcryptPrefix := realPassword[:4]
if bcryptPrefix == "$2a$" || bcryptPrefix == "$2x$" || bcryptPrefix == "$2y$" {
return bcrypt.CompareHashAndPassword([]byte(realPassword), []byte(password)) == nil
}

log.Printf("Invalid htpasswd entry for %s. Must be a SHA or bcrypt entry.", user)
return false
}
25 changes: 23 additions & 2 deletions htpasswd_test.go
Expand Up @@ -2,11 +2,14 @@ package main

import (
"bytes"
"github.com/bmizerany/assert"
"fmt"
"testing"

"github.com/bmizerany/assert"
"golang.org/x/crypto/bcrypt"
)

func TestHtpasswd(t *testing.T) {
func TestSHA(t *testing.T) {
file := bytes.NewBuffer([]byte("testuser:{SHA}PaVBVZkYqAjCQCu6UBL2xgsnZhw=\nfoo:{SHA}rjXz/gOeuoMRiEa7Get6eHtKkX0=\n"))
h, err := NewHtpasswd(file)
assert.Equal(t, err, nil)
Expand All @@ -20,3 +23,21 @@ func TestHtpasswd(t *testing.T) {
valid = h.Validate("nobody", "ghjk")
assert.Equal(t, valid, false)
}

func TestBcrypt(t *testing.T) {
hash1, err := bcrypt.GenerateFromPassword([]byte("password"), 1)
hash2, err := bcrypt.GenerateFromPassword([]byte("top-secret"), 2)
assert.Equal(t, err, nil)

contents := fmt.Sprintf("testuser1:%s\ntestuser2:%s\n", hash1, hash2)
file := bytes.NewBuffer([]byte(contents))

h, err := NewHtpasswd(file)
assert.Equal(t, err, nil)

valid := h.Validate("testuser1", "password")
assert.Equal(t, valid, true)

valid = h.Validate("testuser2", "top-secret")
assert.Equal(t, valid, true)
}
2 changes: 1 addition & 1 deletion main.go
Expand Up @@ -61,7 +61,7 @@ func main() {
flagSet.String("client-secret", "", "the OAuth Client Secret")
flagSet.String("client-secret-file", "", "a file containing the client-secret")
flagSet.String("authenticated-emails-file", "", "authenticate against emails via file (one per line)")
flagSet.String("htpasswd-file", "", "additionally authenticate against a htpasswd file. Entries must be created with \"htpasswd -s\" for SHA encryption")
flagSet.String("htpasswd-file", "", "additionally authenticate against a htpasswd file. Entries must be created with \"htpasswd -s\" for SHA password hashes or \"htpasswd -B\" for bcrypt hashes")
flagSet.Bool("display-htpasswd-form", true, "display username / password login form if an htpasswd file is provided")
flagSet.String("custom-templates-dir", "", "path to custom html templates")
flagSet.String("footer", "", "custom footer string. Use \"-\" to disable default footer.")
Expand Down
35 changes: 35 additions & 0 deletions vendor/golang.org/x/crypto/bcrypt/base64.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 3fc0d89

Please sign in to comment.