123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- package utils
- import (
- "fmt"
- "os"
- "path/filepath"
- "github.com/0xJacky/Nginx-UI/internal/cache"
- "github.com/0xJacky/Nginx-UI/internal/helper"
- "github.com/0xJacky/Nginx-UI/internal/nginx"
- "github.com/0xJacky/Nginx-UI/settings"
- )
- // IsValidLogPath checks if a log path is valid:
- // 1. It must be a regular file or a symlink to a regular file
- // 2. It must not point to a console or special device
- // 3. It must be under the whitelist directories
- func IsValidLogPath(logPath string) bool {
- // First check if the path is in the whitelist
- if !isLogPathUnderWhiteList(logPath) {
- return false
- }
- // Check if the path exists
- fileInfo, err := os.Lstat(logPath)
- if err != nil {
- // If the file doesn't exist, it might be created later
- // We'll assume it's valid for now
- return true
- }
- // If it's a symlink, follow it safely
- if fileInfo.Mode()&os.ModeSymlink != 0 {
- // Use EvalSymlinks to safely resolve the entire symlink chain
- // This function detects circular symlinks and returns an error
- resolvedPath, err := filepath.EvalSymlinks(logPath)
- if err != nil {
- return false
- }
- // Check the resolved target file
- targetInfo, err := os.Stat(resolvedPath)
- if err != nil {
- return false
- }
- // Only accept regular files as targets
- result := targetInfo.Mode().IsRegular()
- return result
- }
- // For non-symlinks, just check if it's a regular file
- result := fileInfo.Mode().IsRegular()
- return result
- }
- // isLogPathUnderWhiteList checks if a log path is under one of the paths in LogDirWhiteList
- func isLogPathUnderWhiteList(path string) bool {
- prefix := nginx.GetPrefix()
- cacheKey := fmt.Sprintf("isLogPathUnderWhiteList:%s", path)
- res, ok := cache.Get(cacheKey)
- // If cached, return the result directly
- if ok {
- return res.(bool)
- }
- // Only build the whitelist when cache miss occurs
- logDirWhiteList := append([]string{}, settings.NginxSettings.LogDirWhiteList...)
- accessLogPath := nginx.GetAccessLogPath()
- errorLogPath := nginx.GetErrorLogPath()
- if accessLogPath != "" {
- logDirWhiteList = append(logDirWhiteList, filepath.Dir(accessLogPath))
- }
- if errorLogPath != "" {
- logDirWhiteList = append(logDirWhiteList, filepath.Dir(errorLogPath))
- }
- if prefix != "" {
- logDirWhiteList = append(logDirWhiteList, prefix)
- }
- // Check if path is under any whitelist directory
- for _, whitePath := range logDirWhiteList {
- if helper.IsUnderDirectory(path, whitePath) {
- cache.Set(cacheKey, true, 0)
- return true
- }
- }
- // Cache negative result as well to avoid repeated checks
- cache.Set(cacheKey, false, 0)
- return false
- }
|