164 lines
4.0 KiB
Go
164 lines
4.0 KiB
Go
package main
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
)
|
|
|
|
// Default operator listener
|
|
var defaultOperatorListenerAddr = "0.0.0.0:8080"
|
|
|
|
// Default HTTPS listener address and port
|
|
var defaultListenHTTPSaddr = []string{"test1.com"}
|
|
var defaultListenHTTPSport = "8443"
|
|
|
|
// To store server's password
|
|
var serverPass *string
|
|
var serverHashedPass string
|
|
|
|
// Developer mode
|
|
var DevelMode bool
|
|
|
|
// Certificates
|
|
var serverCertPath = "certificates/server.crt"
|
|
var serverKeyPath = "certificates/server.key"
|
|
var caCertPath = "certificates/ca.crt"
|
|
|
|
// Global, as will be shared
|
|
var tlsConfig *tls.Config
|
|
|
|
func main() {
|
|
|
|
// log.SetFlags(log.Ltime | log.Lshortfile)
|
|
log.SetFlags(log.Ltime)
|
|
|
|
// Handle signals for graceful shutdown
|
|
stop := make(chan os.Signal, 1)
|
|
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
|
|
|
|
// Load avaialbe modules from directory
|
|
InitModules()
|
|
|
|
go func() {
|
|
<-stop
|
|
log.Println("Shutting down server gracefully...")
|
|
os.Exit(0)
|
|
}()
|
|
|
|
// Parse arguments
|
|
serverPass = flag.String("p", "", "Password for operator authentication")
|
|
serverAddr := flag.String("ip", defaultOperatorListenerAddr, "IP address and port to listen for operators")
|
|
flag.BoolVar(&DevelMode, "devel", false, "Developer mode")
|
|
flag.Parse()
|
|
|
|
// Check if pass is provided
|
|
if *serverPass == "" {
|
|
log.Println("Usage: server.exe -p <password>")
|
|
return
|
|
}
|
|
log.Println("Server password set.")
|
|
|
|
// Store hashed server password
|
|
serverHashedPass = HashPassword(serverPass)
|
|
|
|
// Load CA certificate
|
|
caCert, err := os.ReadFile(caCertPath)
|
|
if err != nil {
|
|
log.Fatalf("Failed to read CA certificate: %v", err)
|
|
}
|
|
|
|
// Load our CA cert for mTLS
|
|
caCertPool := x509.NewCertPool()
|
|
if !caCertPool.AppendCertsFromPEM(caCert) {
|
|
log.Fatal("Failed to append CA certificate to pool")
|
|
}
|
|
|
|
// Load certificates
|
|
cert, err := tls.LoadX509KeyPair(serverCertPath, serverKeyPath)
|
|
if err != nil {
|
|
fmt.Println("Error loading certificates:", err)
|
|
return
|
|
}
|
|
|
|
// Init TLS context
|
|
tlsConfig = &tls.Config{
|
|
Certificates: []tls.Certificate{cert},
|
|
ClientCAs: caCertPool,
|
|
ClientAuth: tls.RequireAndVerifyClientCert, // Client cert will be requested and verified
|
|
}
|
|
// Skip cert verifications if developing or debugging
|
|
if DevelMode {
|
|
log.Print("Skipping mTLS in devel mode")
|
|
tlsConfig.ClientAuth = tls.NoClientCert
|
|
}
|
|
|
|
// Goroutines
|
|
// Start default operator listener
|
|
go ListenForOperator(tlsConfig, serverAddr)
|
|
|
|
// Initialize configuration
|
|
if err := InitConfig(); err != nil {
|
|
log.Fatal("Failed to initialize configuration:", err)
|
|
}
|
|
|
|
// Start default agent listeners
|
|
if DevelMode {
|
|
StartAgentListener("https", defaultListenHTTPSaddr, defaultListenHTTPSport, "default_HTTPS", nil)
|
|
}
|
|
|
|
select {}
|
|
}
|
|
|
|
// Start listening for operators
|
|
func ListenForOperator(tlsConfig *tls.Config, serverAddr *string) {
|
|
|
|
// Start listening for operators
|
|
listener, err := tls.Listen("tcp", *serverAddr, tlsConfig)
|
|
if err != nil {
|
|
log.Fatalf("Error starting operator server: %v", err)
|
|
return
|
|
}
|
|
defer listener.Close()
|
|
|
|
// Accept connection via go routine
|
|
for {
|
|
operatorConn, err := listener.Accept()
|
|
if err != nil {
|
|
log.Printf("Error accepting connection: %v", err)
|
|
continue
|
|
}
|
|
go HandleOperatorConnection(operatorConn)
|
|
}
|
|
}
|
|
|
|
// Log operator's connection, authenticate and start parsing commands
|
|
func HandleOperatorConnection(operatorConn net.Conn) {
|
|
defer func() {
|
|
log.Printf("Operator connection closed from: %s", operatorConn.RemoteAddr())
|
|
log.Printf("\n")
|
|
operatorConn.Close()
|
|
}()
|
|
|
|
// Authenticate operator
|
|
operatorID, authenticated := AuthenticateOperator(operatorConn, serverHashedPass)
|
|
|
|
if !authenticated {
|
|
log.Printf("Authentication failed")
|
|
return
|
|
}
|
|
|
|
// Update dynamic tab completion right after operator connects
|
|
UpdateListenersTabCompletion()
|
|
UpdateAgentsTabCompletion()
|
|
|
|
// Handle operator commands after successful authentication
|
|
ParseOperatorCommands(operatorConn, operatorID)
|
|
}
|