@@ -2,6 +2,8 @@ package main
22
33import (
44 "bytes"
5+ "crypto/sha256"
6+ "crypto/subtle"
57 "encoding/json"
68 "fmt"
79 "io/ioutil"
@@ -42,11 +44,11 @@ type Configure struct {
4244 Debug bool `yaml:"debug"`
4345 GoogleTrackerID string `yaml:"google-tracker-id"`
4446 Auth struct {
45- Type string `yaml:"type"` // openid|http|github
46- OpenID string `yaml:"openid"`
47- HTTP string `yaml:"http"`
48- ID string `yaml:"id"` // for oauth2
49- Secret string `yaml:"secret"` // for oauth2
47+ Type string `yaml:"type"` // openid|http|github
48+ OpenID string `yaml:"openid"`
49+ HTTP [] string `yaml:"http"`
50+ ID string `yaml:"id"` // for oauth2
51+ Secret string `yaml:"secret"` // for oauth2
5052 } `yaml:"auth"`
5153 DeepPathMaxDepth int `yaml:"deep-path-max-depth"`
5254 NoIndex bool `yaml:"no-index"`
@@ -113,7 +115,7 @@ func parseFlags() error {
113115 kingpin .Flag ("cert" , "tls cert.pem path" ).StringVar (& gcfg .Cert )
114116 kingpin .Flag ("key" , "tls key.pem path" ).StringVar (& gcfg .Key )
115117 kingpin .Flag ("auth-type" , "Auth type <http|openid>" ).StringVar (& gcfg .Auth .Type )
116- kingpin .Flag ("auth-http" , "HTTP basic auth (ex: user:pass)" ).StringVar (& gcfg .Auth .HTTP )
118+ kingpin .Flag ("auth-http" , "HTTP basic auth (ex: user:pass)" ).StringsVar (& gcfg .Auth .HTTP )
117119 kingpin .Flag ("auth-openid" , "OpenID auth identity url" ).StringVar (& gcfg .Auth .OpenID )
118120 kingpin .Flag ("theme" , "web theme, one of <black|green>" ).StringVar (& gcfg .Theme )
119121 kingpin .Flag ("upload" , "enable upload support" ).BoolVar (& gcfg .Upload )
@@ -165,6 +167,28 @@ func cors(next http.Handler) http.Handler {
165167 })
166168}
167169
170+ func multiBasicAuth (auths []string ) func (http.Handler ) http.Handler {
171+ userPassMap := make (map [string ]string )
172+ for _ , auth := range auths {
173+ userpass := strings .SplitN (auth , ":" , 2 )
174+ if len (userpass ) == 2 {
175+ userPassMap [userpass [0 ]] = userpass [1 ]
176+ }
177+ }
178+ return httpauth .BasicAuth (httpauth.AuthOptions {
179+ Realm : "Restricted" ,
180+ AuthFunc : func (user , pass string , request * http.Request ) bool {
181+ password , ok := userPassMap [user ]
182+ if ! ok {
183+ return false
184+ }
185+ givenPass := sha256 .Sum256 ([]byte (pass ))
186+ requiredPass := sha256 .Sum256 ([]byte (password ))
187+ return subtle .ConstantTimeCompare (givenPass [:], requiredPass [:]) == 1
188+ },
189+ })
190+ }
191+
168192func main () {
169193 if err := parseFlags (); err != nil {
170194 log .Fatal (err )
@@ -208,13 +232,9 @@ func main() {
208232 hdlr = accesslog .NewLoggingHandler (hdlr , logger )
209233
210234 // HTTP Basic Authentication
211- userpass := strings .SplitN (gcfg .Auth .HTTP , ":" , 2 )
212235 switch gcfg .Auth .Type {
213236 case "http" :
214- if len (userpass ) == 2 {
215- user , pass := userpass [0 ], userpass [1 ]
216- hdlr = httpauth .SimpleBasicAuth (user , pass )(hdlr )
217- }
237+ hdlr = multiBasicAuth (gcfg .Auth .HTTP )(hdlr )
218238 case "openid" :
219239 handleOpenID (gcfg .Auth .OpenID , false ) // FIXME(ssx): set secure default to false
220240 // case "github":
0 commit comments