From eb85a6e94cbeea7fbd624674605f6ecb98cb3ba8 Mon Sep 17 00:00:00 2001 From: Solderpunk Date: Sat, 25 Feb 2023 11:29:13 +0100 Subject: [PATCH] Another big refactor, splitting the Config struct in two. The split reflects that between variables which can and cannot be overridden by .molly files, and this greatly simplifies the processing of said files, getting rid of the need for lots of ugly temporary variable thrashing. --- certificate.go | 2 +- config.go | 200 +++++++++++++++++------------------------ dirlist.go | 4 +- dynamic.go | 10 +-- handler.go | 30 +++---- launch.go | 34 +++---- main.go | 4 +- main_unix.go | 4 +- security.go | 2 +- security_oldgolinux.go | 2 +- security_openbsd.go | 2 +- security_other_unix.go | 2 +- 12 files changed, 129 insertions(+), 167 deletions(-) diff --git a/certificate.go b/certificate.go index 0e89fba..0d39684 100644 --- a/certificate.go +++ b/certificate.go @@ -27,7 +27,7 @@ func enforceCertificateValidity(clientCerts []*x509.Certificate, conn net.Conn, } } -func handleCertificateZones(URL *url.URL, clientCerts []*x509.Certificate, config Config, conn net.Conn, logEntry *LogEntry) { +func handleCertificateZones(URL *url.URL, clientCerts []*x509.Certificate, config UserConfig, conn net.Conn, logEntry *LogEntry) { authorised := true for zone, allowedFingerprints := range config.CertificateZones { matched, err := regexp.Match(zone, []byte(URL.Path)) diff --git a/config.go b/config.go index 3623d1d..c5aa19e 100644 --- a/config.go +++ b/config.go @@ -9,195 +9,167 @@ import ( "strings" ) -type Config struct { +type SysConfig struct { Port int Hostname string CertPath string KeyPath string - DocBase string - HomeDocBase string - GeminiExt string - DefaultLang string - DefaultEncoding string AccessLog string ErrorLog string - ReadMollyFiles bool - TempRedirects map[string]string - PermRedirects map[string]string - MimeOverrides map[string]string + DocBase string + HomeDocBase string CGIPaths []string SCGIPaths map[string]string - CertificateZones map[string][]string + ReadMollyFiles bool AllowTLS12 bool - DirectorySort string - DirectorySubdirsFirst bool - DirectoryReverse bool - DirectoryTitles bool } -type MollyFile struct { +type UserConfig struct { GeminiExt string + DefaultLang string + DefaultEncoding string TempRedirects map[string]string PermRedirects map[string]string MimeOverrides map[string]string CertificateZones map[string][]string - DefaultLang string - DefaultEncoding string DirectorySort string DirectorySubdirsFirst bool DirectoryReverse bool DirectoryTitles bool } -func getConfig(filename string) (Config, error) { +func getConfig(filename string) (SysConfig, UserConfig, error) { - var config Config + var sysConfig SysConfig + var userConfig UserConfig // Defaults - config.Port = 1965 - config.Hostname = "localhost" - config.CertPath = "cert.pem" - config.KeyPath = "key.pem" - config.DocBase = "/var/gemini/" - config.HomeDocBase = "users" - config.GeminiExt = "gmi" - config.DefaultLang = "" - config.DefaultEncoding = "" - config.AccessLog = "access.log" - config.ErrorLog = "" - config.TempRedirects = make(map[string]string) - config.PermRedirects = make(map[string]string) - config.CGIPaths = make([]string, 0) - config.SCGIPaths = make(map[string]string) - config.AllowTLS12 = true - config.DirectorySort = "Name" - config.DirectorySubdirsFirst = false + sysConfig.Port = 1965 + sysConfig.Hostname = "localhost" + sysConfig.CertPath = "cert.pem" + sysConfig.KeyPath = "key.pem" + sysConfig.AccessLog = "access.log" + sysConfig.ErrorLog = "" + sysConfig.DocBase = "/var/gemini/" + sysConfig.HomeDocBase = "users" + sysConfig.CGIPaths = make([]string, 0) + sysConfig.SCGIPaths = make(map[string]string) + sysConfig.ReadMollyFiles = false + sysConfig.AllowTLS12 = true + + userConfig.GeminiExt = "gmi" + userConfig.DefaultLang = "" + userConfig.DefaultEncoding = "" + userConfig.TempRedirects = make(map[string]string) + userConfig.PermRedirects = make(map[string]string) + userConfig.DirectorySort = "Name" + userConfig.DirectorySubdirsFirst = false // Return defaults if no filename given if filename == "" { - return config, nil + return sysConfig, userConfig, nil } // Attempt to overwrite defaults from file - _, err := toml.DecodeFile(filename, &config) + _, err := toml.DecodeFile(filename, &sysConfig) if err != nil { - return config, err + return sysConfig, userConfig, err + } + _, err = toml.DecodeFile(filename, &userConfig) + if err != nil { + return sysConfig, userConfig, err } // Force hostname to lowercase - config.Hostname = strings.ToLower(config.Hostname) + sysConfig.Hostname = strings.ToLower(sysConfig.Hostname) // Validate pseudo-enums - switch config.DirectorySort { - case "Name", "Size", "Time": - default: - return config, errors.New("Invalid DirectorySort value.") + switch userConfig.DirectorySort { + case "Name", "Size", "Time": + default: + return sysConfig, userConfig, errors.New("Invalid DirectorySort value.") } // Absolutise paths - config.DocBase, err = filepath.Abs(config.DocBase) + sysConfig.DocBase, err = filepath.Abs(sysConfig.DocBase) if err != nil { - return config, err + return sysConfig, userConfig, err } - config.CertPath, err = filepath.Abs(config.CertPath) + sysConfig.CertPath, err = filepath.Abs(sysConfig.CertPath) if err != nil { - return config, err + return sysConfig, userConfig, err } - config.KeyPath, err = filepath.Abs(config.KeyPath) + sysConfig.KeyPath, err = filepath.Abs(sysConfig.KeyPath) if err != nil { - return config, err + return sysConfig, userConfig, err } - if config.AccessLog != "" && config.AccessLog != "-" { - config.AccessLog, err = filepath.Abs(config.AccessLog) + if sysConfig.AccessLog != "" && sysConfig.AccessLog != "-" { + sysConfig.AccessLog, err = filepath.Abs(sysConfig.AccessLog) if err != nil { - return config, err + return sysConfig, userConfig, err } } - if config.ErrorLog != "" { - config.ErrorLog, err = filepath.Abs(config.ErrorLog) + if sysConfig.ErrorLog != "" { + sysConfig.ErrorLog, err = filepath.Abs(sysConfig.ErrorLog) if err != nil { - return config, err + return sysConfig, userConfig, err } } // Absolutise CGI paths - for index, cgiPath := range config.CGIPaths { + for index, cgiPath := range sysConfig.CGIPaths { if !filepath.IsAbs(cgiPath) { - config.CGIPaths[index] = filepath.Join(config.DocBase, cgiPath) + sysConfig.CGIPaths[index] = filepath.Join(sysConfig.DocBase, cgiPath) } } // Expand CGI paths var cgiPaths []string - for _, cgiPath := range config.CGIPaths { + for _, cgiPath := range sysConfig.CGIPaths { expandedPaths, err := filepath.Glob(cgiPath) if err != nil { - return config, errors.New("Error expanding CGI path glob " + cgiPath + ": " + err.Error()) + return sysConfig, userConfig, errors.New("Error expanding CGI path glob " + cgiPath + ": " + err.Error()) } cgiPaths = append(cgiPaths, expandedPaths...) } - config.CGIPaths = cgiPaths + sysConfig.CGIPaths = cgiPaths // Absolutise SCGI paths - for index, scgiPath := range config.SCGIPaths { - config.SCGIPaths[index], err = filepath.Abs( scgiPath) + for index, scgiPath := range sysConfig.SCGIPaths { + sysConfig.SCGIPaths[index], err = filepath.Abs( scgiPath) if err != nil { - return config, err + return sysConfig, userConfig, err } } // Validate redirects - for _, value := range config.TempRedirects { + for _, value := range userConfig.TempRedirects { if strings.Contains(value, "://") && !strings.HasPrefix(value, "gemini://") { - return config, errors.New("Invalid cross-protocol redirect to " + value) + return sysConfig, userConfig, errors.New("Invalid cross-protocol redirect to " + value) } } - for _, value := range config.PermRedirects { + for _, value := range userConfig.PermRedirects { if strings.Contains(value, "://") && !strings.HasPrefix(value, "gemini://") { - return config, errors.New("Ignoring cross-protocol redirect to " + value) + return sysConfig, userConfig, errors.New("Ignoring cross-protocol redirect to " + value) } } - return config, nil + return sysConfig, userConfig, nil } -func parseMollyFiles(path string, config *Config) { +func parseMollyFiles(path string, docBase string, config UserConfig) UserConfig { // Replace config variables which use pointers with new ones, // so that changes made here aren't reflected everywhere. - newTempRedirects := make(map[string]string) - for key, value := range config.TempRedirects { - newTempRedirects[key] = value - } - config.TempRedirects = newTempRedirects - newPermRedirects := make(map[string]string) - for key, value := range config.PermRedirects { - newPermRedirects[key] = value - } - config.PermRedirects = newPermRedirects - newMimeOverrides := make(map[string]string) - for key, value := range config.MimeOverrides { - newMimeOverrides[key] = value - } - config.MimeOverrides = newMimeOverrides - newCertificateZones := make(map[string][]string) - for key, value := range config.CertificateZones { - newCertificateZones[key] = value - } - config.CertificateZones = newCertificateZones - // Initialise MollyFile using main Config - var mollyFile MollyFile - mollyFile.GeminiExt = config.GeminiExt - mollyFile.DefaultLang = config.DefaultLang - mollyFile.DefaultEncoding = config.DefaultEncoding - mollyFile.DirectorySort = config.DirectorySort - mollyFile.DirectorySubdirsFirst = config.DirectorySubdirsFirst - mollyFile.DirectoryReverse = config.DirectoryReverse - mollyFile.DirectoryTitles = config.DirectoryTitles + config.TempRedirects = make(map[string]string) + config.PermRedirects = make(map[string]string) + config.MimeOverrides = make(map[string]string) + config.CertificateZones = make(map[string][]string) + // Build list of directories to check var dirs []string dirs = append(dirs, path) for { - if path == filepath.Clean(config.DocBase) { + if path == filepath.Clean(docBase) { break } subpath := filepath.Dir(path) @@ -219,38 +191,28 @@ func parseMollyFiles(path string, config *Config) { continue } // If the file exists and we can read it, try to parse it - _, err = toml.DecodeFile(mollyPath, &mollyFile) + _, err = toml.DecodeFile(mollyPath, &config) if err != nil { log.Println("Error parsing .molly file " + mollyPath + ": " + err.Error()) continue } - // Overwrite main Config using MollyFile - config.GeminiExt = mollyFile.GeminiExt - config.DefaultLang = mollyFile.DefaultLang - config.DefaultEncoding = mollyFile.DefaultEncoding - config.DirectorySort = mollyFile.DirectorySort - config.DirectorySubdirsFirst = mollyFile.DirectorySubdirsFirst - config.DirectoryReverse = mollyFile.DirectoryReverse - config.DirectoryTitles = mollyFile.DirectoryTitles - for key, value := range mollyFile.TempRedirects { + + for key, value := range config.TempRedirects { if strings.Contains(value, "://") && !strings.HasPrefix(value, "gemini://") { log.Println("Ignoring cross-protocol redirect to " + value + " in .molly file " + mollyPath) continue } config.TempRedirects[key] = value } - for key, value := range mollyFile.PermRedirects { + for key, value := range config.PermRedirects { if strings.Contains(value, "://") && !strings.HasPrefix(value, "gemini://") { log.Println("Ignoring cross-protocol redirect to " + value + " in .molly file " + mollyPath) continue } config.PermRedirects[key] = value } - for key, value := range mollyFile.MimeOverrides { - config.MimeOverrides[key] = value - } - for key, value := range mollyFile.CertificateZones { - config.CertificateZones[key] = value - } + } + + return config } diff --git a/dirlist.go b/dirlist.go index 09ecd62..4ef1536 100644 --- a/dirlist.go +++ b/dirlist.go @@ -11,7 +11,7 @@ import ( "strings" ) -func generateDirectoryListing(URL *url.URL, path string, config Config) (string, error) { +func generateDirectoryListing(URL *url.URL, path string, config UserConfig) (string, error) { var listing string files, err := ioutil.ReadDir(path) if err != nil { @@ -82,7 +82,7 @@ func generateDirectoryListing(URL *url.URL, path string, config Config) (string, return listing, nil } -func generatePrettyFileLabel(info os.FileInfo, path string, config Config) string { +func generatePrettyFileLabel(info os.FileInfo, path string, config UserConfig) string { var size string if info.IsDir() { size = " " diff --git a/dynamic.go b/dynamic.go index 8180428..e0cebf0 100644 --- a/dynamic.go +++ b/dynamic.go @@ -15,7 +15,7 @@ import ( "time" ) -func handleCGI(config Config, path string, cgiPath string, URL *url.URL, logEntry *LogEntry, conn net.Conn) { +func handleCGI(config SysConfig, path string, cgiPath string, URL *url.URL, logEntry *LogEntry, conn net.Conn) { // Find the shortest leading part of path which maps to an executable file. // Call this part scriptPath, and everything after it pathInfo. components := strings.Split(path, "/") @@ -86,7 +86,7 @@ func handleCGI(config Config, path string, cgiPath string, URL *url.URL, logEntr conn.Write(response) } -func handleSCGI(URL *url.URL, scgiPath string, scgiSocket string, config Config, logEntry *LogEntry, conn net.Conn) { +func handleSCGI(URL *url.URL, scgiPath string, scgiSocket string, config SysConfig, logEntry *LogEntry, conn net.Conn) { // Connect to socket socket, err := net.Dial("unix", scgiSocket) @@ -148,7 +148,7 @@ func handleSCGI(URL *url.URL, scgiPath string, scgiSocket string, config Config, } } -func prepareCGIVariables(config Config, URL *url.URL, conn net.Conn, script_path string, path_info string) map[string]string { +func prepareCGIVariables(config SysConfig, URL *url.URL, conn net.Conn, script_path string, path_info string) map[string]string { vars := prepareGatewayVariables(config, URL, conn) vars["GATEWAY_INTERFACE"] = "CGI/1.1" vars["SCRIPT_PATH"] = script_path @@ -156,7 +156,7 @@ func prepareCGIVariables(config Config, URL *url.URL, conn net.Conn, script_path return vars } -func prepareSCGIVariables(config Config, URL *url.URL, scgiPath string, conn net.Conn) map[string]string { +func prepareSCGIVariables(config SysConfig, URL *url.URL, scgiPath string, conn net.Conn) map[string]string { vars := prepareGatewayVariables(config, URL, conn) vars["SCGI"] = "1" vars["CONTENT_LENGTH"] = "0" @@ -165,7 +165,7 @@ func prepareSCGIVariables(config Config, URL *url.URL, scgiPath string, conn net return vars } -func prepareGatewayVariables(config Config, URL *url.URL, conn net.Conn) map[string]string { +func prepareGatewayVariables(config SysConfig, URL *url.URL, conn net.Conn) map[string]string { vars := make(map[string]string) vars["QUERY_STRING"] = URL.RawQuery vars["REQUEST_METHOD"] = "" diff --git a/handler.go b/handler.go index 92d7507..7e5ce26 100644 --- a/handler.go +++ b/handler.go @@ -36,7 +36,7 @@ func isSubdir(subdir, superdir string) (bool, error) { return false, nil } -func handleGeminiRequest(conn net.Conn, config Config, accessLogEntries chan LogEntry, wg *sync.WaitGroup) { +func handleGeminiRequest(conn net.Conn, sysConfig SysConfig, config UserConfig, accessLogEntries chan LogEntry, wg *sync.WaitGroup) { defer conn.Close() defer wg.Done() var tlsConn (*tls.Conn) = conn.(*tls.Conn) @@ -75,7 +75,7 @@ func handleGeminiRequest(conn net.Conn, config Config, accessLogEntries chan Log if strings.HasSuffix(requestedHost, ".") { requestedHost = requestedHost[:len(requestedHost)-1] } - if requestedHost != config.Hostname || (URL.Port() != "" && URL.Port() != strconv.Itoa(config.Port)) { + if requestedHost != sysConfig.Hostname || (URL.Port() != "" && URL.Port() != strconv.Itoa(sysConfig.Port)) { conn.Write([]byte("53 No proxying to other hosts or ports!\r\n")) logEntry.Status = 53 return @@ -89,7 +89,7 @@ func handleGeminiRequest(conn net.Conn, config Config, accessLogEntries chan Log } // Resolve URI path to actual filesystem path, including following symlinks - raw_path := resolvePath(URL.Path, config) + raw_path := resolvePath(URL.Path, sysConfig) path, err := filepath.EvalSymlinks(raw_path) if err!= nil { log.Println("Error evaluating path " + raw_path + " for symlinks: " + err.Error()) @@ -99,7 +99,7 @@ func handleGeminiRequest(conn net.Conn, config Config, accessLogEntries chan Log // If symbolic links have been used to escape the intended document directory, // deny all knowledge - isSub, err := isSubdir(path, config.DocBase) + isSub, err := isSubdir(path, sysConfig.DocBase) if err != nil { log.Println("Error testing whether path " + path + " is below DocBase: " + err.Error()) } @@ -114,15 +114,15 @@ func handleGeminiRequest(conn net.Conn, config Config, accessLogEntries chan Log // Paranoid security measures: // Fail ASAP if the URL has mapped to a sensitive file - if path == config.CertPath || path == config.KeyPath || path == config.AccessLog || path == config.ErrorLog || filepath.Base(path) == ".molly" { + if path == sysConfig.CertPath || path == sysConfig.KeyPath || path == sysConfig.AccessLog || path == sysConfig.ErrorLog || filepath.Base(path) == ".molly" { conn.Write([]byte("51 Not found!\r\n")) logEntry.Status = 51 return } // Read Molly files - if config.ReadMollyFiles { - parseMollyFiles(path, &config) + if sysConfig.ReadMollyFiles { + config = parseMollyFiles(path, sysConfig.DocBase, config) } // Check whether this URL is in a certificate zone @@ -138,17 +138,17 @@ func handleGeminiRequest(conn net.Conn, config Config, accessLogEntries chan Log } // Check whether this URL is mapped to an SCGI app - for scgiPath, scgiSocket := range config.SCGIPaths { + for scgiPath, scgiSocket := range sysConfig.SCGIPaths { if strings.HasPrefix(URL.Path, scgiPath) { - handleSCGI(URL, scgiPath, scgiSocket, config, &logEntry, conn) + handleSCGI(URL, scgiPath, scgiSocket, sysConfig, &logEntry, conn) return } } // Check whether this URL is in a configured CGI path - for _, cgiPath := range config.CGIPaths { + for _, cgiPath := range sysConfig.CGIPaths { if strings.HasPrefix(path, cgiPath) { - handleCGI(config, path, cgiPath, URL, &logEntry, conn) + handleCGI(sysConfig, path, cgiPath, URL, &logEntry, conn) if logEntry.Status != 0 { return } @@ -212,7 +212,7 @@ func readRequest(conn net.Conn, logEntry *LogEntry) (*url.URL, error) { return URL, nil } -func resolvePath(path string, config Config) string { +func resolvePath(path string, config SysConfig) string { // Handle tildes if strings.HasPrefix(path, "/~") { bits := strings.Split(path, "/") @@ -226,7 +226,7 @@ func resolvePath(path string, config Config) string { return path } -func handleRedirects(URL *url.URL, config Config, conn net.Conn, logEntry *LogEntry) { +func handleRedirects(URL *url.URL, config UserConfig, conn net.Conn, logEntry *LogEntry) { handleRedirectsInner(URL, config.TempRedirects, 30, conn, logEntry) handleRedirectsInner(URL, config.PermRedirects, 31, conn, logEntry) } @@ -252,7 +252,7 @@ func handleRedirectsInner(URL *url.URL, redirects map[string]string, status int, } } -func serveDirectory(URL *url.URL, path string, logEntry *LogEntry, conn net.Conn, config Config) { +func serveDirectory(URL *url.URL, path string, logEntry *LogEntry, conn net.Conn, config UserConfig) { // Redirect to add trailing slash if missing // (otherwise relative links don't work properly) if !strings.HasSuffix(URL.Path, "/") { @@ -281,7 +281,7 @@ func serveDirectory(URL *url.URL, path string, logEntry *LogEntry, conn net.Conn } } -func serveFile(path string, logEntry *LogEntry, conn net.Conn, config Config) { +func serveFile(path string, logEntry *LogEntry, conn net.Conn, config UserConfig) { // Get MIME type of files ext := filepath.Ext(path) var mimeType string diff --git a/launch.go b/launch.go index 01f99bc..ce68dcb 100644 --- a/launch.go +++ b/launch.go @@ -16,12 +16,12 @@ import ( var VERSION = "0.0.0" -func launch(config Config, privInfo userInfo) int { +func launch(sysConfig SysConfig, userConfig UserConfig, privInfo userInfo) int { var err error // Open log files - if config.ErrorLog != "" { - errorLogFile, err := os.OpenFile(config.ErrorLog, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if sysConfig.ErrorLog != "" { + errorLogFile, err := os.OpenFile(sysConfig.ErrorLog, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Println("Error opening error log file: " + err.Error()) return 1 @@ -32,10 +32,10 @@ func launch(config Config, privInfo userInfo) int { log.SetFlags(log.Ldate|log.Ltime) var accessLogFile *os.File - if config.AccessLog == "-" { + if sysConfig.AccessLog == "-" { accessLogFile = os.Stdout - } else if config.AccessLog != "" { - accessLogFile, err = os.OpenFile(config.AccessLog, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + } else if sysConfig.AccessLog != "" { + accessLogFile, err = os.OpenFile(sysConfig.AccessLog, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Println("Error opening access log file: " + err.Error()) return 1 @@ -45,22 +45,22 @@ func launch(config Config, privInfo userInfo) int { // Read TLS files, create TLS config // Check key file permissions first - info, err := os.Stat(config.KeyPath) + info, err := os.Stat(sysConfig.KeyPath) if err != nil { log.Println("Error opening TLS key file: " + err.Error()) return 1 } if uint64(info.Mode().Perm())&0444 == 0444 { - log.Println("Refusing to use world-readable TLS key file " + config.KeyPath) + log.Println("Refusing to use world-readable TLS key file " + sysConfig.KeyPath) return 1 } // Check certificate hostname matches server hostname - info, err = os.Stat(config.CertPath) + info, err = os.Stat(sysConfig.CertPath) if err != nil { log.Println("Error opening TLS certificate file: " + err.Error()) return 1 } - certFile, err := os.Open(config.CertPath) + certFile, err := os.Open(sysConfig.CertPath) if err != nil { log.Println("Error opening TLS certificate file: " + err.Error()) return 1 @@ -76,7 +76,7 @@ func launch(config Config, privInfo userInfo) int { return 1 } certx509, err := x509.ParseCertificate(certDer.Bytes) - err = certx509.VerifyHostname(config.Hostname) + err = certx509.VerifyHostname(sysConfig.Hostname) if err != nil { log.Println("Invalid TLS certificate: " + err.Error()) return 1 @@ -88,7 +88,7 @@ func launch(config Config, privInfo userInfo) int { } // Load certificate and private key - cert, err := tls.LoadX509KeyPair(config.CertPath, config.KeyPath) + cert, err := tls.LoadX509KeyPair(sysConfig.CertPath, sysConfig.KeyPath) if err != nil { log.Println("Error loading TLS keypair: " + err.Error()) return 1 @@ -96,7 +96,7 @@ func launch(config Config, privInfo userInfo) int { var tlscfg tls.Config tlscfg.Certificates = []tls.Certificate{cert} tlscfg.ClientAuth = tls.RequestClientCert - if config.AllowTLS12 { + if sysConfig.AllowTLS12 { tlscfg.MinVersion = tls.VersionTLS12 } else { tlscfg.MinVersion = tls.VersionTLS13 @@ -110,14 +110,14 @@ func launch(config Config, privInfo userInfo) int { } // Apply security restrictions - err = enableSecurityRestrictions(config, privInfo) + err = enableSecurityRestrictions(sysConfig, privInfo) if err != nil { log.Println("Exiting due to failure to apply security restrictions.") return 1 } // Create TLS listener - listener, err := tls.Listen("tcp", ":"+strconv.Itoa(config.Port), &tlscfg) + listener, err := tls.Listen("tcp", ":"+strconv.Itoa(sysConfig.Port), &tlscfg) if err != nil { log.Println("Error creating TLS listener: " + err.Error()) return 1 @@ -126,7 +126,7 @@ func launch(config Config, privInfo userInfo) int { // Start log handling routines var accessLogEntries chan LogEntry - if config.AccessLog == "" { + if sysConfig.AccessLog == "" { accessLogEntries = nil } else { accessLogEntries = make(chan LogEntry, 10) @@ -156,7 +156,7 @@ func launch(config Config, privInfo userInfo) int { conn, err := listener.Accept() if err == nil { wg.Add(1) - go handleGeminiRequest(conn, config, accessLogEntries, &wg) + go handleGeminiRequest(conn, sysConfig, userConfig, accessLogEntries, &wg) } else { select { case <-shutdown: diff --git a/main.go b/main.go index 1991a33..04a7b5a 100644 --- a/main.go +++ b/main.go @@ -25,12 +25,12 @@ func main() { } // Read config - config, err := getConfig(conf_file) + sysConfig, userConfig, err := getConfig(conf_file) if err != nil { log.Fatal(err) } // Run server and exit var dummy userInfo - os.Exit(launch(config, dummy)) + os.Exit(launch(sysConfig, userConfig, dummy)) } diff --git a/main_unix.go b/main_unix.go index 0a25e23..9a0acfe 100644 --- a/main_unix.go +++ b/main_unix.go @@ -30,7 +30,7 @@ func main() { } // Read config - config, err := getConfig(conf_file) + sysConfig, userConfig, err := getConfig(conf_file) if err != nil { log.Fatal(err) } @@ -51,5 +51,5 @@ func main() { } // Run server and exit - os.Exit(launch(config, privInfo)) + os.Exit(launch(sysConfig, userConfig, privInfo)) } diff --git a/security.go b/security.go index 2bd11f1..66a2104 100644 --- a/security.go +++ b/security.go @@ -9,6 +9,6 @@ type userInfo struct { // This is intended to be called immediately prior to accepting client // connections and may be used to establish a security "jail" for the molly // brown executable. -func enableSecurityRestrictions(config Config, ui userInfo) error { +func enableSecurityRestrictions(config SysConfig, ui userInfo) error { return nil } diff --git a/security_oldgolinux.go b/security_oldgolinux.go index 25271dd..88eb1c1 100644 --- a/security_oldgolinux.go +++ b/security_oldgolinux.go @@ -7,7 +7,7 @@ import ( "os" ) -func enableSecurityRestrictions(config Config, ui userInfo) error { +func enableSecurityRestrictions(config SysConfig, ui userInfo) error { // Prior to Go 1.6, setuid did not work reliably on Linux // So, absolutely refuse to run as root diff --git a/security_openbsd.go b/security_openbsd.go index 2b008b4..b6660d1 100644 --- a/security_openbsd.go +++ b/security_openbsd.go @@ -11,7 +11,7 @@ import ( // operations available to the molly brown executable. Please note that (S)CGI // processes that molly brown spawns or communicates with are unrestricted // and should pledge their own restrictions and unveil their own files. -func enableSecurityRestrictions(config Config, ui userInfo) error { +func enableSecurityRestrictions(config SysConfig, ui userInfo) error { // Setuid to an unprivileged user err := DropPrivs(ui) diff --git a/security_other_unix.go b/security_other_unix.go index e627d73..1865a23 100644 --- a/security_other_unix.go +++ b/security_other_unix.go @@ -2,7 +2,7 @@ package main -func enableSecurityRestrictions(config Config, ui userInfo) error { +func enableSecurityRestrictions(config SysConfig, ui userInfo) error { // Setuid to an unprivileged user return DropPrivs(ui)