diff --git a/README.md b/README.md index 9446276..64628d6 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,8 @@ Usage of /usr/local/bin/basic_hmac_auth: hex-encoded HMAC secret value -secret-file string file containing single line with hex-encoded secret + -strict + require shortest possible, invariant form of encoding (default true) -version show program version and exit ``` diff --git a/cmd/main.go b/cmd/main.go index b57486f..75d5311 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -22,6 +22,7 @@ const ( var ( bufferSize = flag.Int("buffer-size", 0, "initial buffer size for stream parsing") + strict = flag.Bool("strict", true, "require shortest possible, invariant form of encoding") hexSecret = flag.String("secret", "", "hex-encoded HMAC secret value") hexSecretFile = flag.String("secret-file", "", "file containing single line with hex-encoded secret") showVersion = flag.Bool("version", false, "show program version and exit") @@ -80,6 +81,7 @@ func run() int { err = (&handler.BasicHMACAuthHandler{ Secret: secret, BufferSize: *bufferSize, + Strict: *strict, }).Run(os.Stdin, os.Stdout) if err != nil { log.Printf("auth handler terminated with error: %v", err) diff --git a/handler/handler.go b/handler/handler.go index d24ab91..c49d7e2 100644 --- a/handler/handler.go +++ b/handler/handler.go @@ -18,6 +18,7 @@ const ( type BasicHMACAuthHandler struct { Secret []byte BufferSize int + Strict bool } func (a *BasicHMACAuthHandler) Run(input io.Reader, output io.Writer) error { @@ -28,7 +29,7 @@ func (a *BasicHMACAuthHandler) Run(input io.Reader, output io.Writer) error { rd := bufio.NewReaderSize(input, bufSize) scanner := proto.NewElasticLineScanner(rd, '\n') - verifier := hmac.NewVerifier(a.Secret) + verifier := hmac.NewVerifier(a.Secret, a.Strict) emitter := proto.NewResponseEmitter(output) diff --git a/hmac/hmac.go b/hmac/hmac.go index 3e96a8b..28b9cfd 100644 --- a/hmac/hmac.go +++ b/hmac/hmac.go @@ -12,7 +12,6 @@ import ( const ( HMACSignaturePrefix = "dumbproxy grant token v1" HMACExpireSize = 8 - passwordBufferSize = HMACExpireSize + 64 // for worst case if 512-bit hash is used for some reason ) var hmacSignaturePrefix = []byte(HMACSignaturePrefix) @@ -22,13 +21,21 @@ func NewHasher(secret []byte) hash.Hash { } type Verifier struct { - mac hash.Hash - buf []byte + mac hash.Hash + buf []byte + dec *base64.Encoding + strict bool } -func NewVerifier(secret []byte) *Verifier { +func NewVerifier(secret []byte, strict bool) *Verifier { + dec := base64.RawURLEncoding + if strict { + dec = dec.Strict() + } return &Verifier{ - mac: hmac.New(sha256.New, secret), + mac: hmac.New(sha256.New, secret), + strict: strict, + dec: dec, } } @@ -39,10 +46,14 @@ func (v *Verifier) ensureBufferSize(size int) { } func (v *Verifier) VerifyLoginAndPassword(login, password []byte) bool { - v.ensureBufferSize(base64.RawURLEncoding.DecodedLen(len(password))) + if v.strict && len(password) != v.dec.EncodedLen(HMACExpireSize+v.mac.Size()) { + return false + } + + v.ensureBufferSize(v.dec.DecodedLen(len(password))) buf := v.buf - n, err := base64.RawURLEncoding.Decode(buf, password) - if err != nil { + n, err := v.dec.Decode(buf, password) + if v.strict && err != nil { return false } buf = buf[:n]