mirror of
https://shylinux.com/x/ContextOS
synced 2025-04-26 09:14:06 +08:00
412 lines
12 KiB
Go
412 lines
12 KiB
Go
package ssh // {{{
|
|
// }}}
|
|
import ( // {{{
|
|
"contexts"
|
|
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// }}}
|
|
|
|
type SSH struct {
|
|
nfs *ctx.Context
|
|
peer map[string]*ctx.Message
|
|
|
|
*ctx.Context
|
|
}
|
|
|
|
func (ssh *SSH) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{
|
|
c.Caches = map[string]*ctx.Cache{
|
|
"hostname": &ctx.Cache{Name: "hostname", Value: "com", Help: "主机数量"},
|
|
}
|
|
c.Configs = map[string]*ctx.Config{}
|
|
|
|
s := new(SSH)
|
|
s.Context = c
|
|
return s
|
|
}
|
|
|
|
// }}}
|
|
func (ssh *SSH) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
|
|
ssh.Caches["hostname"] = &ctx.Cache{Name: "hostname", Value: "", Help: "主机数量"}
|
|
if ssh.Context == Index {
|
|
Pulse = m
|
|
}
|
|
return ssh
|
|
}
|
|
|
|
// }}}
|
|
func (ssh *SSH) Start(m *ctx.Message, arg ...string) bool { // {{{
|
|
ssh.nfs = m.Source()
|
|
m.Cap("stream", m.Source().Name)
|
|
return false
|
|
}
|
|
|
|
// }}}
|
|
func (ssh *SSH) Close(m *ctx.Message, arg ...string) bool { // {{{
|
|
return false
|
|
switch ssh.Context {
|
|
case m.Target():
|
|
case m.Source():
|
|
}
|
|
if m.Target() == Index {
|
|
go func() {
|
|
m.Target().Begin(m)
|
|
m.Sess("nfs", "nfs")
|
|
for !m.Caps("stream") {
|
|
time.Sleep(time.Second * time.Duration(m.Confi("interval")))
|
|
go ssh.Message().Spawn(m.Target()).Copy(ssh.Message(), "detail").Cmd()
|
|
time.Sleep(time.Second * time.Duration(m.Confi("interval")))
|
|
}
|
|
}()
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// }}}
|
|
|
|
func Done(m *ctx.Message, lock chan bool) { // {{{
|
|
m.Log("lock", "done before %v", m.Meta["detail"])
|
|
if m.Options("stdio") {
|
|
lock <- true
|
|
}
|
|
m.Log("lock", "done after %v", m.Meta["detail"])
|
|
}
|
|
|
|
// }}}
|
|
func Wait(m *ctx.Message, lock chan bool) { // {{{
|
|
m.Log("lock", "wait before %v", m.Meta["detail"])
|
|
if m.Options("stdio") {
|
|
<-lock
|
|
}
|
|
m.Log("lock", "wait after %v", m.Meta["detail"])
|
|
}
|
|
|
|
// }}}
|
|
|
|
var Pulse *ctx.Message
|
|
var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
|
|
Caches: map[string]*ctx.Cache{
|
|
"nhost": &ctx.Cache{Name: "主机数量", Value: "0", Help: "主机数量"},
|
|
"route": &ctx.Cache{Name: "route", Value: "com", Help: "主机数量"},
|
|
"count": &ctx.Cache{Name: "count", Value: "3", Help: "主机数量"},
|
|
"share": &ctx.Cache{Name: "share", Value: "root", Help: "主机数量"},
|
|
"level": &ctx.Cache{Name: "level", Value: "root", Help: "主机数量"},
|
|
|
|
"domain": &ctx.Cache{Name: "domain", Value: "com", Help: "主机数量"},
|
|
},
|
|
Configs: map[string]*ctx.Config{
|
|
"interval": &ctx.Config{Name: "interval", Value: "3", Help: "主机数量"},
|
|
"hostname": &ctx.Config{Name: "hostname", Value: "com", Help: "主机数量"},
|
|
"domain.json": &ctx.Config{Name: "domain.json", Value: "var/domain.json", Help: "主机数量"},
|
|
"domain.png": &ctx.Config{Name: "domain.png", Value: "var/domain.png", Help: "主机数量"},
|
|
|
|
"mdb": &ctx.Config{Name: "mdb", Value: "mdb.chat", Help: "主机数量"},
|
|
"uid": &ctx.Config{Name: "uid", Value: "", Help: "主机数量"},
|
|
|
|
"type": &ctx.Config{Name: "type", Value: "terminal", Help: "主机数量"},
|
|
"kind": &ctx.Config{Name: "kind", Value: "terminal", Help: "主机数量"},
|
|
"name": &ctx.Config{Name: "name", Value: "vps", Help: "主机数量"},
|
|
"mark": &ctx.Config{Name: "mark", Value: "com", Help: "主机数量"},
|
|
},
|
|
Commands: map[string]*ctx.Command{
|
|
"listen": &ctx.Command{Name: "listen address protocol", Help: "监听连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
if _, ok := m.Target().Server.(*SSH); m.Assert(ok) { // {{{
|
|
m.Sess("nfs").Call(func(sub *ctx.Message) *ctx.Message {
|
|
sub.Start(fmt.Sprintf("host%d", Pulse.Capi("nhost", 1)), "远程主机")
|
|
return sub
|
|
}, m.Meta["detail"])
|
|
m.Spawn(m.Target()).Cmd("save")
|
|
}
|
|
// }}}
|
|
}},
|
|
"dial": &ctx.Command{Name: "dial address protocol", Help: "建立连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
if _, ok := m.Target().Server.(*SSH); m.Assert(ok) { // {{{
|
|
m.Sess("nfs").CallBack(true, func(sub *ctx.Message) *ctx.Message {
|
|
sub.Target().Start(sub)
|
|
sub.Spawn().Cmd("pwd", m.Conf("hostname"))
|
|
return sub
|
|
}, m.Meta["detail"])
|
|
}
|
|
// }}}
|
|
}},
|
|
"send": &ctx.Command{Name: "send [domain str] cmd arg...", Help: "远程执行",
|
|
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
if ssh, ok := m.Target().Server.(*SSH); m.Assert(ok) { // {{{
|
|
domain := ""
|
|
if len(arg) > 1 && arg[0] == "domain" {
|
|
domain, arg = arg[1], arg[2:]
|
|
domain = strings.TrimPrefix(strings.TrimPrefix(domain, m.Cap("domain")), ".")
|
|
}
|
|
|
|
if domain != "" {
|
|
domain_miss := true
|
|
host := strings.SplitN(domain, ".", 2)
|
|
m.Travel(func(m *ctx.Message, i int) bool {
|
|
if i > 0 {
|
|
if m.Cap("hostname") == host[0] {
|
|
ssh, ok := m.Target().Server.(*SSH)
|
|
m.Assert(ok)
|
|
|
|
msg := m.Spawn(ssh.Message().Source()).Copy(m, "option")
|
|
if len(host) > 1 {
|
|
msg.Options("downflow", true)
|
|
msg.Detail("send", "domain", host[1], arg)
|
|
} else {
|
|
msg.Detail(arg)
|
|
}
|
|
|
|
if ssh.Message().Back(msg); !msg.Appends("domain_miss") {
|
|
m.Copy(msg, "result").Copy(msg, "append")
|
|
domain_miss = false
|
|
return false
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
return true
|
|
}, c)
|
|
|
|
if domain_miss && !m.Options("downflow") && m.Cap("domain") != m.Conf("domain") {
|
|
ssh, ok := c.Server.(*SSH)
|
|
m.Assert(ok)
|
|
|
|
msg := m.Spawn(ssh.Message().Source()).Copy(m, "option")
|
|
msg.Detail("send", "domain", domain, arg)
|
|
|
|
if ssh.Message().Back(msg); !msg.Appends("domain_miss") {
|
|
m.Copy(msg, "result").Copy(msg, "append")
|
|
domain_miss = false
|
|
}
|
|
}
|
|
|
|
m.Appends("domain_miss", domain_miss)
|
|
return
|
|
}
|
|
|
|
if m.Options("send_code") || m.Cap("status") != "start" {
|
|
msg := m.Spawn().Cmd(arg)
|
|
m.Copy(msg, "result").Copy(msg, "append")
|
|
} else {
|
|
msg := m.Spawn(ssh.Message().Source())
|
|
msg.Copy(m, "option").Detail(arg)
|
|
ssh.Message().Back(msg)
|
|
m.Copy(msg, "result").Copy(msg, "append")
|
|
}
|
|
return
|
|
} // }}}
|
|
}},
|
|
"pwd": &ctx.Command{Name: "pwd", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
if len(arg) == 0 { // {{{
|
|
if m.Target() == c {
|
|
m.Echo(m.Cap("domain"))
|
|
} else {
|
|
m.Echo("%s.%s", m.Cap("domain"), m.Cap("hostname"))
|
|
}
|
|
return
|
|
}
|
|
|
|
if m.Target() == c {
|
|
msg := m.Spawn().Cmd("send", "pwd", arg[0])
|
|
m.Copy(msg, "result").Copy(msg, "append")
|
|
m.Cap("domain", msg.Result(0))
|
|
} else if m.Options("send_code") {
|
|
hostname := arg[0]
|
|
m.Travel(func(m *ctx.Message, line int) bool {
|
|
if hostname == m.Cap("hostname") {
|
|
hostname += m.Cap("nhost")
|
|
return false
|
|
}
|
|
return true
|
|
}, c)
|
|
m.Echo("%s.%s", m.Cap("domain"), m.Cap("hostname", hostname))
|
|
} // }}}
|
|
}},
|
|
"hello": &ctx.Command{Name: "hello request", Help: "加密请求", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
aaa := m.Target().Message().Sess("aaa", false) // {{{
|
|
for _, k := range m.Meta["seal"] {
|
|
for i, v := range m.Meta[k] {
|
|
m.Meta[k][i] = m.Spawn(aaa).Cmd("deal", v).Result(0)
|
|
}
|
|
}
|
|
for _, k := range m.Meta["encrypt"] {
|
|
for i, v := range m.Meta[k] {
|
|
m.Meta[k][i] = m.Spawn(aaa).Cmd("decrypt", v).Result(0)
|
|
}
|
|
}
|
|
|
|
if len(arg) == 0 {
|
|
if !m.Has("mi") {
|
|
cert := aaa.Spawn().Cmd("certificate")
|
|
m.Echo(cert.Result(0))
|
|
} else {
|
|
msg := m.Sess("aaa").Cmd("login", m.Option("mi"), m.Option("mi"))
|
|
m.Echo(msg.Result(0))
|
|
msg.Sess("aaa").Cmd("newcipher", m.Option("mi"))
|
|
}
|
|
return
|
|
}
|
|
|
|
msg := m.Spawn().Copy(m, "option").Cmd(arg)
|
|
m.Copy(msg, "result").Copy(msg, "append")
|
|
// }}}
|
|
}},
|
|
"shake": &ctx.Command{
|
|
Name: "shake [domain host] cmd... [seal option...][encrypt option...]",
|
|
Help: "加密通信",
|
|
Form: map[string]int{"seal": -1, "encrypt": -1},
|
|
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
if ssh, ok := m.Target().Server.(*SSH); m.Assert(ok) { // {{{
|
|
if len(arg) == 0 {
|
|
for k, v := range ssh.peer {
|
|
m.Echo("%s: %s\n", k, v.Cap("stream"))
|
|
}
|
|
return
|
|
}
|
|
|
|
peer := "peer"
|
|
args := []string{}
|
|
if len(arg) > 1 && arg[0] == "domain" {
|
|
args = append(args, "domain", arg[1])
|
|
peer, arg = arg[1], arg[2:]
|
|
}
|
|
if ssh.peer == nil {
|
|
ssh.peer = map[string]*ctx.Message{}
|
|
}
|
|
user, ok := ssh.peer[peer]
|
|
if !ok {
|
|
user = m.Sess("aaa").Cmd("login", "cert", m.Spawn().Cmd("send", args, "hello"), peer)
|
|
ssh.peer[peer] = user
|
|
mi := user.Cap("sessid")
|
|
|
|
remote := m.Spawn().Add("option", mi, m.Spawn(user).Cmd("seal", mi)).Add("option", "seal", mi).Cmd("send", args, "hello")
|
|
m.Spawn(user).Cmd("newcipher", mi)
|
|
user.Cap("remote", "remote", remote.Result(0), "远程会话")
|
|
user.Cap("remote_mi", "remote_mi", mi, "远程密钥")
|
|
}
|
|
|
|
msg := m.Spawn(ssh.Message().Source()).Copy(m, "option")
|
|
msg.Option("hello", "world")
|
|
msg.Option("world", "hello")
|
|
for _, k := range msg.Meta["seal"] {
|
|
for i, v := range msg.Meta[k] {
|
|
msg.Meta[k][i] = msg.Spawn(user).Cmd("seal", v).Result(0)
|
|
}
|
|
}
|
|
for _, k := range msg.Meta["encrypt"] {
|
|
for i, v := range msg.Meta[k] {
|
|
msg.Meta[k][i] = msg.Spawn(user).Cmd("encrypt", v).Result(0)
|
|
}
|
|
}
|
|
msg.Detail("send", args, "hello", arg)
|
|
ssh.Message().Back(msg)
|
|
m.Copy(msg, "result").Copy(msg, "append")
|
|
} // }}}
|
|
}},
|
|
"close": &ctx.Command{Name: "close", Help: "连接断开", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
m.Target().Close(m)
|
|
}},
|
|
"list": &ctx.Command{Name: "list", Help: "连接断开", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
domain := m.Cap("domain")
|
|
m.Travel(func(m *ctx.Message, i int) bool {
|
|
if m.Confs("domains") {
|
|
m.Echo("%s: %s.%s\n", m.Target().Name, domain, m.Conf("domains"))
|
|
}
|
|
return true
|
|
}, c)
|
|
}},
|
|
"save": &ctx.Command{Name: "save", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
json := m.Sess("nfs") // {{{
|
|
json.Put("option", "data", map[string]string{"domain": m.Cap("domain")})
|
|
json.Cmd("json", m.Conf("domain.json"))
|
|
m.Sess("nfs").Cmd("genqr", m.Conf("domain.png"), json.Result(0))
|
|
// }}}
|
|
}},
|
|
"who": &ctx.Command{Name: "who", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
|
aaa := m.Sess("aaa") // {{{
|
|
if aaa != nil {
|
|
m.Echo(aaa.Cap("group"))
|
|
}
|
|
// }}}
|
|
}},
|
|
"good": &ctx.Command{Name: "good context|command|config|cache args", Help: "设备注册", Hand: func(m *ctx.Message, c *ctx.Context, cmd string, arg ...string) {
|
|
if len(arg) == 0 { // {{{
|
|
m.Append("share", m.Cap("share"))
|
|
m.Append("level", m.Cap("level"))
|
|
m.Append("type", m.Conf("type"))
|
|
m.Append("value", m.Cap("domain"))
|
|
m.Append("kind", m.Conf("kind"))
|
|
m.Append("name", m.Cap("domain"))
|
|
m.Append("mark", m.Conf("mark"))
|
|
m.Append("count", m.Cap("count"))
|
|
m.Back(m)
|
|
return
|
|
}
|
|
cmds := m.Option("cmds")
|
|
|
|
if arg[0] == "context" {
|
|
if len(arg) > 1 {
|
|
cmds = arg[1]
|
|
}
|
|
|
|
m.Travel(func(msg *ctx.Message, i int) bool {
|
|
current := msg.Target()
|
|
if _, ok := current.Index[cmds]; ok {
|
|
|
|
} else if cmds != "" && cmds != "root" {
|
|
return true
|
|
}
|
|
|
|
m.Add("append", "name", current.Name)
|
|
m.Add("append", "help", current.Help)
|
|
return true
|
|
}, ctx.Index)
|
|
return
|
|
}
|
|
|
|
if len(arg) > 2 {
|
|
cmds = arg[2]
|
|
}
|
|
current := m.Sess(arg[1], arg[1], "search").Target()
|
|
if x, ok := current.Index[cmds]; ok {
|
|
current = x
|
|
} else if cmds != "" && cmds != "root" {
|
|
return
|
|
}
|
|
|
|
switch arg[0] {
|
|
case "command":
|
|
|
|
for k, x := range current.Commands {
|
|
m.Add("append", "key", k)
|
|
m.Add("append", "name", x.Name)
|
|
m.Add("append", "help", x.Help)
|
|
}
|
|
case "config":
|
|
for k, x := range current.Configs {
|
|
m.Add("append", "key", k)
|
|
m.Add("append", "name", x.Name)
|
|
m.Add("append", "value", x.Value)
|
|
m.Add("append", "help", x.Help)
|
|
}
|
|
case "cache":
|
|
for k, x := range current.Caches {
|
|
m.Add("append", "key", k)
|
|
m.Add("append", "name", x.Name)
|
|
m.Add("append", "value", x.Value)
|
|
m.Add("append", "help", x.Help)
|
|
}
|
|
} // }}}
|
|
}},
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
ssh := &SSH{}
|
|
ssh.Context = Index
|
|
ctx.Index.Register(Index, ssh)
|
|
}
|