From f8366c2f09c77a55dc53038cae0b101263488867 Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Thu, 10 Oct 2019 14:37:27 -0600 Subject: http: authentication module; hash-password cmd; http_basic provider This implements HTTP basicauth into Caddy 2. The basic auth module will not work with passwords that are not securely hashed, so a subcommand hash-password was added to make it convenient to produce those hashes. Also included is Caddyfile support. Closes #2747. --- modules/caddyhttp/caddyauth/hashes.go | 111 ++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 modules/caddyhttp/caddyauth/hashes.go (limited to 'modules/caddyhttp/caddyauth/hashes.go') diff --git a/modules/caddyhttp/caddyauth/hashes.go b/modules/caddyhttp/caddyauth/hashes.go new file mode 100644 index 0000000..a515c09 --- /dev/null +++ b/modules/caddyhttp/caddyauth/hashes.go @@ -0,0 +1,111 @@ +// Copyright 2015 Matthew Holt and The Caddy Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package caddyauth + +import ( + "github.com/caddyserver/caddy/v2" + "golang.org/x/crypto/bcrypt" + "golang.org/x/crypto/scrypt" +) + +func init() { + caddy.RegisterModule(BcryptHash{}) + caddy.RegisterModule(ScryptHash{}) +} + +// BcryptHash implements the bcrypt hash. +type BcryptHash struct{} + +// CaddyModule returns the Caddy module information. +func (BcryptHash) CaddyModule() caddy.ModuleInfo { + return caddy.ModuleInfo{ + Name: "http.handlers.authentication.hashes.bcrypt", + New: func() caddy.Module { return new(BcryptHash) }, + } +} + +// Compare compares passwords. +func (BcryptHash) Compare(hashed, plaintext, _ []byte) (bool, error) { + err := bcrypt.CompareHashAndPassword(hashed, plaintext) + if err == bcrypt.ErrMismatchedHashAndPassword { + return false, nil + } + if err != nil { + return false, err + } + return true, nil +} + +// ScryptHash implements the scrypt KDF as a hash. +type ScryptHash struct { + N int `json:"N,omitempty"` + R int `json:"r,omitempty"` + P int `json:"p,omitempty"` + KeyLength int `json:"key_length,omitempty"` +} + +// CaddyModule returns the Caddy module information. +func (ScryptHash) CaddyModule() caddy.ModuleInfo { + return caddy.ModuleInfo{ + Name: "http.handlers.authentication.hashes.scrypt", + New: func() caddy.Module { return new(ScryptHash) }, + } +} + +// Provision sets up s. +func (s *ScryptHash) Provision(_ caddy.Context) error { + s.SetDefaults() + return nil +} + +// SetDefaults sets safe default parameters, but does +// not overwrite existing values. Each default parameter +// is set independently; it does not check to ensure +// that r*p < 2^30. The defaults chosen are those as +// recommended in 2019 by +// https://godoc.org/golang.org/x/crypto/scrypt. +func (s *ScryptHash) SetDefaults() { + if s.N == 0 { + s.N = 32768 + } + if s.R == 0 { + s.R = 8 + } + if s.P == 0 { + s.P = 1 + } + if s.KeyLength == 0 { + s.KeyLength = 32 + } +} + +// Compare compares passwords. +func (s ScryptHash) Compare(hashed, plaintext, salt []byte) (bool, error) { + ourHash, err := scrypt.Key(plaintext, salt, s.N, s.R, s.P, s.KeyLength) + if err != nil { + return false, err + } + if hashesMatch(hashed, ourHash) { + return true, nil + } + return false, nil +} + +// Interface guards +var ( + _ Comparer = (*BcryptHash)(nil) + _ Comparer = (*ScryptHash)(nil) + _ caddy.Provisioner = (*ScryptHash)(nil) +) -- cgit v1.2.3