From 4d5f45a1a7d398235157613e7f74843d0baa3eae Mon Sep 17 00:00:00 2001 From: shaoying Date: Sun, 14 Oct 2018 09:50:18 +0800 Subject: [PATCH] mac opt aaa --- etc/init.shy | 1 - src/contexts/aaa/aaa.go | 1090 +++++++++++++++------------------------ src/contexts/ctx.go | 17 +- src/contexts/ssh/ssh.go | 318 +++--------- 4 files changed, 504 insertions(+), 922 deletions(-) diff --git a/etc/init.shy b/etc/init.shy index c42427b7..8a8bc784 100644 --- a/etc/init.shy +++ b/etc/init.shy @@ -1,4 +1,3 @@ -login root root ~aaa # login load var/login.txt ~file1 diff --git a/src/contexts/aaa/aaa.go b/src/contexts/aaa/aaa.go index c72bc8fa..dd6c212d 100644 --- a/src/contexts/aaa/aaa.go +++ b/src/contexts/aaa/aaa.go @@ -1,762 +1,490 @@ -package aaa // {{{ -// }}} -import ( // {{{ +package aaa + +import ( "contexts" - "crypto/sha1" - "math/big" - "net/http" - "sort" - - "encoding/json" - - "bufio" - "io" - "io/ioutil" - "os" - "crypto" - "crypto/md5" - "strings" - "crypto/aes" "crypto/cipher" + "crypto/md5" crand "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/base64" - "encoding/pem" - "encoding/hex" - "math/rand" - + "encoding/pem" "fmt" + "io/ioutil" + "math/big" + "math/rand" "strconv" "time" ) -// }}} - type AAA struct { + certificate *x509.Certificate public *rsa.PublicKey private *rsa.PrivateKey - certificate *x509.Certificate encrypt cipher.BlockMode decrypt cipher.BlockMode - lark chan *ctx.Message - sessions map[string]*ctx.Message *ctx.Context } -func (aaa *AAA) Session(meta string) string { // {{{ +func (aaa *AAA) Session(meta string) string { bs := md5.Sum([]byte(fmt.Sprintln("%d%d%s", time.Now().Unix(), rand.Int(), meta))) return hex.EncodeToString(bs[:]) } - -// }}} -func (aaa *AAA) Password(pwd string) string { // {{{ - bs := md5.Sum([]byte(fmt.Sprintln("用户密码:%s", pwd))) +func (aaa *AAA) Password(pwd string) string { + bs := md5.Sum([]byte(fmt.Sprintln("password:%s", pwd))) return hex.EncodeToString(bs[:]) } +func (aaa *AAA) Input(stream string) []byte { + if b, e := ioutil.ReadFile(stream); e == nil { + return b + } + return []byte(stream) +} +func (aaa *AAA) Decode(stream string) []byte { + buf, e := ioutil.ReadFile(stream) + if e != nil { + buf = []byte(stream) + } + block, _ := pem.Decode(buf) + return block.Bytes +} -// }}} - -func (aaa *AAA) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{ +func (aaa *AAA) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { + now := time.Now().Unix() c.Caches = map[string]*ctx.Cache{ - "time": &ctx.Cache{Name: "time", Value: fmt.Sprintf("%d", time.Now().Unix()), Help: "登录时间", Hand: func(m *ctx.Message, x *ctx.Cache, arg ...string) string { - if len(arg) > 0 { // {{{ + "method": &ctx.Cache{Name: "method", Value: arg[0], Help: "登录方式"}, + "sessid": &ctx.Cache{Name: "sessid", Value: aaa.Session(arg[1]), Help: "会话令牌"}, + "expire_time": &ctx.Cache{Name: "expire_time", Value: fmt.Sprintf("%d", int64(m.Confi("expire"))+now), Help: "会话超时"}, + "login_time": &ctx.Cache{Name: "login_time", Value: fmt.Sprintf("%d", now), Help: "登录时间", Hand: func(m *ctx.Message, x *ctx.Cache, arg ...string) string { + if len(arg) > 0 { return arg[0] } n, e := strconv.Atoi(x.Value) m.Assert(e) return time.Unix(int64(n), 0).Format("15:03:04") - // }}} }}, - "username": &ctx.Cache{Name: "username", Value: arg[0], Help: "用户名"}, - "password": &ctx.Cache{Name: "password", Value: arg[1], Help: "用户密码,加密存储"}, - "sessid": &ctx.Cache{Name: "sessid", Value: arg[2], Help: "会话令牌"}, - "expire": &ctx.Cache{Name: "expire", Value: fmt.Sprintf("%d", int64(m.Confi("expire"))+time.Now().Unix()), Help: "会话超时"}, - } - c.Configs = map[string]*ctx.Config{ - "lark": &ctx.Config{Name: "lark", Value: map[string]interface{}{}, Help: "用户密码,加密存储"}, } + c.Configs = map[string]*ctx.Config{} s := new(AAA) s.Context = c - s.sessions = aaa.sessions - if m.Has("cert") { - s.certificate = m.Optionv("certificate").(*x509.Certificate) - s.public = s.certificate.PublicKey.(*rsa.PublicKey) - } - if m.Has("pub") { - s.public = m.Optionv("public").(*rsa.PublicKey) - } - if m.Has("key") { - s.private = m.Optionv("private").(*rsa.PrivateKey) - s.public = &s.private.PublicKey - - } - return s } - -// }}} -func (aaa *AAA) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ +func (aaa *AAA) Begin(m *ctx.Message, arg ...string) ctx.Server { return aaa } +func (aaa *AAA) Start(m *ctx.Message, arg ...string) bool { + stream := arg[1] + switch arg[0] { + case "cert": + cert, e := x509.ParseCertificate(aaa.Decode(stream)) + m.Assert(e) -// }}} -func (aaa *AAA) Start(m *ctx.Message, arg ...string) bool { // {{{ - aaa.sessions[m.Cap("sessid")] = m - m.Log("info", "%d login %s", m.Capi("nuser", 1), m.Cap("stream", arg[0])) - if arg[0] == "lark" { - aaa.lark = make(chan *ctx.Message) + aaa.certificate = cert + aaa.public = cert.PublicKey.(*rsa.PublicKey) + stream = aaa.Password(stream) + case "pub": + public, e := x509.ParsePKIXPublicKey(aaa.Decode(stream)) + m.Assert(e) - for { - msg := <-aaa.lark - from := msg.Option("username") - m.Log("lark", "%v", msg.Meta["detail"]) - m.Travel(func(m *ctx.Message, n int) bool { - if m.Cap("username") == msg.Detail(1) { - m.Confv("lark", strings.Join([]string{from, "-2"}, "."), - map[string]interface{}{"time": msg.Time(), "type": "recv", "text": msg.Detail(2)}) - } - return true - }, aaa.Context) - } - return true + aaa.public = public.(*rsa.PublicKey) + stream = aaa.Password(stream) + case "key": + private, e := x509.ParsePKCS1PrivateKey(aaa.Decode(stream)) + m.Assert(e) + + aaa.private = private + aaa.public = &aaa.private.PublicKey + stream = aaa.Password(stream) } + m.Log("info", "%d login %s", m.Capi("nuser"), m.Cap("stream", stream)) + return false +} +func (aaa *AAA) Close(m *ctx.Message, arg ...string) bool { return false } -// }}} -func (aaa *AAA) Close(m *ctx.Message, arg ...string) bool { // {{{ - switch aaa.Context { - case m.Target(): - if int64(m.Capi("expire")) > time.Now().Unix() { - return false - } - delete(aaa.sessions, m.Cap("sessid")) - m.Log("info", "%d logout %s", m.Capi("nuser", -1), m.Cap("username")) - case m.Source(): - } - return true -} - -// }}} - -var Pulse *ctx.Message var Index = &ctx.Context{Name: "aaa", Help: "认证中心", Caches: map[string]*ctx.Cache{ "nuser": &ctx.Cache{Name: "nuser", Value: "0", Help: "用户数量"}, - - "access_expire": &ctx.Cache{Name: "会话超时", Value: "0", Help: "会话超时"}, - "access_token": &ctx.Cache{Name: "会话令牌", Value: "0", Help: "会话令牌", Hand: func(m *ctx.Message, x *ctx.Cache, arg ...string) string { - if len(arg) > 0 { // {{{ - return arg[0] - } - - if m.Capi("access_expire") < int(time.Now().Unix()) { - var data struct { - Errcode int64 - Errmsg string - Access_token string - Expires_in int64 - } - res, e := http.Get(fmt.Sprintf(m.Conf("wx_api")+m.Conf("access_route"), m.Conf("appid"), m.Conf("appmm"))) - m.Assert(e) - m.Assert(json.NewDecoder(res.Body).Decode(&data)) - m.Cap("access_expire", fmt.Sprintf("%d", time.Now().Unix()+data.Expires_in)) - x.Value = data.Access_token - m.Log("info", "access_token: %s(%s)", m.Cap("access_token"), m.Cap("access_expire")) - m.Cap("stream", m.Conf("appid")) - } - return x.Value // }}} - }}, }, Configs: map[string]*ctx.Config{ - "wx_api": &ctx.Config{Name: "微信接口", Value: "https://api.weixin.qq.com/cgi-bin/", Help: "微信登录"}, - "access_route": &ctx.Config{Name: "微信登录", Value: "token?grant_type=client_credential&appid=%s&secret=%s", Help: "微信登录"}, - "appid": &ctx.Config{Name: "微信帐号", Value: "", Help: "微信帐号"}, - "appmm": &ctx.Config{Name: "微信密码", Value: "", Help: "微信密码"}, - "token": &ctx.Config{Name: "微信令牌", Value: "", Help: "微信密码"}, - - "rootname": &ctx.Config{Name: "rootname", Value: "root", Help: "根用户名"}, - "expire": &ctx.Config{Name: "expire(s)", Value: "7200", Help: "会话超时"}, - "pub": &ctx.Config{Name: "pub", Value: "etc/pub.pem", Help: "公钥文件"}, - "key": &ctx.Config{Name: "key", Value: "etc/key.pem", Help: "私钥文件"}, - - "aaa_name": &ctx.Config{Name: "aaa_name", Value: "user", Help: "默认模块名", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string { - if len(arg) > 0 { // {{{ - return arg[0] - } - return fmt.Sprintf("%s%d", x.Value, m.Capi("nuser", 1)) - // }}} - }}, - "aaa_help": &ctx.Config{Name: "aaa_help", Value: "登录用户", Help: "默认模块帮助"}, + "expire": &ctx.Config{Name: "expire(s)", Value: "7200", Help: "会话超时"}, + "cert": &ctx.Config{Name: "cert", Value: "etc/pem/cert.pem", Help: "证书文件"}, + "pub": &ctx.Config{Name: "pub", Value: "etc/pem/pub.pem", Help: "公钥文件"}, + "key": &ctx.Config{Name: "key", Value: "etc/pem/key.pem", Help: "私钥文件"}, }, Commands: map[string]*ctx.Command{ "login": &ctx.Command{ - Name: "login [sessid]|[username password]|[cert certfile]|[pub pubfile]|[key keyfile]|[ip ipstr]|[load|save filename]", - Help: "用户登录, sessid: 会话ID, username: 用户名, password: 密码, load: 加载用户信息, save: 保存用户信息, filename: 文件名", - Form: map[string]int{"cert": 1, "pub": 1, "key": 1, "ip": 1}, + Name: "login [sessid]|[username password]", + Form: map[string]int{"ip": 1, "openid": 1, "cert": 1, "pub": 1, "key": 1, "load": 1, "save": 1}, + Help: []string{"会话管理", "sessid: 令牌", "username: 账号", "password: 密码", + "ip: 主机地址", "openid: 微信登录", "cert: 证书", "pub: 公钥", "key: 私钥", "load: 加载会话", "save: 保存会话"}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if aaa, ok := c.Server.(*AAA); m.Assert(ok) { // {{{ - stream := "" - // method := "" - // username := "" - if len(arg) > 0 { - switch arg[0] { - case "openid": - // method = arg[0] - // username = arg[1] - stream = arg[1] + if aaa, ok := c.Server.(*AAA); m.Assert(ok) { + method := "" + for _, v := range []string{"ip", "openid", "cert", "pub", "key"} { + if m.Has(v) { + method = v } } + if method != "" { + m.Travel(func(m *ctx.Message, n int) bool { + if n > 0 && m.Cap("method") == method { + switch method { + case "ip", "openid": + if m.Cap("stream") == m.Option(method) { + m.Cap("expire_time", fmt.Sprintf("%d", time.Now().Unix()+int64(m.Confi("expire")))) + m.Echo(m.Cap("sessid")) + return false + } + case "cert", "pub", "key": + if m.Cap("stream") == aaa.Password(m.Option(method)) { + m.Cap("expire_time", fmt.Sprintf("%d", time.Now().Unix()+int64(m.Confi("expire")))) + m.Echo(m.Cap("sessid")) + return false + } + } + } + return true + }, c) + if m.Results(0) { + return + } - if m.Has("ip") { - stream = m.Option("ip") - } - if m.Has("openid") { - stream = m.Option("openid") - } - if m.Has("pub") { - stream = m.Option("pub") - buf, e := ioutil.ReadFile(m.Option("pub")) - if e != nil { - buf = []byte(m.Option("pub")) - e = nil - stream = "RSA PUBLIC KEY" - } - block, _ := pem.Decode(buf) - public, e := x509.ParsePKIXPublicKey(block.Bytes) - m.Assert(e) - m.Optionv("public", public) - } - if m.Options("cert") { - stream = m.Option("cert") - buf, e := ioutil.ReadFile(m.Option("cert")) - if e != nil { - buf = []byte(m.Option("cert")) - e = nil - stream = "CERTIFICATE" - } - block, _ := pem.Decode(buf) - cert, e := x509.ParseCertificate(block.Bytes) - m.Assert(e) - m.Optionv("certificate", cert) - } - if m.Has("key") { - stream = m.Option("key") - buf, e := ioutil.ReadFile(m.Option("key")) - if e != nil { - buf = []byte(m.Option("key")) - e = nil - stream = "RSA PRIVATE KEY" - } - block, buf := pem.Decode(buf) - private, e := x509.ParsePKCS1PrivateKey(block.Bytes) - m.Assert(e) - m.Optionv("private", private) - } - - if stream != "" { - m.Start(arg[0], m.Confx("aaa_help"), arg[0], "", aaa.Session(arg[0])) - m.Cap("stream", stream) + m.Start(fmt.Sprintf("user%d", m.Capi("nuser", 1)), "用户登录", method, m.Option(method)) + m.Echo(m.Cap("sessid")) return } switch len(arg) { - case 0: - m.Travel(func(m *ctx.Message, i int) bool { - if i > 0 { - m.Echo("%s: %s\n", m.Cap("username"), m.Cap("sessid")) - } - return true - }) - case 1: - if msg, ok := aaa.sessions[arg[0]]; ok { - if int64(msg.Capi("expire")) > time.Now().Unix() { - m.Echo(msg.Cap("username")) - m.Copy(msg, "target") - m.Appendv("aaa", msg) - m.Sess("aaa", msg) - } else { - delete(aaa.sessions, arg[0]) - msg.Target().Close(msg) - m.Capi("nuser", -1) - } - } - default: - switch arg[0] { - case "load": - if f, e := os.Open(arg[1]); m.Assert(e) { - for bio := bufio.NewScanner(f); bio.Scan(); { - word := strings.SplitN(bio.Text(), ":", 3) - msg := m.Spawn() - msg.Start(word[0], "用户", word[0], word[1], word[2]) - msg.Spawn().Cmd("config", "load", fmt.Sprintf("var/%s.json", word[0]), "lark") - } - } - case "save": - if f, e := os.Create(arg[1]); m.Assert(e) { - m.Travel(func(m *ctx.Message, i int) bool { - if i > 0 && m.Cap("username") != "root" { - f.WriteString(fmt.Sprintf("%s:%s:%s\n", m.Cap("username"), m.Cap("password"), m.Cap("sessid"))) - m.Spawn().Cmd("config", "save", fmt.Sprintf("var/%s.json", m.Cap("username")), "lark") - } - return true - }) - } - default: - find := false - m.Travel(func(m *ctx.Message, line int) bool { - if line > 0 && m.Cap("username") == arg[0] { - if m.Cap("password") == aaa.Password(arg[1]) { - m.Sess("aaa", m.Target()) - m.Echo(m.Cap("sessid")) - m.Appendv("aaa", m) - m.Sess("aaa", m) - } else { - m.Sess("aaa", c) - } - find = true - return false - } - return true - }, c) - - if !find { - m.Start(arg[0], m.Confx("aaa_help"), arg[0], aaa.Password(arg[1]), aaa.Session(arg[0])) - m.Cap("stream", arg[0]) + case 2: + m.Travel(func(m *ctx.Message, n int) bool { + if n > 0 && m.Cap("method") == "password" && m.Cap("stream") == arg[0] { + m.Assert(m.Cap("password") == aaa.Password(arg[1])) + m.Cap("expire_time", fmt.Sprintf("%d", time.Now().Unix()+int64(m.Confi("expire")))) m.Echo(m.Cap("sessid")) - m.Appendv("aaa", m) - m.Sess("aaa", m) + return false } - } - } - } // }}} - }}, - "certificate": &ctx.Command{Name: "certificate filename", Help: "散列", - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.certificate != nil { // {{{ - certificate := string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: aaa.certificate.Raw})) - if m.Echo(certificate); len(arg) > 0 { - m.Assert(ioutil.WriteFile(arg[0], []byte(certificate), 0666)) - } - } - // }}} - }}, - "public": &ctx.Command{Name: "public filename", Help: "散列", - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.public != nil { // {{{ - pub, e := x509.MarshalPKIXPublicKey(aaa.public) - m.Assert(e) - public := string(pem.EncodeToMemory(&pem.Block{Type: "RSA PUBLIC KEY", Bytes: pub})) - if m.Echo(public); len(arg) > 0 { - m.Assert(ioutil.WriteFile(arg[0], []byte(public), 0666)) - } - } - // }}} - }}, - "private": &ctx.Command{Name: "private filename", Help: "散列", - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.private != nil { // {{{ - private := string(pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(aaa.private)})) - if m.Echo(private); len(arg) > 0 { - m.Assert(ioutil.WriteFile(arg[0], []byte(private), 0666)) - } - } - // }}} - }}, - "sign": &ctx.Command{Name: "sign [file filename][content] [sign signfile]", Help: "散列", - Form: map[string]int{"file": 1, "sign": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.private != nil { // {{{ - var content []byte - if m.Has("file") { - b, e := ioutil.ReadFile(m.Option("file")) - m.Assert(e) - content = b - } else if len(arg) > 0 { - content = []byte(arg[0]) - } - - h := md5.Sum(content) - b, e := rsa.SignPKCS1v15(crand.Reader, aaa.private, crypto.MD5, h[:]) - m.Assert(e) - - res := base64.StdEncoding.EncodeToString(b) - if m.Echo(res); m.Has("sign") { - m.Assert(ioutil.WriteFile(m.Option("sign"), []byte(res), 0666)) - } - } - // }}} - }}, - "verify": &ctx.Command{Name: "verify [file filename][content] [sign signfile][signature]", Help: "散列", - Form: map[string]int{"file": 1, "sign": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.public != nil { // {{{ - var content []byte - if m.Has("file") { - b, e := ioutil.ReadFile(m.Option("file")) - m.Assert(e) - content = b - } else if len(arg) > 0 { - content, arg = []byte(arg[0]), arg[1:] - } - - var sign []byte - if m.Has("sign") { - b, e := ioutil.ReadFile(m.Option("sign")) - m.Assert(e) - sign = b - } else if len(arg) > 0 { - sign, arg = []byte(arg[0]), arg[1:] - } - - buf := make([]byte, 1024) - n, e := base64.StdEncoding.Decode(buf, sign) - m.Assert(e) - buf = buf[:n] - - h := md5.Sum(content) - m.Echo("%t", rsa.VerifyPKCS1v15(aaa.public, crypto.MD5, h[:], buf) == nil) - } - // }}} - }}, - "seal": &ctx.Command{Name: "seal [file filename][content] [seal sealfile]", Help: "散列", - Form: map[string]int{"file": 1, "seal": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.public != nil { // {{{ - var content []byte - if m.Has("file") { - b, e := ioutil.ReadFile(m.Option("file")) - m.Assert(e) - content = b - } else if len(arg) > 0 { - content = []byte(arg[0]) - } - - b, e := rsa.EncryptPKCS1v15(crand.Reader, aaa.public, content) - m.Assert(e) - - res := base64.StdEncoding.EncodeToString(b) - if m.Echo(res); m.Has("seal") { - m.Assert(ioutil.WriteFile(m.Option("seal"), []byte(res), 0666)) - } - } - // }}} - }}, - "deal": &ctx.Command{Name: "deal [file filename][content]", Help: "散列", - Form: map[string]int{"file": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.private != nil { // {{{ - var content []byte - if m.Has("file") { - b, e := ioutil.ReadFile(m.Option("file")) - m.Assert(e) - content = b - } else if len(arg) > 0 { - content, arg = []byte(arg[0]), arg[1:] - } - - buf := make([]byte, 1024) - n, e := base64.StdEncoding.Decode(buf, content) - m.Assert(e) - buf = buf[:n] - - b, e := rsa.DecryptPKCS1v15(crand.Reader, aaa.private, buf) - m.Assert(e) - m.Echo(string(b)) - } - - // }}} - }}, - "newcipher": &ctx.Command{Name: "newcipher", Help: "散列", - Form: map[string]int{"file": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) { // {{{ - salt := md5.Sum([]byte(arg[0])) - block, e := aes.NewCipher(salt[:]) - m.Assert(e) - aaa.encrypt = cipher.NewCBCEncrypter(block, salt[:]) - aaa.decrypt = cipher.NewCBCDecrypter(block, salt[:]) - } - // }}} - }}, - "encrypt": &ctx.Command{Name: "encrypt [file filename][content] [enfile]", Help: "散列", - Form: map[string]int{"file": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.encrypt != nil { // {{{ - var content []byte - if m.Has("file") { - b, e := ioutil.ReadFile(m.Option("file")) - m.Assert(e) - content = b - } else if len(arg) > 0 { - content, arg = []byte(arg[0]), arg[1:] - } - - bsize := aaa.encrypt.BlockSize() - size := (len(content) / bsize) * bsize - if len(content)%bsize != 0 { - size += bsize - } - buf := make([]byte, size) - for pos := 0; pos < len(content); pos += bsize { - end := pos + bsize - if end > len(content) { - end = len(content) - } - - b := make([]byte, bsize) - copy(b, content[pos:end]) - - aaa.encrypt.CryptBlocks(buf[pos:pos+bsize], b) - } - - res := base64.StdEncoding.EncodeToString(buf) - if m.Echo(res); len(arg) > 0 { - m.Assert(ioutil.WriteFile(arg[0], []byte(res), 0666)) - } - } - // }}} - }}, - "decrypt": &ctx.Command{Name: "decrypt [file filename][content] [defile]", Help: "散列", - Form: map[string]int{"file": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.decrypt != nil { // {{{ - var content []byte - if m.Has("file") { - b, e := ioutil.ReadFile(m.Option("file")) - m.Assert(e) - content = b - } else if len(arg) > 0 { - content, arg = []byte(arg[0]), arg[1:] - } - - buf := make([]byte, 1024) - n, e := base64.StdEncoding.Decode(buf, content) - m.Assert(e) - buf = buf[:n] - - res := make([]byte, n) - aaa.decrypt.CryptBlocks(res, buf) - - if m.Echo(string(res)); len(arg) > 0 { - m.Assert(ioutil.WriteFile(arg[0], res, 0666)) - } - } - // }}} - }}, - "md5": &ctx.Command{Name: "md5 [file filename][content]", Help: "散列", - Form: map[string]int{"file": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if m.Options("file") { // {{{ - f, e := os.Open(m.Option("file")) - m.Assert(e) - - h := md5.New() - io.Copy(h, f) - - m.Echo(hex.EncodeToString(h.Sum([]byte{})[:])) - } else if len(arg) > 0 { - h := md5.Sum([]byte(arg[0])) - m.Echo(hex.EncodeToString(h[:])) - } - // }}} - }}, - "rsa": &ctx.Command{Name: "rsa gen|encrypt|decrypt|sign|verify [keyfile filename][key str][mmfile filename][mm str][signfile filename][signs str][file filename] content", - Help: ` gen生成密钥, encrypt公钥加密, decrypt私钥解密, sgin私钥签名, verify公钥验签, - keyfile密钥文件, key密钥字符串,mm加密文件, mm加密字符串, signfile签名文件,signs签名字符串, - file数据文件,content数据内容. - 密钥: rsa gen keyfile key.pem - 加密: rsa encrypt keyfile pubkey.pem mmfile mm.txt hello - 解密: rsa decrypt keyfile key.pem mmfile mm.txt - 签名: rsa sign keyfile key.pem signfile sign.txt hello - 验签: rsa verify keyfile pubkey.pem signfile sign.txt hello`, - Form: map[string]int{"keyfile": 1, "key": 1, "mmfile": 1, "mm": 1, "signfile": 1, "signs": 1, "file": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if arg[0] == "gen" { // {{{ - keys, e := rsa.GenerateKey(crand.Reader, 1024) - m.Assert(e) - - private := string(pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(keys)})) - m.Append("private", private) - m.Echo(private) - - pub, e := x509.MarshalPKIXPublicKey(&keys.PublicKey) - m.Assert(e) - - public := string(pem.EncodeToMemory(&pem.Block{Type: "RSA PUBLIC KEY", Bytes: pub})) - m.Append("public", public) - m.Echo(public) - - template := x509.Certificate{SerialNumber: big.NewInt(1)} - cert, e := x509.CreateCertificate(crand.Reader, &template, &template, &keys.PublicKey, keys) - m.Assert(e) - - certificate := string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert})) - m.Append("certificate", certificate) - m.Echo(certificate) - - if m.Options("keyfile") { - ioutil.WriteFile(m.Option("keyfile"), []byte(private), 0666) - ioutil.WriteFile("pub"+m.Option("keyfile"), []byte(public), 0666) - ioutil.WriteFile("cert"+m.Option("keyfile"), []byte(certificate), 0666) - } - return - } - - keys := []byte(m.Option("key")) - if m.Options("keyfile") { - b, e := ioutil.ReadFile(m.Option("keyfile")) - m.Assert(e) - keys = b - } - - block, e := pem.Decode(keys) - m.Assert(e) - - if arg[0] == "decrypt" { - private, e := x509.ParsePKCS1PrivateKey(block.Bytes) - m.Assert(e) - - mm := []byte(m.Option("mm")) - if m.Options("mmfile") { - b, e := ioutil.ReadFile(m.Option("mmfile")) - m.Assert(e) - mm = b - } - - buf := make([]byte, 1024) - n, e := base64.StdEncoding.Decode(buf, mm) - m.Assert(e) - buf = buf[:n] - - b, e := rsa.DecryptPKCS1v15(crand.Reader, private, buf) - m.Assert(e) - - m.Echo(string(b)) - if m.Options("file") { - ioutil.WriteFile(m.Option("file"), b, 0666) - } - return - } - - var content []byte - if m.Options("file") { - b, e := ioutil.ReadFile(m.Option("file")) - m.Assert(e) - content = b - } else if len(arg) > 1 { - content = []byte(arg[1]) - } - - switch arg[0] { - case "encrypt": - public, e := x509.ParsePKIXPublicKey(block.Bytes) - m.Assert(e) - - b, e := rsa.EncryptPKCS1v15(crand.Reader, public.(*rsa.PublicKey), content) - m.Assert(e) - - res := base64.StdEncoding.EncodeToString(b) - m.Echo(res) - if m.Options("mmfile") { - ioutil.WriteFile(m.Option("mmfile"), []byte(res), 0666) - } - - case "sign": - private, e := x509.ParsePKCS1PrivateKey(block.Bytes) - m.Assert(e) - - h := md5.Sum(content) - b, e := rsa.SignPKCS1v15(crand.Reader, private, crypto.MD5, h[:]) - m.Assert(e) - - res := base64.StdEncoding.EncodeToString(b) - m.Echo(res) - - if m.Options("signfile") { - ioutil.WriteFile(m.Option("signfile"), []byte(res), 0666) - } - - case "verify": - public, e := x509.ParsePKIXPublicKey(block.Bytes) - m.Assert(e) - - sign := []byte(m.Option("sign")) - if m.Options("signfile") { - b, e := ioutil.ReadFile(m.Option("signfile")) - m.Assert(e) - sign = b - } - - buf := make([]byte, 1024) - n, e := base64.StdEncoding.Decode(buf, sign) - m.Assert(e) - buf = buf[:n] - - h := md5.Sum(content) - m.Echo("%t", rsa.VerifyPKCS1v15(public.(*rsa.PublicKey), crypto.MD5, h[:], buf) == nil) - } - // }}} - }}, - "lark": &ctx.Command{Name: "lark who message", Help: "散列", - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if m.Option("username") == "" { - m.Option("username", m.Sess("aaa", false).Cap("username")) - } - if aaa, ok := c.Server.(*AAA); m.Assert(ok) && aaa.lark != nil { // {{{ - m.Travel(func(m *ctx.Message, n int) bool { - if n == 0 || m.Cap("username") != m.Option("username") { return true + }, c) + if m.Results(0) { + return } - switch len(arg) { - case 0: - for k, v := range m.Confv("lark").(map[string]interface{}) { - for _, x := range v.([]interface{}) { - val := x.(map[string]interface{}) - m.Add("append", "friend", k) - m.Add("append", "time", val["time"]) - m.Add("append", "type", val["type"]) - if val["type"].(string) == "send" { - m.Add("append", "text", fmt.Sprintf("<< %v", val["text"])) - } else { - m.Add("append", "text", fmt.Sprintf(">> %v", val["text"])) - } + m.Start(fmt.Sprintf("user%d", m.Capi("nuser", 1)), "密码登录", "password", arg[0]) + m.Cap("password", "password", aaa.Password(arg[1]), "密码登录") + m.Echo(m.Cap("sessid")) + return + case 1: + m.Travel(func(m *ctx.Message, n int) bool { + if n > 0 && m.Cap("sessid") == arg[0] { + if int64(m.Capi("expire_time")) > time.Now().Unix() { + m.Echo(m.Cap("stream")) + } else { + m.Target().Close(m) } + return false } - case 1: - for _, v := range m.Confv("lark", arg[0]).([]interface{}) { - val := v.(map[string]interface{}) - m.Add("append", "time", val["time"]) - m.Add("append", "text", val["text"]) + return true + }, c) + case 0: + m.Travel(func(m *ctx.Message, n int) bool { + if n > 0 { + m.Add("append", "method", m.Cap("method")) + m.Add("append", "stream", m.Cap("stream")) } - case 2: - m.Confv("lark", strings.Join([]string{arg[0], "-2"}, "."), - map[string]interface{}{"time": m.Time(), "type": "send", "text": arg[1]}) - aaa.lark <- m - m.Echo("%s send done", m.Time()) - } - return false - }, c) + return true + }, c) + m.Table() + } } - // }}} }}, - "wx": &ctx.Command{Name: "wx check signature", Help: "微信", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - list := []string{m.Option("nonce"), m.Option("timestamp"), m.Conf("token")} - sort.Strings(list) - b := sha1.Sum([]byte(strings.Join(list, ""))) - - if m.Option("signature") == hex.EncodeToString(b[:]) { - m.Echo("ok") + "cert": &ctx.Command{Name: "cert [filename]", Help: "导出证书", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.certificate != nil { + certificate := string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: aaa.certificate.Raw})) + if m.Echo(certificate); len(arg) > 0 { + m.Assert(ioutil.WriteFile(arg[0], []byte(certificate), 0666)) + } } }}, + "pub": &ctx.Command{Name: "pub [filename]", Help: "导出公钥", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.public != nil { + pub, e := x509.MarshalPKIXPublicKey(aaa.public) + m.Assert(e) + public := string(pem.EncodeToMemory(&pem.Block{Type: "RSA PUBLIC KEY", Bytes: pub})) + if m.Echo(public); len(arg) > 0 { + m.Assert(ioutil.WriteFile(arg[0], []byte(public), 0666)) + } + } + }}, + "key": &ctx.Command{Name: "key [filename]", Help: "导出私钥", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.private != nil { + private := string(pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(aaa.private)})) + if m.Echo(private); len(arg) > 0 { + m.Assert(ioutil.WriteFile(arg[0], []byte(private), 0666)) + } + } + }}, + "sign": &ctx.Command{Name: "sign content [signfile]", Help: "数字签名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.private != nil { + h := md5.Sum(aaa.Input(arg[0])) + b, e := rsa.SignPKCS1v15(crand.Reader, aaa.private, crypto.MD5, h[:]) + m.Assert(e) + + res := base64.StdEncoding.EncodeToString(b) + if m.Echo(res); len(arg) > 1 { + m.Assert(ioutil.WriteFile(arg[1], []byte(res), 0666)) + } + } + }}, + "verify": &ctx.Command{Name: "verify content signature", Help: "数字验签", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.public != nil { + buf := make([]byte, 1024) + n, e := base64.StdEncoding.Decode(buf, aaa.Input(arg[1])) + m.Assert(e) + buf = buf[:n] + + h := md5.Sum(aaa.Input(arg[0])) + m.Echo("%t", rsa.VerifyPKCS1v15(aaa.public, crypto.MD5, h[:], buf) == nil) + } + }}, + "seal": &ctx.Command{Name: "seal content [sealfile]", Help: "数字加密", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.public != nil { + b, e := rsa.EncryptPKCS1v15(crand.Reader, aaa.public, aaa.Input(arg[0])) + m.Assert(e) + + res := base64.StdEncoding.EncodeToString(b) + if m.Echo(res); len(arg) > 1 { + m.Assert(ioutil.WriteFile(arg[1], []byte(res), 0666)) + } + } + }}, + "deal": &ctx.Command{Name: "deal content", Help: "数字解密", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.private != nil { + buf := make([]byte, 1024) + n, e := base64.StdEncoding.Decode(buf, aaa.Input(arg[0])) + m.Assert(e) + buf = buf[:n] + + b, e := rsa.DecryptPKCS1v15(crand.Reader, aaa.private, buf) + m.Assert(e) + m.Echo(string(b)) + } + }}, + "newcipher": &ctx.Command{Name: "newcipher salt", Help: "加密算法", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) { + salt := md5.Sum(aaa.Input(arg[0])) + block, e := aes.NewCipher(salt[:]) + m.Assert(e) + aaa.encrypt = cipher.NewCBCEncrypter(block, salt[:]) + aaa.decrypt = cipher.NewCBCDecrypter(block, salt[:]) + } + }}, + "encrypt": &ctx.Command{Name: "encrypt content [enfile]", Help: "加密数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.encrypt != nil { + content := aaa.Input(arg[0]) + + bsize := aaa.encrypt.BlockSize() + size := (len(content) / bsize) * bsize + if len(content)%bsize != 0 { + size += bsize + } + + buf := make([]byte, size) + for pos := 0; pos < len(content); pos += bsize { + end := pos + bsize + if end > len(content) { + end = len(content) + } + + b := make([]byte, bsize) + copy(b, content[pos:end]) + + aaa.encrypt.CryptBlocks(buf[pos:pos+bsize], b) + } + + res := base64.StdEncoding.EncodeToString(buf) + if m.Echo(res); len(arg) > 1 { + m.Assert(ioutil.WriteFile(arg[1], []byte(res), 0666)) + } + } + }}, + "decrypt": &ctx.Command{Name: "decrypt content [defile]", Help: "解密数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.decrypt != nil { + content := aaa.Input(arg[0]) + + buf := make([]byte, 1024) + n, e := base64.StdEncoding.Decode(buf, content) + m.Assert(e) + buf = buf[:n] + + res := make([]byte, n) + aaa.decrypt.CryptBlocks(res, buf) + + if m.Echo(string(res)); len(arg) > 1 { + m.Assert(ioutil.WriteFile(arg[1], res, 0666)) + } + } + }}, + "md5": &ctx.Command{Name: "md5 content", Help: "数字摘要", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) { + h := md5.Sum(aaa.Input(arg[0])) + m.Echo(hex.EncodeToString(h[:])) + } + }}, + "rsa": &ctx.Command{Name: "rsa gen|sign|verify|encrypt|decrypt|cert", + Help: []string{"gen: 生成密钥, sgin: 私钥签名, verify: 公钥验签, encrypt: 公钥加密, decrypt: 私钥解密", + "密钥: rsa gen [keyfile [pubfile [certfile]]]", + "加密: rsa encrypt pub content [enfile]", + "解密: rsa decrypt key content [defile]", + "签名: rsa sign key content [signfile]", + "验签: rsa verify pub content", + }, + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) { + switch arg[0] { + case "gen": + // 生成私钥 + keys, e := rsa.GenerateKey(crand.Reader, 1024) + m.Assert(e) + + private := string(pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(keys)})) + m.Echo(m.Append("private", private)) + + // 生成公钥 + pub, e := x509.MarshalPKIXPublicKey(&keys.PublicKey) + m.Assert(e) + + public := string(pem.EncodeToMemory(&pem.Block{Type: "RSA PUBLIC KEY", Bytes: pub})) + m.Echo(m.Append("public", public)) + + // 生成证书 + template := x509.Certificate{ + SerialNumber: big.NewInt(1), + IsCA: true, + KeyUsage: x509.KeyUsageCertSign, + } + m.Log("fuck", "what %#v", template) + cert, e := x509.CreateCertificate(crand.Reader, &template, &template, &keys.PublicKey, keys) + m.Assert(e) + + certificate := string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert})) + m.Echo(m.Append("certificate", certificate)) + + // 输出文件 + if len(arg) > 1 { + ioutil.WriteFile(arg[1], []byte(private), 0666) + } + if len(arg) > 2 { + ioutil.WriteFile(arg[2], []byte(public), 0666) + } + if len(arg) > 3 { + ioutil.WriteFile(arg[3], []byte(certificate), 0666) + } + case "sign": + private, e := x509.ParsePKCS1PrivateKey(aaa.Decode(arg[1])) + m.Assert(e) + + h := md5.Sum(aaa.Input(arg[2])) + b, e := rsa.SignPKCS1v15(crand.Reader, private, crypto.MD5, h[:]) + m.Assert(e) + + res := base64.StdEncoding.EncodeToString(b) + if m.Echo(res); len(arg) > 3 { + ioutil.WriteFile(arg[3], []byte(res), 0666) + } + case "verify": + public, e := x509.ParsePKIXPublicKey(aaa.Decode(arg[1])) + m.Assert(e) + + buf := make([]byte, 1024) + n, e := base64.StdEncoding.Decode(buf, aaa.Input(arg[2])) + m.Assert(e) + buf = buf[:n] + + h := md5.Sum(aaa.Input(arg[3])) + m.Echo("%t", rsa.VerifyPKCS1v15(public.(*rsa.PublicKey), crypto.MD5, h[:], buf) == nil) + case "encrypt": + public, e := x509.ParsePKIXPublicKey(aaa.Decode(arg[1])) + m.Assert(e) + + b, e := rsa.EncryptPKCS1v15(crand.Reader, public.(*rsa.PublicKey), aaa.Input(arg[2])) + m.Assert(e) + + res := base64.StdEncoding.EncodeToString(b) + if m.Echo(res); len(arg) > 3 { + ioutil.WriteFile(arg[3], []byte(res), 0666) + } + case "decrypt": + private, e := x509.ParsePKCS1PrivateKey(aaa.Decode(arg[1])) + m.Assert(e) + + buf := make([]byte, 1024) + n, e := base64.StdEncoding.Decode(buf, aaa.Input(arg[2])) + m.Assert(e) + buf = buf[:n] + + b, e := rsa.DecryptPKCS1v15(crand.Reader, private, buf) + m.Assert(e) + + if m.Echo(string(b)); len(arg) > 3 { + ioutil.WriteFile(arg[3], b, 0666) + } + case "cert": + private, e := x509.ParsePKCS1PrivateKey(aaa.Decode(arg[1])) + m.Assert(e) + + cert, e := x509.ParseCertificate(aaa.Decode(arg[2])) + m.Assert(e) + + public, e := x509.ParsePKIXPublicKey(aaa.Decode(arg[3])) + m.Assert(e) + + template := &x509.Certificate{ + SerialNumber: big.NewInt(rand.Int63()), + NotBefore: time.Now(), + NotAfter: time.Now().AddDate(1, 0, 0), + } + buf, e := x509.CreateCertificate(crand.Reader, template, cert, public, private) + + certificate := string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: buf})) + if m.Echo(certificate); len(arg) > 4 { + ioutil.WriteFile(arg[4], []byte(certificate), 0666) + } + case "check": + defer func() { + e := recover() + m.Log("fuck", "what %v", e) + }() + + root, e := x509.ParseCertificate(aaa.Decode(arg[1])) + m.Assert(e) + + cert, e := x509.ParseCertificate(aaa.Decode(arg[2])) + m.Assert(e) + + // ee := cert.CheckSignatureFrom(root) + // m.Echo("%v", ee) + // + m.Log("fuck", "----") + pool := &x509.CertPool{} + m.Log("fuck", "----") + m.Echo("%c", pool) + m.Log("fuck", "----") + pool.AddCert(root) + m.Log("fuck", "----") + c, e := cert.Verify(x509.VerifyOptions{Roots: pool}) + m.Log("fuck", "----") + m.Echo("%c", c) + } + } + }}, }, } @@ -764,6 +492,4 @@ func init() { aaa := &AAA{} aaa.Context = Index ctx.Index.Register(Index, aaa) - - aaa.sessions = make(map[string]*ctx.Message) } diff --git a/src/contexts/ctx.go b/src/contexts/ctx.go index 140cb42c..177c3158 100644 --- a/src/contexts/ctx.go +++ b/src/contexts/ctx.go @@ -231,7 +231,7 @@ type Config struct { } type Command struct { Name string - Help string + Help interface{} Form map[string]int Hand func(m *Message, c *Context, key string, arg ...string) @@ -870,12 +870,15 @@ func (m *Message) Put(meta string, key string, value interface{}) *Message { } return m } -func (m *Message) Has(key string) bool { - if _, ok := m.Data[key]; ok { - return true - } - if _, ok := m.Meta[key]; ok { - return true +func (m *Message) Has(key ...string) bool { + switch len(key) { + case 1: + if _, ok := m.Data[key[0]]; ok { + return true + } + if _, ok := m.Meta[key[0]]; ok { + return true + } } return false } diff --git a/src/contexts/ssh/ssh.go b/src/contexts/ssh/ssh.go index 10714de5..08d10255 100644 --- a/src/contexts/ssh/ssh.go +++ b/src/contexts/ssh/ssh.go @@ -4,13 +4,10 @@ import ( "contexts" "fmt" "strings" - "time" ) type SSH struct { - nfs *ctx.Context peer map[string]*ctx.Message - *ctx.Context } @@ -24,175 +21,120 @@ func (ssh *SSH) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server } 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: "主机数量"}, "domain": &ctx.Cache{Name: "domain", Value: "", 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: "主机数量"}, }, Configs: map[string]*ctx.Config{ "hostname": &ctx.Config{Name: "hostname", Value: "com", Help: "主机数量"}, - "interval": &ctx.Config{Name: "interval", Value: "3", 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 [security [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)), "远程主机") - sub.Spawn().Cmd("pwd", "") - return sub - }, m.Meta["detail"]) - if !m.Caps("domain") { - m.Cap("domain", m.Cap("hostname", m.Conf("hostname"))) - } - // m.Spawn(m.Target()).Cmd("save") + m.Sess("nfs").Call(func(sub *ctx.Message) *ctx.Message { + sub.Start(fmt.Sprintf("host%d", m.Capi("nhost", 1)), "远程主机") + sub.Spawn().Cmd("pwd", "") + return sub + }, m.Meta["detail"]) + if !m.Caps("domain") { + m.Cap("domain", m.Cap("hostname", m.Conf("hostname"))) } + // m.Spawn(m.Target()).Cmd("save") }}, "dial": &ctx.Command{Name: "dial address [security [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) - return sub - }, m.Meta["detail"]) + m.Sess("nfs").CallBack(true, func(sub *ctx.Message) *ctx.Message { + sub.Target().Start(sub) + 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) { + origin, domain := "", "" + if len(arg) > 1 && arg[0] == "domain" { + origin, arg = arg[1], arg[2:] + if d := strings.TrimPrefix(origin, m.Cap("domain")); len(d) > 0 && d[0] == '.' { + domain = d[1:] + } else if d == "" { + domain = d + } else { + domain = origin + } + + if domain == "" { //本地执行 + msg := m.Spawn().Cmd(arg) + m.Copy(msg, "result").Copy(msg, "append") + return + } + } else { + if m.Has("send_code") { //本地执行 + msg := m.Spawn().Cmd(arg) + m.Copy(msg, "result").Copy(msg, "append") + } else { //对端执行 + msg := m.Spawn(ssh.Message().Source()) + msg.Cmd("send", arg) + m.Copy(msg, "result").Copy(msg, "append") + } + return + } + + match := false + host := strings.SplitN(domain, ".", 2) + m.Travel(func(m *ctx.Message, i int) bool { + if i == 0 { + return true + } + if m.Cap("hostname") == host[0] || "*" == host[0] { + ssh, ok := m.Target().Server.(*SSH) + m.Assert(ok) + msg := m.Spawn(ssh.Message().Source()) + + if len(host) > 1 { + msg.Cmd("send", "domain", host[1], arg) + } else { + msg.Cmd("send", arg) + } + m.Copy(msg, "result").Copy(msg, "append") + + if !match { + match = !m.Appends("domain_miss") + } + return host[0] == "*" + } + return true + }, c) + + if match { + return + } + if m.Target() == c && m.Has("send_code") { + m.Appends("domain_miss", true) + return + } + if m.Cap("domain") == m.Conf("hostname") { + m.Appends("domain_miss", true) + return + } + + // 向上路由 + msg := m.Spawn(c.Message().Source()) + msg.Cmd("send", "domain", origin, arg) + m.Copy(msg, "result").Copy(msg, "append") } }}, - "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) { - origin, domain := "", "" - if len(arg) > 1 && arg[0] == "domain" { - origin, arg = arg[1], arg[2:] - if d := strings.TrimPrefix(origin, m.Cap("domain")); len(d) > 0 && d[0] == '.' { - domain = d[1:] - } else if d == "" { - domain = d - } else { - domain = origin - } - - if domain == "" { //本地执行 - msg := m.Spawn().Cmd(arg) - m.Copy(msg, "result").Copy(msg, "append") - return - } - } else { - if m.Has("send_code") { //本地执行 - msg := m.Spawn().Cmd(arg) - m.Copy(msg, "result").Copy(msg, "append") - } else { //对端执行 - msg := m.Spawn(ssh.Message().Source()) - msg.Cmd("send", arg) - m.Copy(msg, "result").Copy(msg, "append") - } - return - } - - match := false - host := strings.SplitN(domain, ".", 2) - m.Travel(func(m *ctx.Message, i int) bool { - if i == 0 { - return true - } - if m.Cap("hostname") == host[0] || "*" == host[0] { - ssh, ok := m.Target().Server.(*SSH) - m.Assert(ok) - msg := m.Spawn(ssh.Message().Source()) - - if len(host) > 1 { - msg.Cmd("send", "domain", host[1], arg) - } else { - msg.Cmd("send", arg) - } - m.Copy(msg, "result").Copy(msg, "append") - - if !match { - match = !m.Appends("domain_miss") - } - return host[0] == "*" - } - return true - }, c) - - if match { - return - } - if m.Target() == c && m.Has("send_code") { - m.Appends("domain_miss", true) - return - } - if m.Cap("domain") == m.Conf("hostname") { - m.Appends("domain_miss", true) - return - } - - // 向上路由 - msg := m.Spawn(c.Message().Source()) - msg.Cmd("send", "domain", origin, arg) - m.Copy(msg, "result").Copy(msg, "append") - } - }}, - "pwd": &ctx.Command{Name: "pwd", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "pwd": &ctx.Command{Name: "pwd [hostname]", Help: "主机域名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if len(arg) == 0 { m.Echo(m.Cap("domain")) return @@ -309,18 +251,6 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", 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")}) @@ -328,82 +258,6 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", 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) - } - } - }}, }, }