192 lines
4.4 KiB
Go
192 lines
4.4 KiB
Go
package fs
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"ollie/bypass"
|
|
"ollie/session"
|
|
)
|
|
|
|
func readSessionIdx(_ HandlerCtx) ([]byte, error) {
|
|
return session.BuildIndex(), nil
|
|
}
|
|
|
|
func readAgentIdx(ctx HandlerCtx) ([]byte, error) {
|
|
return session.BuildAgentIndex(ctx.Session.Core), nil
|
|
}
|
|
|
|
func requestSessionNew(_ HandlerCtx, data []byte) ([]byte, error) {
|
|
args := strings.Fields(string(data))
|
|
name := ""
|
|
remote := ""
|
|
for _, arg := range args {
|
|
if k, v, ok := strings.Cut(arg, "="); ok {
|
|
switch k {
|
|
case "name":
|
|
name = v
|
|
case "remote":
|
|
remote = v
|
|
}
|
|
}
|
|
}
|
|
sess, err := session.CreateEmpty(name, remote)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return []byte(sess.Name() + "\n"), nil
|
|
}
|
|
|
|
// sessionBindings returns bindings for all sessions.
|
|
// The Blueprint pattern clones the structure and binds ctx.Session.
|
|
func sessionBindings(ctx HandlerCtx) ([]Binding, error) {
|
|
rs := ctx.RootState
|
|
sessions := session.Sessions()
|
|
|
|
out := make([]Binding, 0, len(sessions))
|
|
for name, sess := range sessions {
|
|
// Get or create cached SessionNode wrapper
|
|
node := rs.GetOrCreateNode(sess)
|
|
n := name // capture
|
|
out = append(out, Binding{
|
|
Name: sess.Name(),
|
|
Aliases: []string{sess.ID},
|
|
UID: sess.Uname,
|
|
GID: "agent",
|
|
Applier: func(c HandlerCtx) HandlerCtx {
|
|
c.Context = node.Ctx()
|
|
c.Session = node
|
|
c.Remove = func() {
|
|
session.Kill(n)
|
|
rs.RemoveNode(n)
|
|
}
|
|
c.Rename = func(newName string) error {
|
|
if err := session.Rename(n, newName); err != nil {
|
|
return err
|
|
}
|
|
rs.RenameNode(n, newName)
|
|
return nil
|
|
}
|
|
return c
|
|
},
|
|
Remove: func() {
|
|
session.Kill(n)
|
|
rs.RemoveNode(n)
|
|
},
|
|
Rename: func(newName string) error {
|
|
if err := session.Rename(n, newName); err != nil {
|
|
return err
|
|
}
|
|
rs.RenameNode(n, newName)
|
|
return nil
|
|
},
|
|
})
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func readSessionEnv(ctx HandlerCtx) ([]byte, error) {
|
|
s := ctx.Session
|
|
var sb strings.Builder
|
|
fmt.Fprintf(&sb, "OLLIE_SESSION_ID=%s\n", s.ID())
|
|
for _, e := range os.Environ() {
|
|
if strings.HasPrefix(e, "OLLIE_") && !strings.HasPrefix(e, "OLLIE_SESSION_ID=") {
|
|
sb.WriteString(e)
|
|
sb.WriteByte('\n')
|
|
}
|
|
}
|
|
return []byte(sb.String()), nil
|
|
}
|
|
|
|
func readSessionPaused(ctx HandlerCtx) ([]byte, error) {
|
|
if ctx.Session.IsPaused() {
|
|
return []byte("true\n"), nil
|
|
}
|
|
return []byte("false\n"), nil
|
|
}
|
|
|
|
func readSessionConnected(ctx HandlerCtx) ([]byte, error) {
|
|
if ctx.Session.IsConnected() {
|
|
return []byte("true\n"), nil
|
|
}
|
|
return []byte("false\n"), nil
|
|
}
|
|
|
|
func requestSessionCtl(ctx HandlerCtx, data []byte) ([]byte, error) {
|
|
return rdwrDispatch(sessionCtlHandlers)(ctx, data)
|
|
}
|
|
|
|
var sessionCtlHandlers = map[string]rdwrHandler{
|
|
"kill": func(ctx HandlerCtx, _ []string) ([]byte, error) {
|
|
ctx.Remove()
|
|
return []byte("ok\n"), nil
|
|
},
|
|
".": func(ctx HandlerCtx, _ []string) ([]byte, error) {
|
|
ctx.Remove()
|
|
return []byte("ok\n"), nil
|
|
},
|
|
"save": func(ctx HandlerCtx, _ []string) ([]byte, error) {
|
|
if ctx.Session.Core != nil {
|
|
ctx.Session.Core.Save()
|
|
}
|
|
return []byte("ok\n"), nil
|
|
},
|
|
"invalidate": func(ctx HandlerCtx, _ []string) ([]byte, error) {
|
|
ctx.Session.InvalidateModelsCache()
|
|
return []byte("ok\n"), nil
|
|
},
|
|
"pause": func(ctx HandlerCtx, _ []string) ([]byte, error) {
|
|
if err := ctx.Session.Pause(); err != nil {
|
|
return nil, err
|
|
}
|
|
return []byte("ok\n"), nil
|
|
},
|
|
"resume": func(ctx HandlerCtx, _ []string) ([]byte, error) {
|
|
if err := ctx.Session.Resume(); err != nil {
|
|
return nil, err
|
|
}
|
|
return []byte("ok\n"), nil
|
|
},
|
|
}
|
|
|
|
func readSessionName(ctx HandlerCtx) ([]byte, error) {
|
|
return []byte(ctx.Session.Name() + "\n"), nil
|
|
}
|
|
|
|
func writeSessionName(ctx HandlerCtx, data []byte) error {
|
|
newName := strings.TrimSpace(string(data))
|
|
if newName == "" {
|
|
return nil
|
|
}
|
|
oldName := ctx.Session.Name()
|
|
if newName != oldName {
|
|
return ctx.Rename(newName)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func readSessionID(ctx HandlerCtx) ([]byte, error) {
|
|
return []byte(ctx.Session.ID() + "\n"), nil
|
|
}
|
|
|
|
func readSessionBypass(ctx HandlerCtx) ([]byte, error) {
|
|
if ctx.Bypass == nil {
|
|
return nil, fmt.Errorf("bypass broker not available")
|
|
}
|
|
p := ctx.Bypass.SessionPolicy(ctx.Session.ID())
|
|
return p.Marshal()
|
|
}
|
|
|
|
func writeSessionBypass(ctx HandlerCtx, data []byte) error {
|
|
if ctx.Bypass == nil {
|
|
return fmt.Errorf("bypass broker not available")
|
|
}
|
|
var p bypass.Policy
|
|
if err := bypass.ParsePolicy(data, &p); err != nil {
|
|
return err
|
|
}
|
|
ctx.Bypass.SetSessionPolicy(ctx.Session.ID(), p)
|
|
return nil
|
|
}
|