102 lines
2.2 KiB
Go
102 lines
2.2 KiB
Go
// server9p.go - State management for 9P toolsrv
|
|
package toolsrv
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"runtime"
|
|
"sync"
|
|
|
|
"ollie/fsedsl"
|
|
)
|
|
|
|
// Server9P holds the state for the 9P tool server.
|
|
type Server9P struct {
|
|
mu sync.RWMutex
|
|
|
|
secret string // set on first auth, verified on subsequent
|
|
token string // session token returned after auth
|
|
registry *Registry // tool registry
|
|
sessID string // session ID for registry scoping
|
|
yolo bool // skip sandbox
|
|
|
|
// Process management
|
|
fs *FS9P
|
|
}
|
|
|
|
// NewServer9P creates a new 9P tool server.
|
|
func NewServer9P() *Server9P {
|
|
return &Server9P{
|
|
fs: NewFS9P(""), // cwd set per-agent
|
|
}
|
|
}
|
|
|
|
// SetRegistry configures the tool registry and session ID.
|
|
func (s *Server9P) SetRegistry(r *Registry, sessID string) {
|
|
s.mu.Lock()
|
|
s.registry = r
|
|
s.sessID = sessID
|
|
s.fs.SetRegistry(r, sessID)
|
|
s.mu.Unlock()
|
|
}
|
|
|
|
// SetYolo enables/disables sandbox bypass.
|
|
func (s *Server9P) SetYolo(yolo bool) {
|
|
s.mu.Lock()
|
|
s.yolo = yolo
|
|
s.fs.SetYolo(yolo)
|
|
s.mu.Unlock()
|
|
}
|
|
|
|
// Authenticate handles secret verification.
|
|
// First call sets the secret; subsequent calls must match it.
|
|
// Returns (token, nil) on success, ("", error) on failure.
|
|
func (s *Server9P) Authenticate(clientSecret string) (string, error) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
|
|
if s.secret == "" {
|
|
// First auth - set the secret
|
|
s.secret = clientSecret
|
|
s.token = randomToken()
|
|
return s.token, nil
|
|
}
|
|
|
|
// Subsequent auth - verify secret
|
|
if clientSecret != s.secret {
|
|
return "", fmt.Errorf("authentication failed")
|
|
}
|
|
|
|
return s.token, nil
|
|
}
|
|
|
|
// Token returns the current session token (empty if not authenticated).
|
|
func (s *Server9P) Token() string {
|
|
s.mu.RLock()
|
|
defer s.mu.RUnlock()
|
|
return s.token
|
|
}
|
|
|
|
// HostInfo returns platform info as key=value lines.
|
|
func (s *Server9P) HostInfo() string {
|
|
return fmt.Sprintf("platform=%s\narch=%s\n", runtime.GOOS, runtime.GOARCH)
|
|
}
|
|
|
|
// FS returns the underlying filesystem state.
|
|
func (s *Server9P) FS() *FS9P {
|
|
return s.fs
|
|
}
|
|
|
|
// BuildTree creates the fsedsl tree for this server.
|
|
func (s *Server9P) BuildTree() *fsedsl.Tree {
|
|
ctx := ToolsrvCtx{Server: s}
|
|
return fsedsl.BuildTree(ToolsrvSpec(), ctx)
|
|
}
|
|
|
|
func randomToken() string {
|
|
b := make([]byte, 16)
|
|
rand.Read(b)
|
|
return hex.EncodeToString(b)
|
|
}
|