|
|
|
@ -12,7 +12,6 @@ import (
|
|
|
|
|
|
|
|
|
|
"github.com/grufwub/go-bufpools"
|
|
|
|
|
"github.com/grufwub/go-config"
|
|
|
|
|
"github.com/grufwub/go-errors"
|
|
|
|
|
"github.com/grufwub/go-filecache"
|
|
|
|
|
log "github.com/grufwub/go-logger"
|
|
|
|
|
)
|
|
|
|
@ -23,7 +22,7 @@ func usage(code int) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ParseConfigAndSetup parses necessary core server config from file (and any others defined), and sets up the core ready for Start() to be called
|
|
|
|
|
func ParseConfigAndSetup(tree config.Tree, proto string, defaultPort uint, newListener func() (*Listener, errors.Error), fileContent func(*Path) FileContent, dirHandler func(*Client, *os.File, *Path) errors.Error, largeHandler func(*Client, *os.File, *Path) errors.Error, appendCgi func(*Client, *Request, []string) []string) {
|
|
|
|
|
func ParseConfigAndSetup(tree config.Tree, proto string, defaultPort uint, newListener func() (*Listener, error), fileContent func(*Path) FileContent, dirHandler func(*Client, *os.File, *Path) error, largeHandler func(*Client, *os.File, *Path) error, appendCgi func(*Client, *Request, []string) []string) {
|
|
|
|
|
// Default configuration file location
|
|
|
|
|
configFile := "/etc/gophi." + proto + ".conf"
|
|
|
|
|
|
|
|
|
@ -36,7 +35,7 @@ func ParseConfigAndSetup(tree config.Tree, proto string, defaultPort uint, newLi
|
|
|
|
|
}
|
|
|
|
|
configFile = os.Args[2]
|
|
|
|
|
case "-v", "--version":
|
|
|
|
|
fmt.Println("Gophi (" + proto + ") " + Version)
|
|
|
|
|
fmt.Printf("Gophi (%s) %s\n", proto, Version)
|
|
|
|
|
os.Exit(0)
|
|
|
|
|
default:
|
|
|
|
|
usage(1)
|
|
|
|
@ -95,14 +94,14 @@ func ParseConfigAndSetup(tree config.Tree, proto string, defaultPort uint, newLi
|
|
|
|
|
// Check valid values for BindAddr and Hostname
|
|
|
|
|
if Hostname == "" {
|
|
|
|
|
if Bind == "" {
|
|
|
|
|
SystemLog.Fatal(hostnameBindEmptyStr)
|
|
|
|
|
SystemLog.Fatal("At least one of 'hostname' or 'listen' must be non-empty!")
|
|
|
|
|
}
|
|
|
|
|
Hostname = Bind
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check valid root (i.e. not empty!)
|
|
|
|
|
if Root == "" {
|
|
|
|
|
SystemLog.Fatal(rootDirEmptyErrStr)
|
|
|
|
|
SystemLog.Fatal("No server root directory supplied!")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set port info
|
|
|
|
@ -113,10 +112,10 @@ func ParseConfigAndSetup(tree config.Tree, proto string, defaultPort uint, newLi
|
|
|
|
|
|
|
|
|
|
// Setup listener BEFORE entering chroot
|
|
|
|
|
// in case TLS cert+key needs to be read
|
|
|
|
|
var err errors.Error
|
|
|
|
|
var err error
|
|
|
|
|
serverListener, err = newListener()
|
|
|
|
|
if err != nil {
|
|
|
|
|
SystemLog.Fatalf(listenerBeginFailStr, protocol, Hostname, Port, Bind, Port, err.Error())
|
|
|
|
|
SystemLog.Fatalf("Failed to start listener on %s://%s:%s (%s:%s) - %s", protocol, Hostname, Port, Bind, Port, err.Error())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Setup the sync pools
|
|
|
|
@ -139,33 +138,33 @@ func ParseConfigAndSetup(tree config.Tree, proto string, defaultPort uint, newLi
|
|
|
|
|
// - username but no groupname, we use the user primary gid
|
|
|
|
|
var uid, gid int
|
|
|
|
|
if *username != "" {
|
|
|
|
|
u, osErr := user.Lookup(*username)
|
|
|
|
|
if osErr != nil {
|
|
|
|
|
SystemLog.Fatalf(userLookupErrStr, osErr)
|
|
|
|
|
u, err := user.Lookup(*username)
|
|
|
|
|
if err != nil {
|
|
|
|
|
SystemLog.Fatalf("Error looking up user: %s", err.Error())
|
|
|
|
|
}
|
|
|
|
|
uid, _ = strconv.Atoi(u.Uid)
|
|
|
|
|
gid, _ = strconv.Atoi(u.Gid)
|
|
|
|
|
}
|
|
|
|
|
if *groupname != "" {
|
|
|
|
|
g, osErr := user.LookupGroup(*groupname)
|
|
|
|
|
if osErr != nil {
|
|
|
|
|
SystemLog.Fatalf(groupLookupErrStr, osErr)
|
|
|
|
|
g, err := user.LookupGroup(*groupname)
|
|
|
|
|
if err != nil {
|
|
|
|
|
SystemLog.Fatalf("Error looking up group: %s", err.Error())
|
|
|
|
|
}
|
|
|
|
|
gid, _ = strconv.Atoi(g.Gid)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If chroot provided, change to this!
|
|
|
|
|
if *chroot != "" {
|
|
|
|
|
osErr := syscall.Chroot(*chroot)
|
|
|
|
|
if osErr != nil {
|
|
|
|
|
SystemLog.Fatalf(chrootErrStr, osErr)
|
|
|
|
|
err := syscall.Chroot(*chroot)
|
|
|
|
|
if err != nil {
|
|
|
|
|
SystemLog.Fatalf("Error chrooting into directory: %s", err.Error())
|
|
|
|
|
}
|
|
|
|
|
SystemLog.Infof(chrootStr, *chroot)
|
|
|
|
|
SystemLog.Infof("Chrooting into dir: %s", *chroot)
|
|
|
|
|
|
|
|
|
|
// Ensure we're at root of chroot
|
|
|
|
|
osErr = os.Chdir("/")
|
|
|
|
|
if osErr != nil {
|
|
|
|
|
SystemLog.Fatalf(chDirErrStr, osErr)
|
|
|
|
|
err = os.Chdir("/")
|
|
|
|
|
if err != nil {
|
|
|
|
|
SystemLog.Fatalf("Error entering server directory: %s", err.Error())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -179,33 +178,33 @@ func ParseConfigAndSetup(tree config.Tree, proto string, defaultPort uint, newLi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Change to server root
|
|
|
|
|
osErr := os.Chdir(Root)
|
|
|
|
|
if osErr != nil {
|
|
|
|
|
SystemLog.Fatalf(chDirErrStr, osErr)
|
|
|
|
|
err = os.Chdir(Root)
|
|
|
|
|
if err != nil {
|
|
|
|
|
SystemLog.Fatalf("Error entering server directory: %s", err.Error())
|
|
|
|
|
}
|
|
|
|
|
SystemLog.Infof(chDirStr, Root)
|
|
|
|
|
SystemLog.Infof("Entered server dir: %s", Root)
|
|
|
|
|
|
|
|
|
|
// If been supplied a group, change to requested group
|
|
|
|
|
if *groupname != "" {
|
|
|
|
|
osErr := syscall.Setgid(gid)
|
|
|
|
|
if osErr != nil {
|
|
|
|
|
SystemLog.Fatalf(setgidErrStr, osErr)
|
|
|
|
|
err := syscall.Setgid(gid)
|
|
|
|
|
if err != nil {
|
|
|
|
|
SystemLog.Fatalf("Error performing setgid: %s", err.Error())
|
|
|
|
|
}
|
|
|
|
|
SystemLog.Infof(setgidStr, *groupname)
|
|
|
|
|
SystemLog.Infof("Running as group: %s", *groupname)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If been supplied a user, switch to requested user
|
|
|
|
|
if *username != "" {
|
|
|
|
|
osErr := syscall.Setuid(uid)
|
|
|
|
|
if osErr != nil {
|
|
|
|
|
SystemLog.Fatalf(setuidErrStr, osErr)
|
|
|
|
|
err := syscall.Setuid(uid)
|
|
|
|
|
if err != nil {
|
|
|
|
|
SystemLog.Fatalf("Error performing setuid: %s", err.Error())
|
|
|
|
|
}
|
|
|
|
|
SystemLog.Infof(setuidStr, *username)
|
|
|
|
|
SystemLog.Infof("Running as user: %s", *username)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check not running as root
|
|
|
|
|
if syscall.Geteuid() == 0 || syscall.Getegid() == 0 {
|
|
|
|
|
SystemLog.Fatalf(runningAsRootErrStr)
|
|
|
|
|
SystemLog.Fatal("Gophi does not support running as root!")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FileSystemObject (and related) setup
|
|
|
|
@ -214,40 +213,41 @@ func ParseConfigAndSetup(tree config.Tree, proto string, defaultPort uint, newLi
|
|
|
|
|
|
|
|
|
|
// If no restricted paths provided, set to the disabled function. Else, compile and enable
|
|
|
|
|
if len(*restrictedPathsList) == 0 {
|
|
|
|
|
SystemLog.Info(pathRestrictionsDisabledStr)
|
|
|
|
|
SystemLog.Info("Path restrictions disabled")
|
|
|
|
|
IsRestrictedPath = isRestrictedPathDisabled
|
|
|
|
|
} else {
|
|
|
|
|
SystemLog.Info(pathRestrictionsEnabledStr)
|
|
|
|
|
SystemLog.Info("Path restrictions enabled")
|
|
|
|
|
restrictedPaths = compileRestrictedPathsRegex(*restrictedPathsList)
|
|
|
|
|
IsRestrictedPath = isRestrictedPathEnabled
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If no hidden paths provided, set to the disabled function. Else, compile and enable
|
|
|
|
|
if len(*hiddenPathsList) == 0 {
|
|
|
|
|
SystemLog.Info(pathHidingDisableStr)
|
|
|
|
|
SystemLog.Info("Path hiding disabled")
|
|
|
|
|
IsHiddenPath = isHiddenPathDisabled
|
|
|
|
|
} else {
|
|
|
|
|
SystemLog.Info(pathHidingEnabledStr)
|
|
|
|
|
SystemLog.Info("Path hiding enabled")
|
|
|
|
|
hiddenPaths = compileHiddenPathsRegex(*hiddenPathsList)
|
|
|
|
|
IsHiddenPath = isHiddenPathEnabled
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If no remapped paths provided, set to the disabled function. Else, compile and enable
|
|
|
|
|
if len(*remapRequestsList) == 0 {
|
|
|
|
|
SystemLog.Info(requestRemapDisabledStr)
|
|
|
|
|
SystemLog.Info("Request remapping disabled")
|
|
|
|
|
RemapRequest = remapRequestDisabled
|
|
|
|
|
} else {
|
|
|
|
|
SystemLog.Info(requestRemapEnabledStr)
|
|
|
|
|
SystemLog.Info("Request remapping enabled")
|
|
|
|
|
requestRemaps = compileRequestRemapRegex(*remapRequestsList)
|
|
|
|
|
RemapRequest = remapRequestEnabled
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If no CGI dir supplied, set to disabled function. Else, compile and enable
|
|
|
|
|
if *cgiDir == "" {
|
|
|
|
|
SystemLog.Info(cgiSupportDisabledStr)
|
|
|
|
|
SystemLog.Info("CGI script support disabled")
|
|
|
|
|
WithinCGIDir = withinCGIDirDisabled
|
|
|
|
|
} else {
|
|
|
|
|
SystemLog.Info(cgiSupportEnabledStr)
|
|
|
|
|
SystemLog.Info("CGI script support enabled")
|
|
|
|
|
SystemLog.Infof("CGI safe path: %s", *safePath)
|
|
|
|
|
cgiPath = NewSanitizedPathAtRoot(Root, *cgiDir)
|
|
|
|
|
cgiDirRegex = compileCGIRegex(cgiPath.Relative())
|
|
|
|
|
cgiEnv = setupInitialCGIEnv(*safePath)
|
|
|
|
@ -257,11 +257,11 @@ func ParseConfigAndSetup(tree config.Tree, proto string, defaultPort uint, newLi
|
|
|
|
|
// Set appropriate Path builder function depending
|
|
|
|
|
// on whether user spaces enabled or disabled
|
|
|
|
|
if *userSpacesEnabled {
|
|
|
|
|
SystemLog.Info(userSpacesEnabledStr)
|
|
|
|
|
SystemLog.Info("User spaces support enabled")
|
|
|
|
|
BuildPath = buildPathUserSpacesEnabled
|
|
|
|
|
SystemLog.Infof(userSpacesStr, "public_"+protocol)
|
|
|
|
|
SystemLog.Info("User space directory: public_" + protocol)
|
|
|
|
|
} else {
|
|
|
|
|
SystemLog.Info(userSpacesDisabledStr)
|
|
|
|
|
SystemLog.Info("User spaces support disabled")
|
|
|
|
|
BuildPath = buildPathUserSpacesDisabled
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -287,7 +287,7 @@ func setupLogger(output string) *log.SLogger {
|
|
|
|
|
default:
|
|
|
|
|
file, err := os.OpenFile(output, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf(logOutputErrStr, output, err.Error())
|
|
|
|
|
log.Fatalf("Error opening log output %s: %s", output, err.Error())
|
|
|
|
|
}
|
|
|
|
|
return log.NewSLogger(file, true)
|
|
|
|
|
}
|
|
|
|
|