diff --git a/etc/init.shy b/etc/init.shy index 03429699..90a10ad6 100644 --- a/etc/init.shy +++ b/etc/init.shy @@ -5,3 +5,6 @@ source etc/local.shy alias import nfs alias send send + alias dial dial + +config debug on diff --git a/src/contexts/aaa/aaa.go b/src/contexts/aaa/aaa.go index 945c4842..86a3db4e 100644 --- a/src/contexts/aaa/aaa.go +++ b/src/contexts/aaa/aaa.go @@ -2,6 +2,7 @@ package aaa // {{{ // }}} import ( // {{{ "contexts" + "math/big" "bufio" "io" @@ -12,6 +13,8 @@ import ( // {{{ "crypto/md5" "strings" + "crypto/aes" + "crypto/cipher" crand "crypto/rand" "crypto/rsa" "crypto/x509" @@ -29,6 +32,12 @@ import ( // {{{ // }}} type AAA struct { + public *rsa.PublicKey + private *rsa.PrivateKey + certificate *x509.Certificate + encrypt cipher.BlockMode + decrypt cipher.BlockMode + sessions map[string]*ctx.Message *ctx.Context } @@ -68,6 +77,21 @@ func (aaa *AAA) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server 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) + m.Log("fuck", "public %v", s.public) + } + if m.Has("key") { + s.private = m.Optionv("private").(*rsa.PrivateKey) + s.public = &s.private.PublicKey + m.Log("fuck", "public %v", s.public) + + } + return s } @@ -107,15 +131,76 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", Configs: map[string]*ctx.Config{ "rootname": &ctx.Config{Name: "rootname", Value: "root", Help: "根用户名"}, "expire": &ctx.Config{Name: "expire(s)", Value: "7200", Help: "会话超时"}, - "cert": &ctx.Config{Name: "cert", Value: "etc/cert.pem", 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: "默认模块帮助"}, }, Commands: map[string]*ctx.Command{ "login": &ctx.Command{ - Name: "login [sessid]|[username password]|[load|save filename]", + 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, "load": 1, "save": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) { // {{{ + stream := "" + if m.Has("ip") { + stream = m.Option("ip") + } + 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) + } + + m.Log("fuck", "stream %s", stream) + if stream != "" { + m.Start(m.Confx("aaa_name"), m.Confx("aaa_help"), arg[0], "", aaa.Session(arg[0])) + m.Cap("stream", stream) + return + } + switch len(arg) { case 0: m.Travel(func(m *ctx.Message, i int) bool { @@ -154,19 +239,247 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", }) } default: - if msg := m.Find(arg[0], false); msg == nil { - m.Start(arg[0], "用户", arg[0], aaa.Password(arg[1]), aaa.Session(arg[0])) + 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.Log("fuck", "%v", m.Format()) + m.Sess("aaa", m.Target()) + m.Echo(m.Cap("sessid")) + } else { + m.Sess("aaa", c) + } + find = true + return false + } + return true + }, c) + + if !find { + m.Start(m.Confx("aaa_name"), m.Confx("aaa_help"), arg[0], aaa.Password(arg[1]), aaa.Session(arg[0])) + m.Cap("stream", arg[0]) + m.Sess("aaa", m) m.Echo(m.Cap("sessid")) - } else if msg.Cap("password") != aaa.Password(arg[1]) { - return - } else { - m.Echo(msg.Cap("sessid")) - m.Copy(msg, "target") } } } } // }}} }}, + "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]) + + m.Log("fuck", "pos: %d end: %d", 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:] + } + + m.Log("fuck", "why %v", content) + 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) { @@ -210,9 +523,18 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", 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 } @@ -312,23 +634,6 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", } // }}} }}, - "deal": &ctx.Command{Name: "deal init|sell|buy|done [keyfile name][key str]", 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[:])) - } - // }}} - }}, }, } diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go index 2d58f592..e37d6b55 100644 --- a/src/contexts/cli/cli.go +++ b/src/contexts/cli/cli.go @@ -200,7 +200,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", // }}} }}, "cli_help": &ctx.Config{Name: "cli_help", Value: "shell", Help: "模块文档"}, - "cmd_timeout": &ctx.Config{Name: "cmd_timeout", Value: "3s", Help: "系统命令超时"}, + "cmd_timeout": &ctx.Config{Name: "cmd_timeout", Value: "10s", Help: "系统命令超时"}, "time_format": &ctx.Config{Name: "time_format", Value: "2006-01-02 15:04:05", Help: "时间格式"}, "time_unit": &ctx.Config{Name: "time_unit", Value: "1000", Help: "时间倍数"}, @@ -740,6 +740,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", go func() { if out, e := cmd.CombinedOutput(); e != nil { m.Echo("error: ").Echo("%s\n", e) + m.Echo("%s\n", string(out)) } else { m.Echo(string(out)) } diff --git a/src/contexts/ctx.go b/src/contexts/ctx.go index b5cf8a7e..3079e8eb 100644 --- a/src/contexts/ctx.go +++ b/src/contexts/ctx.go @@ -30,6 +30,12 @@ func Trans(arg ...interface{}) []string { // {{{ ls := []string{} for _, v := range arg { switch val := v.(type) { + case *Message: + if val.Hand { + ls = append(ls, val.Meta["result"]...) + } else { + ls = append(ls, val.Meta["detail"]...) + } case string: ls = append(ls, val) case bool: @@ -96,6 +102,7 @@ type Context struct { requests []*Message sessions []*Message + message *Message contexts map[string]*Context context *Context @@ -150,6 +157,7 @@ func (c *Context) Begin(m *Message, arg ...string) *Context { // {{{ c.requests = append(c.requests, m) m.source.sessions = append(m.source.sessions, m) + c.message = m m.Log("begin", "%d context %v %v", m.root.Capi("ncontext", 1), m.Meta["detail"], m.Meta["option"]) for k, x := range c.Configs { @@ -181,6 +189,7 @@ func (c *Context) Start(m *Message, arg ...string) bool { // {{{ go m.TryCatch(m, true, func(m *Message) { m.Log(m.Cap("status", "start"), "%d server %v %v", m.root.Capi("nserver", 1), m.Meta["detail"], m.Meta["option"]) + c.message = m c.exit = make(chan bool, 2) if running <- true; c.Server != nil && c.Server.Start(m, m.Meta["detail"]...) { c.Close(m, m.Meta["detail"]...) @@ -237,6 +246,11 @@ func (c *Context) Context() *Context { // {{{ return c.context } +// }}} +func (c *Context) Message() *Message { // {{{ + return c.message +} + // }}} func (c *Context) Has(key ...string) bool { // {{{ switch len(key) { @@ -402,6 +416,7 @@ func (m *Message) Assert(e interface{}, msg ...string) bool { // {{{ e = errors.New(msg[0]) } + m.Log("error", "%s", fmt.Sprintln(e)) panic(m.Set("result", "error: ", fmt.Sprintln(e), "\n")) } @@ -495,10 +510,15 @@ func (m *Message) Travel(hand func(m *Message, i int) bool, c ...*Context) { // // }}} -func (m *Message) Spawn(arg ...*Context) *Message { // {{{ +func (m *Message) Spawn(arg ...interface{}) *Message { // {{{ c := m.target if len(arg) > 0 { - c = arg[0] + switch v := arg[0].(type) { + case *Context: + c = v + case *Message: + c = v.target + } } msg := &Message{ @@ -1292,10 +1312,11 @@ func (m *Message) Cmd(args ...interface{}) *Message { // {{{ // }}} func (m *Message) Confx(key string, arg ...interface{}) string { // {{{ + conf := m.Conf(key) if len(arg) == 0 { value := m.Option(key) if value == "" { - value = m.Conf(key) + value = conf } return value } @@ -1327,7 +1348,7 @@ func (m *Message) Confx(key string, arg ...interface{}) string { // {{{ } } if !force && value == "" { - value = m.Conf(key) + value = conf } format := "%s" @@ -2183,9 +2204,16 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } if len(arg) == 1 { - if sub := msg.Sess(arg[0], false); sub != nil { - m.Echo("%d", sub.code) + m.Log("fuck", "%v", m.Meta) + for msg = msg; msg != nil; msg = msg.message { + for k, v := range msg.Sessions { + if k == arg[0] { + m.Echo("%d", v.code) + return + } + } } + m.Log("fuck", "%v", m.Meta) return } @@ -2352,6 +2380,11 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } else { m.Add("append", "context", "") } + if msg.target.Message != nil { + m.Add("append", "message", msg.target.message.code) + } else { + m.Add("append", "message", "") + } m.Add("append", "status", msg.Cap("status")) m.Add("append", "stream", msg.Cap("stream")) diff --git a/src/contexts/nfs/nfs.go b/src/contexts/nfs/nfs.go index ad263486..3e3793d8 100644 --- a/src/contexts/nfs/nfs.go +++ b/src/contexts/nfs/nfs.go @@ -52,7 +52,7 @@ type NFS struct { func (nfs *NFS) open(name string) (*os.File, error) { // {{{ if path.IsAbs(name) { - nfs.Log("info", "open %s", name) + nfs.Message.Log("info", "open %s", name) return os.Open(name) } for i := len(nfs.paths) - 1; i >= 0; i-- { @@ -538,7 +538,6 @@ func (nfs *NFS) Read(p []byte) (n int, err error) { // {{{ // }}} func (nfs *NFS) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{ - nfs.Message = m if len(arg) > 0 && (arg[0] == "scan" || arg[0] == "open" || arg[0] == "append") { c.Caches = map[string]*ctx.Cache{ "pos": &ctx.Cache{Name: "pos", Value: "0", Help: "pos"}, @@ -679,28 +678,22 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { // {{{ nfs.io = m.Optionv("io").(net.Conn) nfs.hand = map[int]*ctx.Message{} nfs.send = make(chan *ctx.Message, 10) - m.Log("fuck", "send %p", nfs.send) nfs.recv = make(chan *ctx.Message, 10) - go func() { + go func() { //发送消息队列 for { select { case msg := <-nfs.send: - m.Log("fuck", "send %p %v", nfs.send, msg.Meta) - m.Log("fuck", "send %p %v", nfs.send, msg.Meta) head, body := "detail", "option" if msg.Hand { - m.Log("fuck", "send %p %v", nfs.send, msg.Meta) head, body = "result", "append" send_code := msg.Option("send_code") msg.Append("send_code1", send_code) m.Log("info", "%s recv: %v %v", msg.Option("recv_code"), msg.Meta[head], msg.Meta[body]) } else { - m.Log("fuck", "send %p %v", nfs.send, msg.Meta) - m.Log("fuck", "send %p %v", nfs.send, msg.Meta) - m.Log("info", "%d send: %v %v", m.Capi("nsend", 1), msg.Meta[head], msg.Meta[body]) + msg.Option("send_code", m.Capi("nsend", 1)) + m.Log("info", "%d send: %v %v", m.Capi("nsend"), msg.Meta[head], msg.Meta[body]) nfs.hand[m.Capi("nsend")] = msg - msg.Option("send_code", m.Capi("nsend")) } for _, v := range msg.Meta[head] { @@ -723,12 +716,18 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { // {{{ } }() - go func() { + go func() { //接收消息队列 bio := bufio.NewScanner(nfs.io) var e error - for msg, head, body := m.Sess("target"), "", ""; bio.Scan(); { + var msg *ctx.Message + for head, body := "", ""; bio.Scan(); { + if msg == nil { + msg = m.Sess("target") + } + if msg.Meta == nil { + msg.Meta = map[string][]string{} + } line := bio.Text() - m.Log("fuck", "send %p %v", nfs.send, msg.Meta) m.Capi("nread", len(line)+1) if len(line) == 0 { @@ -742,7 +741,7 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { // {{{ h.Copy(msg, "result").Copy(msg, "append") h.Remote <- true } - msg = m.Sess("target") + msg = nil continue } @@ -767,8 +766,6 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { // {{{ for { select { case msg := <-nfs.recv: - m.Log("fuck", "why %s %v", msg.Format(), msg.Meta) - nfs.send <- msg.Cmd() } } @@ -1286,16 +1283,10 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", m.Sess("tcp").Call(func(sub *ctx.Message) *ctx.Message { sub.Start(fmt.Sprintf("file%d", m.Capi("nfile", 1)), "远程文件") return sub.Sess("target", m.Source()).Call(func(sub1 *ctx.Message) *ctx.Message { - sub.Log("fuck", "send") - nfs, ok := sub.Target().Server.(*NFS) - sub.Log("fuck", "send %v", ok) - m.Log("fuck", "send %p", nfs.send) + nfs, _ := sub.Target().Server.(*NFS) sub1.Remote = make(chan bool, 1) - sub.Log("info", "before send %d", len(nfs.send)) nfs.send <- sub1 - sub.Log("info", "middle send %d", len(nfs.send)) <-sub1.Remote - sub.Log("info", "after send %d", len(nfs.send)) return nil }) }, m.Meta["detail"]) @@ -1308,13 +1299,9 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", sub.Start(fmt.Sprintf("file%d", m.Capi("nfile", 1)), "远程文件") return sub.Sess("target", m.Source()).Call(func(sub1 *ctx.Message) *ctx.Message { nfs, _ := sub.Target().Server.(*NFS) - m.Log("fuck", "send %p", nfs.send) sub1.Remote = make(chan bool, 1) - sub.Log("info", "before send %d", len(nfs.send)) nfs.send <- sub1 - sub.Log("info", "middle send %d", len(nfs.send)) <-sub1.Remote - sub.Log("info", "after send %d", len(nfs.send)) return nil }) }, m.Meta["detail"]) diff --git a/src/contexts/ssh/ssh.go b/src/contexts/ssh/ssh.go index 1f5bb741..48fe25b1 100644 --- a/src/contexts/ssh/ssh.go +++ b/src/contexts/ssh/ssh.go @@ -11,9 +11,9 @@ import ( // {{{ // }}} type SSH struct { - nfs *ctx.Context + nfs *ctx.Context + peer map[string]*ctx.Message - *ctx.Message *ctx.Context } @@ -30,7 +30,6 @@ 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.Message = m ssh.Caches["hostname"] = &ctx.Cache{Name: "hostname", Value: "", Help: "主机数量"} if ssh.Context == Index { Pulse = m @@ -40,7 +39,6 @@ func (ssh *SSH) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ // }}} func (ssh *SSH) Start(m *ctx.Message, arg ...string) bool { // {{{ - ssh.Message = m ssh.nfs = m.Source() m.Cap("stream", m.Source().Name) return false @@ -59,7 +57,7 @@ func (ssh *SSH) Close(m *ctx.Message, arg ...string) bool { // {{{ 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() + go ssh.Message().Spawn(m.Target()).Copy(ssh.Message(), "detail").Cmd() time.Sleep(time.Second * time.Duration(m.Confi("interval"))) } }() @@ -102,7 +100,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", }, Configs: map[string]*ctx.Config{ "interval": &ctx.Config{Name: "interval", Value: "3", Help: "主机数量"}, - "hostname": &ctx.Config{Name: "hostname", Value: "host", 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: "主机数量"}, @@ -136,125 +134,73 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", // }}} }}, "send": &ctx.Command{Name: "send [domain str] cmd arg...", Help: "远程执行", - Form: map[string]int{"domain": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - m.Log("why", "send") if ssh, ok := m.Target().Server.(*SSH); m.Assert(ok) { // {{{ - if m.Options("domain") { - find := false - host := strings.SplitN(m.Option("domain"), ".", 2) + 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()) + + msg := m.Spawn(ssh.Message().Source()).Copy(m, "option") if len(host) > 1 { - msg.Option("domain", host[1]) - msg.Detail("send", arg) + msg.Options("downflow", true) + msg.Detail("send", "domain", host[1], arg) } else { msg.Detail(arg) } - m.Log("why", "send") - m.Log("why", "send %s", ssh.Message.Format()) - ssh.Message.Back(msg) - m.Copy(msg, "result").Copy(msg, "append") - find = true + + 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 !find && m.Cap("domain") != "com" { + 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()) - msg.Option("domain", m.Option("domain")) - m.Log("why", "send------ %s", c.Name) - msg.Detail("send", arg) - m.Log("why", "send %s", ssh.Message.Format()) - ssh.Message.Back(msg) - m.Copy(msg, "result").Copy(msg, "append") - find = true + 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 } - msg := m.Spawn(ssh.Message.Source()) - m.Log("why", "send") - msg.Detail(arg) - m.Log("why", "send %s", ssh.Message.Format()) - ssh.Message.Back(msg) - m.Copy(msg, "result").Copy(msg, "append") - return - if m.Option("domain") == m.Cap("domain") { //本地命令 - msg := m.Spawn(m.Target()) - msg.Cmd(arg) + 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") - m.Back(m) - return } - - target := strings.Split(m.Option("domain"), ".") - name, rest := target[0], target[1:] - if name == m.Conf("domain") { - if len(target) > 1 { - name = target[1] - rest = target[2:] - } else { - name = "" - } - } - - if len(rest) == 0 && len(name) == 0 { //点对点通信 - if m.Options("nsend") { //接收命令 - msg := m.Spawn(m.Target()) - msg.Cmd(arg) - m.Copy(msg, "result").Copy(msg, "append") - m.Back(m) - } else { //发送命令 - ssh.Message.Sess("nfs").CallBack(m.Options("stdio"), func(host *ctx.Message) *ctx.Message { - m.Back(m.Copy(host, "result").Copy(host, "append")) - return nil - }, "send", "send", arg) - } - return - } - - miss := true - m.Travel(func(m *ctx.Message, i int) bool { //向下搜索 - if ssh, ok := m.Target().Server.(*SSH); ok && m.Conf("domains") == name { - msg := m.Spawn(ssh.nfs) - msg.Option("domain", strings.Join(rest, ".")) - msg.CallBack(m.Options("stdio"), func(host *ctx.Message) *ctx.Message { - return m.Copy(host, "result").Copy(host, "append") - }, "send", "send", arg) - - miss = false - } - return miss - }, c) - - if miss { - if name == m.Cap("domain") { - } - } - - if miss { //向上搜索 - if ssh, ok := c.Server.(*SSH); m.Assert(ok) && ssh.nfs != nil { - msg := m.Spawn(ssh.nfs) - msg.Option("domain", m.Option("domain")) - msg.CallBack(m.Options("stdio"), func(host *ctx.Message) *ctx.Message { - return m.Copy(host, "result").Copy(host, "append") - }, "send", "send", arg) - } - } - } - // }}} + return + } // }}} }}, "pwd": &ctx.Command{Name: "pwd", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if len(arg) == 0 { + if len(arg) == 0 { // {{{ if m.Target() == c { m.Echo(m.Cap("domain")) } else { @@ -268,49 +214,98 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", m.Copy(msg, "result").Copy(msg, "append") m.Cap("domain", msg.Result(0)) } else if m.Options("send_code") { - m.Echo("%s.%s", m.Cap("domain"), m.Cap("hostname", arg[0])) - } - return - - switch len(arg) { // {{{ - case 0: - m.Echo(m.Cap("domain")) - case 1: - if m.Options("nsend") { - domain := arg[0] - - m.Travel(func(m *ctx.Message, i int) bool { - if m.Conf("domains") == domain { - domain = domain + m.Cap("nhost") - return false - } - return true - }, c) - m.Conf("domains", domain) - - mdb := m.Find(m.Conf("mdb"), true) - if mdb != nil { - domain := m.Cap("domain") + "." + m.Conf("domains") - mdb.Cmd("exec", "delete from goodship where value=?", domain) - mdb.Cmd("exec", "insert into goodship(uid, share, level, type, value, kind, name) value(?, 'root', 'root', 'terminal', ?, 'terminal', ?)", m.Conf("uid"), domain, domain) + hostname := arg[0] + m.Travel(func(m *ctx.Message, line int) bool { + if hostname == m.Cap("hostname") { + hostname += m.Cap("nhost") + return false } - - m.Echo(m.Cap("domain")) - m.Echo(".") - m.Echo(m.Conf("domains")) - } else { - m.Spawn(m.Target()).CallBack(m.Options("stdio"), func(msg *ctx.Message) *ctx.Message { - m.Conf("domain", msg.Result(2)) - m.Echo(m.Cap("domain", strings.Join(msg.Meta["result"], ""))) - m.Back(msg) - - m.Spawn(m.Target()).Cmd("save") - return nil - }, "send", "pwd", arg[0]) + 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) }}, diff --git a/src/contexts/tcp/tcp.go b/src/contexts/tcp/tcp.go index f06f628d..b398a255 100644 --- a/src/contexts/tcp/tcp.go +++ b/src/contexts/tcp/tcp.go @@ -21,7 +21,8 @@ type TCP struct { func (tcp *TCP) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{ c.Caches = map[string]*ctx.Cache{ "protocol": &ctx.Cache{Name: "网络协议(tcp/tcp4/tcp6)", Value: m.Conf("protocol"), Help: "网络协议"}, - "security": &ctx.Cache{Name: "加密通信(true/false)", Value: m.Conf("security"), Help: "加密通信"}, + "certfile": &ctx.Cache{Name: "certfile", Value: "", Help: "加密通信"}, + "keyfile": &ctx.Cache{Name: "keyfile", Value: "", Help: "加密通信"}, "address": &ctx.Cache{Name: "网络地址", Value: "", Help: "网络地址"}, "nrecv": &ctx.Cache{Name: "nrecv", Value: "0", Help: "网络地址"}, "nsend": &ctx.Cache{Name: "nsend", Value: "0", Help: "网络地址"}, @@ -41,15 +42,17 @@ func (tcp *TCP) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ // }}} func (tcp *TCP) Start(m *ctx.Message, arg ...string) bool { // {{{ m.Cap("address", m.Confx("address", arg, 1)) - m.Cap("security", m.Confx("security", arg, 2)) - m.Cap("protocol", m.Confx("protocol", arg, 3)) + m.Cap("certfile", m.Confx("certfile", arg, 2)) + m.Cap("keyfile", m.Confx("keyfile", arg, 3)) + m.Cap("protocol", m.Confx("protocol", arg, 4)) switch arg[0] { case "dial": - if m.Caps("security") { - cert, e := tls.LoadX509KeyPair(m.Conf("cert"), m.Conf("key")) + if m.Caps("certfile") { + m.Sess("aaa", m.Sess("aaa").Cmd("login", "cert", m.Cap("certfile"), "key", m.Cap("keyfile"), "tcp")) + cert, e := tls.LoadX509KeyPair(m.Cap("certfile"), m.Cap("keyfile")) m.Assert(e) - conf := &tls.Config{Certificates: []tls.Certificate{cert}} + conf := &tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true} c, e := tls.Dial(m.Cap("protocol"), m.Cap("address"), conf) m.Assert(e) @@ -74,8 +77,9 @@ func (tcp *TCP) Start(m *ctx.Message, arg ...string) bool { // {{{ m.Put("option", "io", tcp.Conn).Back(m.Spawn(m.Source())) return false default: - if m.Cap("security") != "false" { - cert, e := tls.LoadX509KeyPair(m.Conf("cert"), m.Conf("key")) + if m.Caps("certfile") { + m.Sess("aaa", m.Sess("aaa").Cmd("login", "cert", m.Cap("certfile"), "key", m.Cap("keyfile"), "tcp")) + cert, e := tls.LoadX509KeyPair(m.Cap("certfile"), m.Cap("keyfile")) m.Assert(e) conf := &tls.Config{Certificates: []tls.Certificate{cert}}