2026-04-06 00:20:51 -05:00

256 lines
6.7 KiB
Go

package profile
import (
"AdaptixServer/core/utils/logs"
isvalid "AdaptixServer/core/utils/valid"
"errors"
"os"
"strings"
)
func tlsVersionRank(v string) (int, bool) {
s := normalizeTLSVersion(v)
switch s {
case "", "DEFAULT":
return 0, true
case "TLS10", "TLS1.0":
return 10, true
case "TLS11", "TLS1.1":
return 11, true
case "TLS12", "TLS1.2":
return 12, true
case "TLS13", "TLS1.3":
return 13, true
default:
return 0, false
}
}
func normalizeTLSVersion(v string) string {
s := strings.TrimSpace(strings.ToUpper(v))
s = strings.ReplaceAll(s, "_", "")
s = strings.ReplaceAll(s, "-", "")
return s
}
func isAllowedTLSVersion(v string) bool {
s := normalizeTLSVersion(v)
switch s {
case "", "DEFAULT", "TLS10", "TLS1.0", "TLS11", "TLS1.1", "TLS12", "TLS1.2", "TLS13", "TLS1.3":
return true
default:
return false
}
}
func (p *AdaptixProfile) applyDefaults() {
if p.HttpServer == nil {
p.HttpServer = &TsHttpServer{}
}
if p.HttpServer.Error == nil {
p.HttpServer.Error = &TsHttpError{}
}
if p.HttpServer.Error.Status == 0 {
p.HttpServer.Error.Status = 404
}
if p.HttpServer.Error.Headers == nil {
p.HttpServer.Error.Headers = map[string]string{}
}
if p.HttpServer.HTTP == nil {
p.HttpServer.HTTP = &TsHTTPConfig{}
}
if p.HttpServer.HTTP.MaxHeaderBytes == 0 {
p.HttpServer.HTTP.MaxHeaderBytes = 8192
}
if p.HttpServer.HTTP.RequestTimeoutSec == 0 {
p.HttpServer.HTTP.RequestTimeoutSec = 300
}
if p.HttpServer.HTTP.RequestTimeoutMessage == "" {
p.HttpServer.HTTP.RequestTimeoutMessage = "504 Gateway Timeout"
}
if p.HttpServer.TLS == nil {
p.HttpServer.TLS = &TsTLSConfig{}
}
if p.HttpServer.TLS.MinVersion == "" {
p.HttpServer.TLS.MinVersion = "TLS1.2"
}
if p.HttpServer.TLS.MaxVersion == "" {
p.HttpServer.TLS.MaxVersion = "TLS1.3"
}
}
func (p *AdaptixProfile) prepareHttpServer() {
p.applyDefaults()
if p.HttpServer != nil && p.HttpServer.Error != nil && p.HttpServer.Error.PagePath != "" {
fileContent, err := os.ReadFile(p.HttpServer.Error.PagePath)
if err != nil {
logs.Error("", "'HttpServer.error.page': failed to read file: %v", err)
return
}
p.HttpServer.Error.PageContent = string(fileContent)
}
}
func NewProfile() *AdaptixProfile {
return new(AdaptixProfile)
}
func (p *AdaptixProfile) IsValid() error {
valid := true
p.prepareHttpServer()
if p.Server == nil {
logs.Error("", "'Teamserver' must be set")
valid = false
} else {
if p.Server.Port < 1 || 65535 < p.Server.Port {
logs.Error("", "'Teamserver.port' must be between 1 and 65535 (current is %v)", p.Server.Port)
valid = false
}
if isvalid.ValidUriString(p.Server.Endpoint) == false {
logs.Error("'Teamserver.endpoint' must be valid URI value (current is %v)", p.Server.Endpoint)
valid = false
}
if p.Server.Password == "" {
logs.Error("", "'Teamserver.password' must be set")
valid = false
}
if p.Server.Cert == "" {
logs.Error("", "'Teamserver.cert' must be set")
valid = false
} else {
_, err := os.Stat(p.Server.Cert)
if err != nil {
if os.IsNotExist(err) {
logs.Error("", "'Teamserver.cert': file does not exists")
valid = false
} else {
logs.Error("", "'Teamserver.cert': failed to stat file: %v", err)
valid = false
}
}
}
if p.Server.Key == "" {
logs.Error("", "'Teamserver.key' must be set")
valid = false
} else {
_, err := os.Stat(p.Server.Key)
if err != nil {
if os.IsNotExist(err) {
logs.Error("", "'Teamserver.key': file does not exists")
valid = false
} else {
logs.Error("", "'Teamserver.key': failed to stat file: %v", err)
valid = false
}
}
}
if p.Server.Extenders != nil {
for _, ext := range p.Server.Extenders {
if ext != "" {
_, err := os.Stat(ext)
if err != nil {
if os.IsNotExist(err) {
logs.Error("", "Extender %s: file does not exists", ext)
valid = false
} else {
logs.Error("", "Extender %s: failed to stat file: %v", ext, err)
valid = false
}
}
}
}
}
if p.Server.ATokenLive < 1 {
logs.Error("", "'Teamserver.access_token_live_hours' must be set")
valid = false
}
if p.Server.RTokenLive < 1 {
logs.Error("", "'Teamserver.refresh_token_live_hours' must be set")
valid = false
}
}
if p.HttpServer == nil {
logs.Error("", "'HttpServer' must be set")
valid = false
} else {
if p.HttpServer.Error.Status < 100 || p.HttpServer.Error.Status > 999 {
logs.Error("", "'HttpServer.error.status' must be valid HTTP status (current is %v)", p.HttpServer.Error.Status)
valid = false
}
if p.HttpServer.Error.PagePath != "" {
_, err := os.Stat(p.HttpServer.Error.PagePath)
if err != nil {
if os.IsNotExist(err) {
logs.Error("", "'HttpServer.error.page': file does not exists")
valid = false
} else {
logs.Error("", "'HttpServer.error.page': failed to stat file: %v", err)
valid = false
}
}
if p.HttpServer.Error.PageContent == "" {
logs.Error("", "'HttpServer.error.page': file is empty or cannot be read")
valid = false
}
}
if p.HttpServer.HTTP.MaxHeaderBytes < 0 {
logs.Error("", "'HttpServer.http.max_header_bytes' must be >= 0")
valid = false
}
if p.HttpServer.HTTP.ReadHeaderTimeoutSec < 0 {
logs.Error("", "'HttpServer.http.read_header_timeout_sec' must be >= 0")
valid = false
}
if p.HttpServer.HTTP.ReadTimeoutSec < 0 {
logs.Error("", "'HttpServer.http.read_timeout_sec' must be >= 0")
valid = false
}
if p.HttpServer.HTTP.WriteTimeoutSec < 0 {
logs.Error("", "'HttpServer.http.write_timeout_sec' must be >= 0")
valid = false
}
if p.HttpServer.HTTP.IdleTimeoutSec < 0 {
logs.Error("", "'HttpServer.http.idle_timeout_sec' must be >= 0")
valid = false
}
if p.HttpServer.HTTP.RequestTimeoutSec < 0 {
logs.Error("", "'HttpServer.http.request_timeout_sec' must be >= 0")
valid = false
}
if p.HttpServer.TLS.MinVersion != "" && !isAllowedTLSVersion(p.HttpServer.TLS.MinVersion) {
logs.Error("", "'HttpServer.tls.min_version' has unsupported value (current is %v)", p.HttpServer.TLS.MinVersion)
valid = false
}
if p.HttpServer.TLS.MaxVersion != "" && !isAllowedTLSVersion(p.HttpServer.TLS.MaxVersion) {
logs.Error("", "'HttpServer.tls.max_version' has unsupported value (current is %v)", p.HttpServer.TLS.MaxVersion)
valid = false
}
minRank, okMin := tlsVersionRank(p.HttpServer.TLS.MinVersion)
maxRank, okMax := tlsVersionRank(p.HttpServer.TLS.MaxVersion)
if okMin && okMax && minRank != 0 && maxRank != 0 && minRank > maxRank {
logs.Error("", "'HttpServer.tls.min_version' must be <= 'HttpServer.tls.max_version' (current is %v > %v)", p.HttpServer.TLS.MinVersion, p.HttpServer.TLS.MaxVersion)
valid = false
}
}
if valid {
return nil
}
return errors.New("Invalid profile\n")
}