| 
									
										
										
										
											2017-06-21 15:23:33 -06:00
										 |  |  | package restserver | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | Original version copied from: github.com/bitly/oauth2_proxy | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | MIT License | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Permission is hereby granted, free of charge, to any person obtaining a copy | 
					
						
							|  |  |  | of this software and associated documentation files (the "Software"), to deal | 
					
						
							|  |  |  | in the Software without restriction, including without limitation the rights | 
					
						
							|  |  |  | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
					
						
							|  |  |  | copies of the Software, and to permit persons to whom the Software is | 
					
						
							|  |  |  | furnished to do so, subject to the following conditions: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The above copyright notice and this permission notice shall be included in | 
					
						
							|  |  |  | all copies or substantial portions of the Software. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
					
						
							|  |  |  | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
					
						
							|  |  |  | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 
					
						
							|  |  |  | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
					
						
							|  |  |  | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
					
						
							|  |  |  | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 
					
						
							|  |  |  | THE SOFTWARE. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"crypto/sha1" | 
					
						
							| 
									
										
										
										
											2021-01-04 19:05:56 +01:00
										 |  |  | 	"crypto/sha256" | 
					
						
							|  |  |  | 	"crypto/subtle" | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | 	"encoding/base64" | 
					
						
							|  |  |  | 	"encoding/csv" | 
					
						
							|  |  |  | 	"log" | 
					
						
							| 
									
										
										
										
											2016-11-06 20:09:42 +01:00
										 |  |  | 	"os" | 
					
						
							| 
									
										
										
										
											2019-03-04 16:55:29 -07:00
										 |  |  | 	"os/signal" | 
					
						
							| 
									
										
										
										
											2018-02-11 14:54:25 -07:00
										 |  |  | 	"regexp" | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2019-03-04 16:55:29 -07:00
										 |  |  | 	"syscall" | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2018-02-11 14:54:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"golang.org/x/crypto/bcrypt" | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-25 18:14:07 +02:00
										 |  |  | // CheckInterval represents how often we check for changes in htpasswd file. | 
					
						
							| 
									
										
										
										
											2017-10-24 18:48:04 +08:00
										 |  |  | const CheckInterval = 30 * time.Second | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-04 19:05:56 +01:00
										 |  |  | // PasswordCacheDuration represents how long authentication credentials are | 
					
						
							|  |  |  | // cached in memory after they were successfully verified. This allows avoiding | 
					
						
							|  |  |  | // repeatedly verifying the same authentication credentials. | 
					
						
							|  |  |  | const PasswordCacheDuration = time.Minute | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-06 11:15:33 +01:00
										 |  |  | // Lookup passwords in a htpasswd file.  The entries must have been created with -s for SHA encryption. | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-04 19:05:56 +01:00
										 |  |  | type cacheEntry struct { | 
					
						
							|  |  |  | 	expiry   time.Time | 
					
						
							|  |  |  | 	verifier []byte | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-05 17:18:42 +01:00
										 |  |  | // HtpasswdFile is a map for usernames to passwords. | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | type HtpasswdFile struct { | 
					
						
							| 
									
										
										
										
											2017-10-24 17:48:18 +08:00
										 |  |  | 	mutex    sync.Mutex | 
					
						
							|  |  |  | 	path     string | 
					
						
							|  |  |  | 	stat     os.FileInfo | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 	throttle chan struct{} | 
					
						
							| 
									
										
										
										
											2021-01-04 19:01:15 +01:00
										 |  |  | 	users    map[string]string | 
					
						
							| 
									
										
										
										
											2021-01-04 19:05:56 +01:00
										 |  |  | 	cache    map[string]cacheEntry | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-06 11:15:33 +01:00
										 |  |  | // NewHtpasswdFromFile reads the users and passwords from a htpasswd file and returns them.  If an error is encountered, | 
					
						
							|  |  |  | // it is returned, together with a nil-Pointer for the HtpasswdFile. | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | func NewHtpasswdFromFile(path string) (*HtpasswdFile, error) { | 
					
						
							| 
									
										
										
										
											2019-03-04 16:55:29 -07:00
										 |  |  | 	c := make(chan os.Signal, 1) | 
					
						
							|  |  |  | 	signal.Notify(c, syscall.SIGHUP) | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 	stat, err := os.Stat(path) | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	h := &HtpasswdFile{ | 
					
						
							| 
									
										
										
										
											2017-10-24 17:48:18 +08:00
										 |  |  | 		mutex:    sync.Mutex{}, | 
					
						
							|  |  |  | 		path:     path, | 
					
						
							|  |  |  | 		stat:     stat, | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 		throttle: make(chan struct{}), | 
					
						
							| 
									
										
										
										
											2021-01-04 19:05:56 +01:00
										 |  |  | 		cache:    make(map[string]cacheEntry), | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := h.Reload(); err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-24 18:48:04 +08:00
										 |  |  | 	// Start a goroutine that limits reload checks to once per CheckInterval | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 	go h.throttleTimer() | 
					
						
							| 
									
										
										
										
											2021-01-04 19:05:56 +01:00
										 |  |  | 	go h.expiryTimer() | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-04 16:55:29 -07:00
										 |  |  | 	go func() { | 
					
						
							|  |  |  | 		for range c { | 
					
						
							|  |  |  | 			err := h.Reload() | 
					
						
							|  |  |  | 			if err == nil { | 
					
						
							|  |  |  | 				log.Printf("Reloaded htpasswd file") | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				log.Printf("Could not reload htpasswd file: %v", err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 	return h, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-24 18:48:04 +08:00
										 |  |  | // throttleTimer sends at most one message per CheckInterval to throttle file change checks. | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | func (h *HtpasswdFile) throttleTimer() { | 
					
						
							|  |  |  | 	var check struct{} | 
					
						
							|  |  |  | 	for { | 
					
						
							| 
									
										
										
										
											2017-10-24 18:48:04 +08:00
										 |  |  | 		time.Sleep(CheckInterval) | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 		h.throttle <- check | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-04 19:05:56 +01:00
										 |  |  | func (h *HtpasswdFile) expiryTimer() { | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		time.Sleep(5 * time.Second) | 
					
						
							|  |  |  | 		now := time.Now() | 
					
						
							|  |  |  | 		h.mutex.Lock() | 
					
						
							| 
									
										
										
										
											2021-01-04 19:11:42 +01:00
										 |  |  | 		var zeros [sha256.Size]byte | 
					
						
							|  |  |  | 		// try to wipe expired cache entries | 
					
						
							| 
									
										
										
										
											2021-01-04 19:05:56 +01:00
										 |  |  | 		for user, entry := range h.cache { | 
					
						
							|  |  |  | 			if entry.expiry.After(now) { | 
					
						
							| 
									
										
										
										
											2021-01-04 19:11:42 +01:00
										 |  |  | 				copy(entry.verifier, zeros[:]) | 
					
						
							| 
									
										
										
										
											2021-01-04 19:05:56 +01:00
										 |  |  | 				delete(h.cache, user) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		h.mutex.Unlock() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-12 19:57:13 +01:00
										 |  |  | var validUsernameRegexp = regexp.MustCompile(`^[\p{L}\d@._-]+$`) | 
					
						
							| 
									
										
										
										
											2020-12-23 11:30:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | // Reload reloads the htpasswd file. If the reload fails, the Users map is not changed and the error is returned. | 
					
						
							|  |  |  | func (h *HtpasswdFile) Reload() error { | 
					
						
							|  |  |  | 	r, err := os.Open(h.path) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cr := csv.NewReader(r) | 
					
						
							| 
									
										
										
										
											2016-11-05 17:18:42 +01:00
										 |  |  | 	cr.Comma = ':' | 
					
						
							|  |  |  | 	cr.Comment = '#' | 
					
						
							|  |  |  | 	cr.TrimLeadingSpace = true | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-05 17:18:42 +01:00
										 |  |  | 	records, err := cr.ReadAll() | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-10-25 18:31:34 +02:00
										 |  |  | 		_ = r.Close() | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 	users := make(map[string]string) | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | 	for _, record := range records { | 
					
						
							| 
									
										
										
										
											2020-12-23 11:30:00 +01:00
										 |  |  | 		if !validUsernameRegexp.MatchString(record[0]) { | 
					
						
							| 
									
										
										
										
											2022-02-12 19:57:13 +01:00
										 |  |  | 			log.Printf("Ignoring invalid username %q in htpasswd, consists of characters other than letters, numbers, '_', '-', '.' and '@'", record[0]) | 
					
						
							| 
									
										
										
										
											2020-12-23 11:30:00 +01:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 		users[record[0]] = record[1] | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Replace the Users map | 
					
						
							|  |  |  | 	h.mutex.Lock() | 
					
						
							| 
									
										
										
										
											2021-01-04 19:11:42 +01:00
										 |  |  | 	var zeros [sha256.Size]byte | 
					
						
							|  |  |  | 	// try to wipe the old cache entries | 
					
						
							|  |  |  | 	for _, entry := range h.cache { | 
					
						
							|  |  |  | 		copy(entry.verifier, zeros[:]) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-01-04 19:05:56 +01:00
										 |  |  | 	h.cache = make(map[string]cacheEntry) | 
					
						
							| 
									
										
										
										
											2021-01-04 19:11:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-04 19:01:15 +01:00
										 |  |  | 	h.users = users | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 	h.mutex.Unlock() | 
					
						
							| 
									
										
										
										
											2017-10-25 18:31:34 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	_ = r.Close() | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-24 18:48:04 +08:00
										 |  |  | // ReloadCheck checks at most once per CheckInterval if the file changed and will reload the file if it did. | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | // It logs errors and successful reloads, and returns an error if any was encountered. | 
					
						
							|  |  |  | func (h *HtpasswdFile) ReloadCheck() error { | 
					
						
							|  |  |  | 	select { | 
					
						
							|  |  |  | 	case <-h.throttle: | 
					
						
							|  |  |  | 		stat, err := os.Stat(h.path) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			log.Printf("Could not stat htpasswd file: %v", err) | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		reload := false | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		h.mutex.Lock() | 
					
						
							|  |  |  | 		if stat.ModTime() != h.stat.ModTime() || stat.Size() != h.stat.Size() { | 
					
						
							|  |  |  | 			reload = true | 
					
						
							|  |  |  | 			h.stat = stat | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		h.mutex.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if reload { | 
					
						
							|  |  |  | 			err := h.Reload() | 
					
						
							|  |  |  | 			if err == nil { | 
					
						
							|  |  |  | 				log.Printf("Reloaded htpasswd file") | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				log.Printf("Could not reload htpasswd file: %v", err) | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		// No need to check | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 17:39:16 +01:00
										 |  |  | var shaRe = regexp.MustCompile(`^{SHA}`) | 
					
						
							|  |  |  | var bcrRe = regexp.MustCompile(`^\$2b\$|^\$2a\$|^\$2y\$`) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-06 11:15:33 +01:00
										 |  |  | // Validate returns true if password matches the stored password for user.  If no password for user is stored, or the | 
					
						
							|  |  |  | // password is wrong, false is returned. | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | func (h *HtpasswdFile) Validate(user string, password string) bool { | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 	_ = h.ReloadCheck() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-04 19:05:56 +01:00
										 |  |  | 	hash := sha256.New() | 
					
						
							|  |  |  | 	// hash.Write can never fail | 
					
						
							|  |  |  | 	_, _ = hash.Write([]byte(user)) | 
					
						
							|  |  |  | 	_, _ = hash.Write([]byte(":")) | 
					
						
							|  |  |  | 	_, _ = hash.Write([]byte(password)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 	h.mutex.Lock() | 
					
						
							| 
									
										
										
										
											2021-01-04 19:05:56 +01:00
										 |  |  | 	// avoid race conditions with cache replacements | 
					
						
							|  |  |  | 	cache := h.cache | 
					
						
							| 
									
										
										
										
											2021-03-27 18:05:45 +01:00
										 |  |  | 	hashedPassword, exists := h.users[user] | 
					
						
							| 
									
										
										
										
											2021-01-04 19:05:56 +01:00
										 |  |  | 	entry, cacheExists := h.cache[user] | 
					
						
							| 
									
										
										
										
											2017-10-24 17:35:51 +08:00
										 |  |  | 	h.mutex.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | 	if !exists { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-02-11 14:54:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-04 19:05:56 +01:00
										 |  |  | 	if cacheExists && subtle.ConstantTimeCompare(entry.verifier, hash.Sum(nil)) == 1 { | 
					
						
							| 
									
										
										
										
											2021-01-04 19:16:27 +01:00
										 |  |  | 		h.mutex.Lock() | 
					
						
							|  |  |  | 		// repurpose mutex to prevent concurrent cache updates | 
					
						
							|  |  |  | 		// extend cache entry | 
					
						
							|  |  |  | 		cache[user] = cacheEntry{ | 
					
						
							|  |  |  | 			verifier: entry.verifier, | 
					
						
							|  |  |  | 			expiry:   time.Now().Add(PasswordCacheDuration), | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		h.mutex.Unlock() | 
					
						
							| 
									
										
										
										
											2021-01-04 19:05:56 +01:00
										 |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 18:05:45 +01:00
										 |  |  | 	isValid := isMatchingHashAndPassword(hashedPassword, password) | 
					
						
							| 
									
										
										
										
											2021-01-04 19:05:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if !isValid { | 
					
						
							|  |  |  | 		log.Printf("Invalid htpasswd entry for %s.", user) | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	h.mutex.Lock() | 
					
						
							|  |  |  | 	// repurpose mutex to prevent concurrent cache updates | 
					
						
							|  |  |  | 	cache[user] = cacheEntry{ | 
					
						
							|  |  |  | 		verifier: hash.Sum(nil), | 
					
						
							|  |  |  | 		expiry:   time.Now().Add(PasswordCacheDuration), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	h.mutex.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return true | 
					
						
							| 
									
										
										
										
											2015-09-19 14:28:43 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-03-27 18:05:45 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | func isMatchingHashAndPassword(hashedPassword string, password string) bool { | 
					
						
							|  |  |  | 	switch { | 
					
						
							|  |  |  | 	case shaRe.MatchString(hashedPassword): | 
					
						
							|  |  |  | 		d := sha1.New() | 
					
						
							|  |  |  | 		_, _ = d.Write([]byte(password)) | 
					
						
							|  |  |  | 		if subtle.ConstantTimeCompare([]byte(hashedPassword[5:]), []byte(base64.StdEncoding.EncodeToString(d.Sum(nil)))) == 1 { | 
					
						
							|  |  |  | 			return true | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case bcrRe.MatchString(hashedPassword): | 
					
						
							|  |  |  | 		err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password)) | 
					
						
							|  |  |  | 		if err == nil { | 
					
						
							|  |  |  | 			return true | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return false | 
					
						
							|  |  |  | } |