aboutsummaryrefslogtreecommitdiff
path: root/internal/net/server.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-29 01:00:17 -0400
committerhistoria <[not public]>2026-06-29 01:00:17 -0400
commite9d87838590a02c7ca028fad8cd16e42a582dd32 (patch)
tree0d9770d8fc728946c5452e732efbad393a745a23 /internal/net/server.go
parentfffc132263ab7d3c402992bffbaae4790161f7a7 (diff)
downloadthehouseoficarus-e9d87838590a02c7ca028fad8cd16e42a582dd32.tar.gz
feat: self-signed certificates
Diffstat (limited to 'internal/net/server.go')
-rw-r--r--internal/net/server.go106
1 files changed, 88 insertions, 18 deletions
diff --git a/internal/net/server.go b/internal/net/server.go
index 851a4b5..345122e 100644
--- a/internal/net/server.go
+++ b/internal/net/server.go
@@ -1,12 +1,18 @@
package net
import (
+ "crypto/rand"
+ "crypto/rsa"
"crypto/tls"
+ "crypto/x509"
+ "crypto/x509/pkix"
"fmt"
"log"
+ "math/big"
"net"
"net/http"
"sync"
+ "time"
"thehouseoficarus/internal/behavior"
"thehouseoficarus/internal/color"
@@ -70,13 +76,14 @@ type Session struct {
}
type Server struct {
- config *config.Config
- telnetLn net.Listener
- telnetTLSLn net.Listener
- httpServer *http.Server
- httpsServer *http.Server
- hub *Hub
- handler func(*Session, string)
+ config *config.Config
+ telnetLn net.Listener
+ telnetTLSLn net.Listener
+ httpServer *http.Server
+ httpsServer *http.Server
+ httpsTLSConfig *tls.Config
+ hub *Hub
+ handler func(*Session, string)
}
type Hub struct {
@@ -192,12 +199,20 @@ func NewServer(cfg *config.Config) (*Server, error) {
}
if cfg.TelnetTLS.Enabled {
+ var cert tls.Certificate
if cfg.TelnetTLS.CertFile == "" || cfg.TelnetTLS.KeyFile == "" {
- return nil, fmt.Errorf("telnet_tls enabled but cert_file and key_file are required")
- }
- cert, err := tls.LoadX509KeyPair(cfg.TelnetTLS.CertFile, cfg.TelnetTLS.KeyFile)
- if err != nil {
- return nil, fmt.Errorf("telnet_tls cert: %w", err)
+ var err error
+ cert, err = generateSelfSignedCert()
+ if err != nil {
+ return nil, fmt.Errorf("telnet_tls self-signed cert: %w", err)
+ }
+ log.Printf("telnet_tls: using self-signed certificate (no cert_file/key_file configured)")
+ } else {
+ var err error
+ cert, err = tls.LoadX509KeyPair(cfg.TelnetTLS.CertFile, cfg.TelnetTLS.KeyFile)
+ if err != nil {
+ return nil, fmt.Errorf("telnet_tls cert: %w", err)
+ }
}
tlsCfg := &tls.Config{
Certificates: []tls.Certificate{cert},
@@ -219,19 +234,68 @@ func NewServer(cfg *config.Config) (*Server, error) {
}
if cfg.HTTPS.Enabled {
+ var cert tls.Certificate
if cfg.HTTPS.CertFile == "" || cfg.HTTPS.KeyFile == "" {
- return nil, fmt.Errorf("https enabled but cert_file and key_file are required")
+ var err error
+ cert, err = generateSelfSignedCert()
+ if err != nil {
+ return nil, fmt.Errorf("https self-signed cert: %w", err)
+ }
+ log.Printf("https: using self-signed certificate (no cert_file/key_file configured)")
+ } else {
+ var err error
+ cert, err = tls.LoadX509KeyPair(cfg.HTTPS.CertFile, cfg.HTTPS.KeyFile)
+ if err != nil {
+ return nil, fmt.Errorf("https cert: %w", err)
+ }
+ }
+ s.httpsTLSConfig = &tls.Config{
+ Certificates: []tls.Certificate{cert},
+ MinVersion: tls.VersionTLS12,
}
s.httpsServer = &http.Server{
- Addr: fmt.Sprintf(":%d", cfg.HTTPS.Port),
- Handler: newHTTPMux(s),
- TLSConfig: &tls.Config{MinVersion: tls.VersionTLS12},
+ Addr: fmt.Sprintf(":%d", cfg.HTTPS.Port),
+ Handler: newHTTPMux(s),
}
}
return s, nil
}
+func generateSelfSignedCert() (tls.Certificate, error) {
+ key, err := rsa.GenerateKey(rand.Reader, 2048)
+ if err != nil {
+ return tls.Certificate{}, fmt.Errorf("rsa key generation: %w", err)
+ }
+ serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
+ if err != nil {
+ return tls.Certificate{}, fmt.Errorf("serial number: %w", err)
+ }
+ now := time.Now()
+ template := &x509.Certificate{
+ SerialNumber: serial,
+ Subject: pkix.Name{
+ CommonName: "THOI Self-Signed Certificate",
+ },
+ NotBefore: now.Add(-1 * time.Hour),
+ NotAfter: now.Add(365 * 24 * time.Hour),
+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+ BasicConstraintsValid: true,
+ IsCA: true,
+ DNSNames: []string{"localhost"},
+ IPAddresses: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")},
+ }
+ certDER, err := x509.CreateCertificate(rand.Reader, template, template, &key.PublicKey, key)
+ if err != nil {
+ return tls.Certificate{}, fmt.Errorf("x509 creation: %w", err)
+ }
+ return tls.Certificate{
+ Certificate: [][]byte{certDER},
+ PrivateKey: key,
+ }, nil
+}
+
func (s *Server) Hub() *Hub {
return s.hub
}
@@ -300,8 +364,14 @@ func (s *Server) serveHTTP() {
}
func (s *Server) serveHTTPS() {
- err := s.httpsServer.ListenAndServeTLS(s.config.HTTPS.CertFile, s.config.HTTPS.KeyFile)
- if err != nil && err != http.ErrServerClosed {
+ addr := fmt.Sprintf(":%d", s.config.HTTPS.Port)
+ ln, err := net.Listen("tcp", addr)
+ if err != nil {
+ log.Printf("https server error: %v", err)
+ return
+ }
+ tlsLn := tls.NewListener(ln, s.httpsTLSConfig)
+ if err := s.httpsServer.Serve(tlsLn); err != nil && err != http.ErrServerClosed {
log.Printf("https server error: %v", err)
}
}