Compare commits

...
5 Commits
Author SHA1 Message Date
Henrique Dias 764a69cd33 fix: numeric passwords (#24)
License: MIT
Signed-off-by: Henrique Dias <[email protected]>
2019-06-09 13:51:53 +01:00
Henrique Dias d266f1150e fix: auth enabled by default
License: MIT
Signed-off-by: Henrique Dias <[email protected]>
2019-06-09 13:47:28 +01:00
Henrique Dias 76ebaffaef docs: add cors config
License: MIT
Signed-off-by: Henrique Dias <[email protected]>
2019-05-24 14:49:01 +01:00
Henrique Dias 60f2697615 fix: pass through linters
License: MIT
Signed-off-by: Henrique Dias <[email protected]>
2019-05-24 14:47:05 +01:00
oskar e5b3946388 feat: add support for custom CORS headers 2019-05-24 14:43:22 +01:00
7 changed files with 85 additions and 2 deletions
+5
View File
@@ -26,6 +26,11 @@ scope: .
modify: true modify: true
rules: [] rules: []
# CORS configuration
cors:
- enabled: false
allowed_hosts: []
users: users:
- username: admin - username: admin
password: admin password: admin
+1 -1
View File
@@ -9,4 +9,4 @@ func Execute() {
if err := rootCmd.Execute(); err != nil { if err := rootCmd.Execute(); err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }
+41 -1
View File
@@ -5,6 +5,7 @@ import (
"log" "log"
"os" "os"
"regexp" "regexp"
"strconv"
"strings" "strings"
"github.com/hacdias/webdav/webdav" "github.com/hacdias/webdav/webdav"
@@ -81,6 +82,10 @@ func parseUsers(raw []interface{}, c *webdav.Config) {
password, ok := u["password"].(string) password, ok := u["password"].(string)
if !ok { if !ok {
password = "" password = ""
if numPwd, ok := u["password"].(int); ok {
password = strconv.Itoa(numPwd)
}
} }
if strings.HasPrefix(password, "{env}") { if strings.HasPrefix(password, "{env}") {
@@ -118,6 +123,32 @@ func parseUsers(raw []interface{}, c *webdav.Config) {
} }
} }
func parseCors(raw []interface{}, c *webdav.Config) {
hosts := []string{}
for _, v := range raw {
if cfg, ok := v.(map[interface{}]interface{}); ok {
cors := webdav.CorsCfg{
Enabled: cfg["enabled"].(bool),
AllowedHosts: []string{},
}
if allowedHosts, ok := cfg["allowed_hosts"]; ok {
hosts = append(hosts, strings.Split(allowedHosts.(string), ",")...)
}
if len(hosts) == 0 {
hosts = append(hosts, "*")
}
cors.AllowedHosts = hosts
c.Cors = cors
}
}
}
func readConfig(flags *pflag.FlagSet) *webdav.Config { func readConfig(flags *pflag.FlagSet) *webdav.Config {
cfg := &webdav.Config{ cfg := &webdav.Config{
User: &webdav.User{ User: &webdav.User{
@@ -129,7 +160,11 @@ func readConfig(flags *pflag.FlagSet) *webdav.Config {
LockSystem: wd.NewMemLS(), LockSystem: wd.NewMemLS(),
}, },
}, },
Auth: getOptB(flags, "auth"), Auth: getOptB(flags, "auth"),
Cors: webdav.CorsCfg{
Enabled: false,
AllowedHosts: []string{},
},
Users: map[string]*webdav.User{}, Users: map[string]*webdav.User{},
} }
@@ -143,6 +178,11 @@ func readConfig(flags *pflag.FlagSet) *webdav.Config {
parseUsers(users, cfg) parseUsers(users, cfg)
} }
rawCors := v.Get("cors")
if cors, ok := rawCors.([]interface{}); ok {
parseCors(cors, cfg)
}
if len(cfg.Users) != 0 && !cfg.Auth { if len(cfg.Users) != 0 && !cfg.Auth {
log.Print("Users will be ignored due to auth=false") log.Print("Users will be ignored due to auth=false")
} }
+1
View File
@@ -21,6 +21,7 @@ func init() {
flags := rootCmd.Flags() flags := rootCmd.Flags()
flags.StringVarP(&cfgFile, "config", "c", "", "config file path") flags.StringVarP(&cfgFile, "config", "c", "", "config file path")
flags.BoolP("tls", "t", false, "enable tls") flags.BoolP("tls", "t", false, "enable tls")
flags.Bool("auth", true, "enable auth")
flags.String("cert", "cert.pem", "TLS certificate") flags.String("cert", "cert.pem", "TLS certificate")
flags.String("key", "key.pem", "TLS key") flags.String("key", "key.pem", "TLS key")
flags.StringP("address", "a", "0.0.0.0", "address to listen to") flags.StringP("address", "a", "0.0.0.0", "address to listen to")
Regular → Executable
View File
Regular → Executable
+9
View File
@@ -14,3 +14,12 @@ func checkPassword(saved, input string) bool {
return saved == input return saved == input
} }
func isAllowedHost(allowedHosts []string, origin string) bool {
for _, host := range allowedHosts {
if host == origin {
return true
}
}
return false
}
Regular → Executable
+28
View File
@@ -6,16 +6,44 @@ import (
"net/http" "net/http"
) )
// CorsCfg is the CORS config.
type CorsCfg struct {
Enabled bool
AllowedHosts []string
}
// Config is the configuration of a WebDAV instance. // Config is the configuration of a WebDAV instance.
type Config struct { type Config struct {
*User *User
Auth bool Auth bool
Cors CorsCfg
Users map[string]*User Users map[string]*User
} }
// ServeHTTP determines if the request is for this plugin, and if all prerequisites are met. // ServeHTTP determines if the request is for this plugin, and if all prerequisites are met.
func (c *Config) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (c *Config) ServeHTTP(w http.ResponseWriter, r *http.Request) {
u := c.User u := c.User
requestOrigin := r.Header.Get("Origin")
// add cors headers before any operation so even on 401 unauthorized cors will working only when Origin header is present so request came from browser
if c.Cors.Enabled && requestOrigin != "" {
headers := w.Header()
if len(c.Cors.AllowedHosts) == 1 && c.Cors.AllowedHosts[0] == "*" {
headers.Set("Access-Control-Allow-Methods", "*")
headers.Set("Access-Control-Allow-Headers", "*")
headers.Set("Access-Control-Allow-Origin", "*")
} else if isAllowedHost(c.Cors.AllowedHosts, requestOrigin) {
headers.Set("Access-Control-Allow-Origin", requestOrigin)
headers.Set("Access-Control-Allow-Headers", "*")
headers.Set("Access-Control-Allow-Methods", "*")
}
}
if r.Method == "OPTIONS" && c.Cors.Enabled && requestOrigin != "" {
return
}
if c.Auth { if c.Auth {
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`) w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)