SSH Framework Finished. TODO: More Commands

zry 1 year ago
parent
commit
6feca008d7

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<project version="4">
3
+  <component name="VcsDirectoryMappings">
4
+    <mapping directory="" vcs="Git" />
5
+  </component>
6
+</project>

+ 43 - 0
Commands/CommandFuncsBundle.go

@@ -0,0 +1,43 @@
1
+package Commands
2
+
3
+import (
4
+	"golang.org/x/crypto/ssh/terminal"
5
+	"git.swzry.com/NSMCServerLauncher/Utils"
6
+	"path"
7
+	"fmt"
8
+)
9
+
10
+func CMD_pwd_C(args []string, term *terminal.Terminal,context *Utils.UserContextType)  {
11
+	term.Write([]byte("PWD: " + context.PWD + "\n"))
12
+}
13
+
14
+func CMD_cd_C(args []string, term *terminal.Terminal,context *Utils.UserContextType)  {
15
+	stargs := Utils.RestrictQuotedArgs(args)
16
+	fmt.Println(stargs)
17
+	switch len(stargs) {
18
+	case 0:
19
+		term.Write([]byte("PWD: " + context.PWD + "\n"))
20
+		break
21
+	default:
22
+		tpath := "/"
23
+		if stargs[0][0] == '/'{
24
+			tpath = path.Join("/",stargs[0][1:])
25
+		}else{
26
+			tpath = path.Join(context.PWD,stargs[0])
27
+		}
28
+		
29
+		context.PWD = tpath
30
+		//term.Write([]byte("PWD: " + context.PWD + "\n"))
31
+		// TODO: Change PWD
32
+	}
33
+}
34
+
35
+func CMD_mcstat_C(args []string, term *terminal.Terminal,context *Utils.UserContextType)  {
36
+	term.Write([]byte("Minecraft Server Not Running."))
37
+	// TODO: Minecraft Status Display
38
+}
39
+
40
+func CMD_sz_C(args []string, term *terminal.Terminal,context *Utils.UserContextType)  {
41
+	term.Write([]byte("Not Support Yet."))
42
+	// TODO: ZMODEM Transfer
43
+}

+ 74 - 0
Commands/CommandRegistry.go

@@ -0,0 +1,74 @@
1
+package Commands
2
+
3
+import (
4
+	"git.swzry.com/NSMCServerLauncher/Terminal"
5
+	"golang.org/x/crypto/ssh/terminal"
6
+	"git.swzry.com/NSMCServerLauncher/Utils"
7
+)
8
+
9
+func RegistExtendCommands()  {
10
+	Terminal.RegistCommand("pwd",Terminal.RegistedCommand{
11
+		CmdFunc:  CMD_pwd_C,
12
+		HelpFunc: func(topic string, term *terminal.Terminal) {},
13
+		Intro:"Show current work path",
14
+		Usage:"pwd",
15
+	})
16
+	Terminal.RegistCommand("cd",Terminal.RegistedCommand{
17
+		CmdFunc:  CMD_cd_C,
18
+		HelpFunc: func(topic string, term *terminal.Terminal) {},
19
+		Intro:"Change current work path",
20
+		Usage:"cd <path>",
21
+	})
22
+	Terminal.RegistCommand("mcstat",Terminal.RegistedCommand{
23
+		CmdFunc:  CMD_mcstat_C,
24
+		HelpFunc: func(topic string, term *terminal.Terminal) {
25
+			//term.Write([]byte("Disconnect to the server.\n"))
26
+		},
27
+		Intro:"Show the Minecraft server running status.",
28
+		Usage:"mcstat",
29
+	})
30
+	Terminal.RegistCommand("sz",Terminal.RegistedCommand{
31
+		CmdFunc:  CMD_sz_C,
32
+		HelpFunc: func(topic string, term *terminal.Terminal) {
33
+			term.Write([]byte("This command can help you download file from server using ZMODEM\n\n"))
34
+			term.Write([]byte("ZMODEM is a file transfer protocol that can be carried on SSH/Telnet or other protocol.\n"))
35
+			term.Write([]byte("(See also: https://en.wikipedia.org/wiki/ZMODEM)\n\n"))
36
+		},
37
+		Intro:"Download file from server using ZMODEM",
38
+		Usage:"sz <conf|log|mc> <path_to_file>",
39
+	})
40
+}
41
+
42
+func RegistInnerCommands()  {
43
+	Terminal.RegistCommand("help",Terminal.RegistedCommand{
44
+		CmdFunc: func(args []string, term *terminal.Terminal,context *Utils.UserContextType) {},
45
+		HelpFunc: func(topic string, term *terminal.Terminal) {
46
+			//term.Write([]byte("Disconnect to the server.\n"))
47
+		},
48
+		Intro:"Show help informations.",
49
+		Usage:"help\nhelp <command> [topic]",
50
+	})
51
+	Terminal.RegistCommand("about",Terminal.RegistedCommand{
52
+		CmdFunc: func(args []string, term *terminal.Terminal,context *Utils.UserContextType) {},
53
+		HelpFunc: func(topic string, term *terminal.Terminal) {
54
+			//term.Write([]byte("About this system.\n"))
55
+		},
56
+		Intro:"About this system.",
57
+		Usage:"about",
58
+	})
59
+	Terminal.RegistCommand("exit",Terminal.RegistedCommand{
60
+		CmdFunc: func(args []string, term *terminal.Terminal,context *Utils.UserContextType) {},
61
+		HelpFunc: func(topic string, term *terminal.Terminal) {
62
+			//term.Write([]byte("Disconnect to the server.\n"))
63
+		},
64
+		Intro:"Disconnect to the server.",
65
+		Usage:"exit",
66
+	})
67
+}
68
+
69
+func RegistAllCommands()  {
70
+	Terminal.CommandSystemInit()
71
+	RegistInnerCommands()
72
+	RegistExtendCommands()
73
+	Terminal.GenerateHelpCommandList()
74
+}

+ 150 - 0
Logger/Logger.go

@@ -0,0 +1,150 @@
1
+package Logger
2
+
3
+import (
4
+	"fmt"
5
+	"path/filepath"
6
+	"path"
7
+	"gopkg.in/natefinch/lumberjack.v2"
8
+	"time"
9
+	"git.swzry.com/NSMCServerLauncher/Utils"
10
+)
11
+
12
+type LogFileWriter struct{
13
+	lumberjackLogger lumberjack.Logger
14
+	withTime bool
15
+	prefix string
16
+	enable bool
17
+	time_format_string string
18
+}
19
+
20
+func (this *LogFileWriter) Write(data []byte) (int, error) {
21
+	if(this.enable){
22
+		if(this.withTime){
23
+			this.lumberjackLogger.Write([]byte(fmt.Sprintf("[%s]%s",time.Now().Format(this.time_format_string),this.prefix)))
24
+		}else {
25
+			if this.prefix != ""{
26
+				this.lumberjackLogger.Write([]byte(this.prefix))
27
+			}
28
+		}
29
+		return this.lumberjackLogger.Write(data)
30
+	}else {
31
+		return len(data),nil
32
+	}
33
+}
34
+
35
+var Log TypeOfLoggerSystem
36
+
37
+type TypeOfLoggerSystem struct {
38
+	SysDebug    LogFileWriter
39
+	SysInfo     LogFileWriter
40
+	SysWarning  LogFileWriter
41
+	SysCritical LogFileWriter
42
+	SysFatal    LogFileWriter
43
+	MCLOut      LogFileWriter
44
+	MCLErr      LogFileWriter
45
+	SSH         LogFileWriter
46
+}
47
+
48
+func InitLogger() error {
49
+	logdir,err := filepath.Abs(LoggerConf.logdir)
50
+	if err != nil {
51
+		fmt.Println("[StdOutLog][Fatal Error] Failed Get Log Dir: ",err)
52
+		return err
53
+	}
54
+	if err := Utils.MkDirIfNotExist(logdir); err != nil {return err}
55
+
56
+	syslbj := lumberjack.Logger{
57
+		Filename:   path.Join(LoggerConf.logdir,LoggerConf.syslogcfg.Filename),
58
+		MaxSize:    LoggerConf.syslogcfg.MaxSize,
59
+		MaxAge:     LoggerConf.syslogcfg.MaxAge,
60
+		MaxBackups: LoggerConf.syslogcfg.MaxBackups,
61
+		LocalTime:  LoggerConf.syslogcfg.LocalTime,
62
+		Compress:   LoggerConf.syslogcfg.Compress,
63
+	}
64
+	mcoutlbj := lumberjack.Logger{
65
+		Filename:   path.Join(LoggerConf.logdir,LoggerConf.mcloutlogcfg.Filename),
66
+		MaxSize:    LoggerConf.mcloutlogcfg.MaxSize,
67
+		MaxAge:     LoggerConf.mcloutlogcfg.MaxAge,
68
+		MaxBackups: LoggerConf.mcloutlogcfg.MaxBackups,
69
+		LocalTime:  LoggerConf.mcloutlogcfg.LocalTime,
70
+		Compress:   LoggerConf.mcloutlogcfg.Compress,
71
+	}
72
+	mcerrlbj := lumberjack.Logger{
73
+		Filename:   path.Join(LoggerConf.logdir,LoggerConf.mclerrlogcfg.Filename),
74
+		MaxSize:    LoggerConf.mclerrlogcfg.MaxSize,
75
+		MaxAge:     LoggerConf.mclerrlogcfg.MaxAge,
76
+		MaxBackups: LoggerConf.mclerrlogcfg.MaxBackups,
77
+		LocalTime:  LoggerConf.mclerrlogcfg.LocalTime,
78
+		Compress:   LoggerConf.mclerrlogcfg.Compress,
79
+	}
80
+	sshlbj := lumberjack.Logger{
81
+		Filename:   path.Join(LoggerConf.logdir,LoggerConf.sshlogcfg.Filename),
82
+		MaxSize:    LoggerConf.sshlogcfg.MaxSize,
83
+		MaxAge:     LoggerConf.sshlogcfg.MaxAge,
84
+		MaxBackups: LoggerConf.sshlogcfg.MaxBackups,
85
+		LocalTime:  LoggerConf.sshlogcfg.LocalTime,
86
+		Compress:   LoggerConf.sshlogcfg.Compress,
87
+	}
88
+
89
+
90
+	Log = TypeOfLoggerSystem{
91
+		SysCritical: LogFileWriter{
92
+			lumberjackLogger:syslbj,
93
+			enable:true,
94
+			prefix:"<CRITICAL>",
95
+			withTime: true,
96
+			time_format_string:LoggerConf.time_format,
97
+		},
98
+		SysFatal: LogFileWriter{
99
+			lumberjackLogger:syslbj,
100
+			enable:true,
101
+			prefix:"<FATAL>",
102
+			withTime: true,
103
+			time_format_string:LoggerConf.time_format,
104
+		},
105
+		SysInfo: LogFileWriter{
106
+			lumberjackLogger:syslbj,
107
+			enable:true,
108
+			prefix:"<INFO>",
109
+			withTime: true,
110
+			time_format_string:LoggerConf.time_format,
111
+		},
112
+		SysWarning: LogFileWriter{
113
+			lumberjackLogger:syslbj,
114
+			enable:true,
115
+			prefix:"<WARNING>",
116
+			withTime: true,
117
+			time_format_string:LoggerConf.time_format,
118
+		},
119
+		SysDebug: LogFileWriter{
120
+			lumberjackLogger:syslbj,
121
+			enable:LoggerConf.debug_log,
122
+			prefix:"<DEBUG>",
123
+			withTime: true,
124
+			time_format_string:LoggerConf.time_format,
125
+		},
126
+		MCLOut: LogFileWriter{
127
+			lumberjackLogger:mcoutlbj,
128
+			enable:true,
129
+			prefix:"",
130
+			withTime: false,
131
+			time_format_string:LoggerConf.time_format,
132
+		},
133
+		MCLErr: LogFileWriter{
134
+			lumberjackLogger:mcerrlbj,
135
+			enable:true,
136
+			prefix:"",
137
+			withTime: false,
138
+			time_format_string:LoggerConf.time_format,
139
+		},
140
+		SSH: LogFileWriter{
141
+			lumberjackLogger:sshlbj,
142
+			enable:true,
143
+			prefix:"",
144
+			withTime: true,
145
+			time_format_string:LoggerConf.time_format,
146
+		},
147
+	}
148
+
149
+	return nil
150
+}

+ 121 - 0
Logger/LoggerConfParser.go

@@ -0,0 +1,121 @@
1
+package Logger
2
+
3
+import (
4
+	"github.com/larspensjo/config"
5
+	"fmt"
6
+	"git.swzry.com/NSMCServerLauncher/Utils"
7
+)
8
+
9
+var LoggerConf NSMCSL_LoggerConf
10
+
11
+type NSMCSL_LoggerConfigSingleFileSection struct {
12
+	Filename string
13
+	MaxSize int
14
+	MaxAge int
15
+	MaxBackups int
16
+	LocalTime bool
17
+	Compress bool
18
+}
19
+
20
+type NSMCSL_LoggerConf struct {
21
+	logdir string
22
+	debug_log bool
23
+	time_format string
24
+	syslogcfg NSMCSL_LoggerConfigSingleFileSection
25
+	mcloutlogcfg NSMCSL_LoggerConfigSingleFileSection
26
+	mclerrlogcfg NSMCSL_LoggerConfigSingleFileSection
27
+	sshlogcfg NSMCSL_LoggerConfigSingleFileSection
28
+}
29
+
30
+func LoadLoggerConfig(loggerConfFile string) error {
31
+	cf,err := config.ReadDefault(loggerConfFile)
32
+	if (err != nil){
33
+		fmt.Println("Failed Read Log Config File '",loggerConfFile,"' :", err.Error())
34
+		return err
35
+	}
36
+	if r,err := cf.Bool("global","debug_log");err != nil{
37
+		fmt.Println("Failed Parse Log Config File '",loggerConfFile,"' For 'global.debug_log':", err.Error())
38
+		return err
39
+	}else{
40
+		LoggerConf.debug_log = r
41
+	}
42
+	if r,err := cf.String("global","log_dir");err != nil{
43
+		fmt.Println("Failed Parse Log Config File '",loggerConfFile,"' For 'global.log_dir':", err.Error())
44
+		return err
45
+	}else{
46
+		LoggerConf.logdir = Utils.StripSpaceAndQuote(r)
47
+	}
48
+	if r,err := cf.String("global","time_format");err != nil{
49
+		fmt.Println("Failed Parse Log Config File '",loggerConfFile,"' For 'global.time_format':", err.Error())
50
+		return err
51
+	}else{
52
+		LoggerConf.time_format = Utils.StripSpaceAndQuote(r)
53
+	}
54
+	if r,err := i_LoggerConfig_SingleLogParse(cf,"system");err != nil{
55
+		fmt.Println("		(At Log Config File '",loggerConfFile,"')")
56
+		return err
57
+	}else{
58
+		LoggerConf.syslogcfg = r
59
+	}
60
+	if r,err := i_LoggerConfig_SingleLogParse(cf,"mclauncher.stdout");err != nil{
61
+		fmt.Println("		(At Log Config File '",loggerConfFile,"')")
62
+		return err
63
+	}else{
64
+		LoggerConf.mcloutlogcfg = r
65
+	}
66
+	if r,err := i_LoggerConfig_SingleLogParse(cf,"mclauncher.stderr");err != nil{
67
+		fmt.Println("		(At Log Config File '",loggerConfFile,"')")
68
+		return err
69
+	}else{
70
+		LoggerConf.mclerrlogcfg = r
71
+	}
72
+	if r,err := i_LoggerConfig_SingleLogParse(cf,"ssh");err != nil{
73
+		fmt.Println("		(At Log Config File '",loggerConfFile,"')")
74
+		return err
75
+	}else{
76
+		LoggerConf.sshlogcfg = r
77
+	}
78
+
79
+	return nil
80
+}
81
+
82
+func i_LoggerConfig_SingleLogParse(cf *config.Config,secname string) (NSMCSL_LoggerConfigSingleFileSection,error){
83
+	sfs := NSMCSL_LoggerConfigSingleFileSection{}
84
+	if r,err := cf.String(secname,"Filename");err != nil{
85
+		fmt.Println("Failed Parse Log Config File For '",secname,".Filename':", err.Error())
86
+		return sfs,err
87
+	}else{
88
+		sfs.Filename = Utils.StripSpaceAndQuote(r)
89
+	}
90
+	if r,err := cf.Bool(secname,"Compress");err != nil{
91
+		fmt.Println("Failed Parse Log Config File For '",secname,".Compress':", err.Error())
92
+		return sfs,err
93
+	}else{
94
+		sfs.Compress = r
95
+	}
96
+	if r,err := cf.Bool(secname,"LocalTime");err != nil{
97
+		fmt.Println("Failed Parse Log Config File For '",secname,".LocalTime':", err.Error())
98
+		return sfs,err
99
+	}else{
100
+		sfs.LocalTime = r
101
+	}
102
+	if r,err := cf.Int(secname,"MaxAge");err != nil{
103
+		fmt.Println("Failed Parse Log Config File For '",secname,".MaxAge':", err.Error())
104
+		return sfs,err
105
+	}else{
106
+		sfs.MaxAge = r
107
+	}
108
+	if r,err := cf.Int(secname,"MaxSize");err != nil{
109
+		fmt.Println("Failed Parse Log Config File For '",secname,".MaxSize':", err.Error())
110
+		return sfs,err
111
+	}else{
112
+		sfs.MaxSize = r
113
+	}
114
+	if r,err := cf.Int(secname,"MaxBackups");err != nil{
115
+		fmt.Println("Failed Parse Log Config File For '",secname,".MaxBackups':", err.Error())
116
+		return sfs,err
117
+	}else{
118
+		sfs.MaxBackups = r
119
+	}
120
+	return sfs,nil
121
+}

+ 93 - 0
SSHServer/SSHConfParser.go

@@ -0,0 +1,93 @@
1
+package SSHServer
2
+
3
+import (
4
+	"github.com/larspensjo/config"
5
+	"fmt"
6
+	"git.swzry.com/NSMCServerLauncher/Utils"
7
+	"path/filepath"
8
+	"git.swzry.com/NSMCServerLauncher/Logger"
9
+)
10
+
11
+var SSHServerConf NSMCSL_SSHConf
12
+
13
+type NSMCSL_SSHConf struct {
14
+	bind_addr string
15
+	max_auth_tries int
16
+	host_key_file string
17
+	defult_key_length int
18
+	super_user string
19
+	passwd map[string]string
20
+}
21
+
22
+func LoadSSHConfig(loggerConfFile string) error {
23
+	cf,err := config.ReadDefault(loggerConfFile)
24
+	if (err != nil){
25
+		fmt.Println("Failed Read Log Config File '",loggerConfFile,"' :", err.Error())
26
+		return err
27
+	}
28
+	if r,err := cf.String("sshserver","bind_address");err != nil{
29
+		fmt.Println("Failed Parse Log Config File For 'sshserver.bind_address':", err.Error())
30
+		return err
31
+	}else{
32
+		SSHServerConf.bind_addr = Utils.StripSpaceAndQuote(r)
33
+	}
34
+	if r,err := cf.Int("auth","max_auth_tries");err != nil{
35
+		fmt.Println("Failed Parse Log Config File For 'auth.max_auth_tries':", err.Error())
36
+		return err
37
+	}else{
38
+		SSHServerConf.max_auth_tries = r
39
+	}
40
+	if r,err := cf.Int("sshserver","defult_key_length");err != nil{
41
+		fmt.Println("Failed Parse Log Config File For 'sshserver.defult_key_length':", err.Error())
42
+		return err
43
+	}else{
44
+		SSHServerConf.defult_key_length = r
45
+	}
46
+	if r,err := cf.String("sshserver","host_key_file");err != nil{
47
+		fmt.Println("Failed Parse Log Config File For 'sshserver.host_key_file':", err.Error())
48
+		return err
49
+	}else{
50
+		hostkey,err := filepath.Abs(Utils.StripSpaceAndQuote(r))
51
+		if err != nil {
52
+			fmt.Println("[StdOutLog][Fatal Error] Failed Get HostKey Dir: ",err)
53
+			return err
54
+		}
55
+		SSHServerConf.host_key_file = hostkey
56
+	}
57
+	err = GetUserPasswdList(cf)
58
+	if err != nil {
59
+		return err
60
+	}
61
+	if r,err := cf.String("auth","super_user");err != nil{
62
+		fmt.Println("Failed Parse Log Config File For 'auth.super_user':", err.Error())
63
+		return err
64
+	}else{
65
+		u := Utils.StripSpaceAndQuote(r)
66
+		_, ok := SSHServerConf.passwd[u]
67
+		if(ok){
68
+			SSHServerConf.super_user = u
69
+		}else {
70
+			fmt.Fprintln(&Logger.Log.SysWarning,"Super User '", u, "' Does Not Exist.")
71
+		}
72
+	}
73
+	return nil
74
+}
75
+
76
+func GetUserPasswdList(cf *config.Config) error{
77
+	SSHServerConf.passwd = make(map[string]string)
78
+	list,err := cf.SectionOptions("users")
79
+	if err != nil {
80
+		fmt.Println("[StdOutLog][Fatal Error] Failed Parse User List: ",err)
81
+		return err
82
+	}
83
+	for _,user := range list{
84
+		r, err := cf.String("users",user)
85
+		if(err != nil){
86
+			fmt.Fprintln(&Logger.Log.SysWarning,"Failed to Parse Password of User '", user, "'")
87
+			continue
88
+		}
89
+		SSHServerConf.passwd[user] = r
90
+		fmt.Fprintf(&Logger.Log.SysDebug,"User %v, Password: %v\n", user, r)
91
+	}
92
+	return nil
93
+}

+ 174 - 0
SSHServer/SSHServer.go

@@ -0,0 +1,174 @@
1
+package SSHServer
2
+
3
+import (
4
+	"git.swzry.com/NSMCServerLauncher/Utils"
5
+	"fmt"
6
+	"git.swzry.com/NSMCServerLauncher/Logger"
7
+	"crypto/rsa"
8
+	"crypto/rand"
9
+	"crypto/x509"
10
+	"encoding/pem"
11
+	"os"
12
+	"golang.org/x/crypto/ssh"
13
+	"io/ioutil"
14
+	"net"
15
+	"github.com/swzry/go.TSmap"
16
+	"golang.org/x/crypto/ssh/terminal"
17
+	"git.swzry.com/NSMCServerLauncher/Terminal"
18
+	"golang.org/x/crypto/bcrypt"
19
+)
20
+
21
+var mainThreadBlockChan chan byte
22
+var ServerConf *ssh.ServerConfig
23
+var _clientListRawMap map[interface{}]interface{}
24
+var ClientList TSmap.TSmap
25
+
26
+func StartSSHServer(mtbc chan byte)  {
27
+	mainThreadBlockChan = mtbc
28
+	if r,err := Utils.PathExists(SSHServerConf.host_key_file); ((!r) || (err != nil)) {
29
+		fmt.Fprintln(&Logger.Log.SysInfo,"Generating SSH Host Key......")
30
+		fmt.Fprintln(&Logger.Log.SysInfo,"(It may takes a long time. Please wait.)")
31
+		fmt.Println("Generating SSH Host Key......")
32
+		fmt.Println("(It may takes a long time. Please wait.)")
33
+		GenerateRSAKey(SSHServerConf.host_key_file, SSHServerConf.defult_key_length)
34
+	}
35
+	ServerConf = &ssh.ServerConfig{
36
+		NoClientAuth: false,
37
+		MaxAuthTries: SSHServerConf.max_auth_tries,
38
+		PasswordCallback: SSHPasswordCallback,
39
+		PublicKeyCallback: SSHPublicKeyCallback,
40
+		AuthLogCallback: SSHAuthLogCallback,
41
+		ServerVersion: "SSH-2.0-NSMCServerLauncher-SSH",
42
+	}
43
+	keyBytes, err := ioutil.ReadFile(SSHServerConf.host_key_file)
44
+	if(err != nil){
45
+		fmt.Fprintln(&Logger.Log.SysFatal,"Failed to Load Host Key File: ", err)
46
+		mainThreadBlockChan <- 1
47
+		return
48
+	}
49
+	key, err := ssh.ParsePrivateKey(keyBytes)
50
+	if(err != nil){
51
+		fmt.Fprintln(&Logger.Log.SysFatal,"Failed to Load Host Key: ", err)
52
+		mainThreadBlockChan <- 1
53
+		return
54
+	}
55
+	ServerConf.AddHostKey(key)
56
+	listener,err := net.Listen("tcp", SSHServerConf.bind_addr)
57
+	if(err != nil){
58
+		fmt.Fprintln(&Logger.Log.SysFatal,"Failed to Bind Address '",SSHServerConf.bind_addr,"': ", err)
59
+		mainThreadBlockChan <- 1
60
+		return
61
+	}
62
+	fmt.Fprintln(&Logger.Log.SysInfo,"Listening At '",listener.Addr().String(),"'.")
63
+	_clientListRawMap = make(map[interface{}]interface{})
64
+	ClientList = &TSmap.NewTSmap{
65
+		ConMap:_clientListRawMap,
66
+	}
67
+	for{
68
+		tcpConn,err := listener.Accept()
69
+		if(err == nil){
70
+			fmt.Fprintf(&Logger.Log.SSH,"New Client '%v' Entered.\n",tcpConn.RemoteAddr())
71
+			_, schan, reqchan, err := ssh.NewServerConn(tcpConn, ServerConf)
72
+			if(err != nil){
73
+				fmt.Fprintf(&Logger.Log.SSH,"Failed Handle Client '%v': %v\n",tcpConn.RemoteAddr(),err)
74
+				tcpConn.Close()
75
+				continue
76
+			}else {
77
+				ClientList.Set(tcpConn,&Utils.ClientConnection{
78
+					Channels: &TSmap.NewTSmap{
79
+						ConMap:make(map[interface{}]interface{}),
80
+					},
81
+				})
82
+				go ssh.DiscardRequests(reqchan)
83
+				go handleChannels(schan, tcpConn)
84
+			}
85
+		}
86
+	}
87
+}
88
+
89
+func handleChannels(ch <-chan ssh.NewChannel, conn net.Conn)  {
90
+	cnt := 0
91
+	chlist,ok := ClientList.Get(conn)
92
+	if(!ok){
93
+		fmt.Fprintf(&Logger.Log.SSH,"Failed Handle Client '%v': Channels Not Found.\n",conn.RemoteAddr())
94
+	}
95
+	for newchan := range ch {
96
+		cnt++;
97
+		fmt.Fprintf(&Logger.Log.SSH,"Client '%v', Channels %v, Handling.\n",conn.RemoteAddr(),cnt)
98
+		go handleChannel(newchan,conn,cnt,chlist.(*Utils.ClientConnection))
99
+	}
100
+}
101
+
102
+func handleChannel(nch ssh.NewChannel,conn net.Conn,num int,chlist *Utils.ClientConnection)  {
103
+	if(nch.ChannelType() == "session"){
104
+		ch,req,err := nch.Accept()
105
+		if(err != nil){
106
+			fmt.Fprintf(&Logger.Log.SSH,"Client '%v', Channels %v, Failed Handling : %v\n",conn.RemoteAddr(),num,err)
107
+			return
108
+		}else{
109
+			r:= <-req
110
+			r.Reply(true,nil)
111
+			chlist.Channels.Set(num,Utils.AvaliableChannel{
112
+				Channel: ch,
113
+				Term:    terminal.NewTerminal(ch,"NSMC >"),
114
+				UserContext: Utils.UserContextType{
115
+					PWD: "/",
116
+				},
117
+			})
118
+			go Terminal.HandlerTerminal(ClientList,conn, num)
119
+		}
120
+	}else{
121
+		nch.Reject(ssh.UnknownChannelType, "Unknown Channel Type")
122
+		fmt.Fprintf(&Logger.Log.SSH,"Client '%v', Channels %v, Rejected : Unknown Channel Type '%v'\n",conn.RemoteAddr(),num,nch.ChannelType())
123
+	}
124
+}
125
+
126
+func SSHPasswordCallback(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error)  {
127
+	val, ok := SSHServerConf.passwd[conn.User()]
128
+	if(!ok){
129
+		fmt.Fprintf(&Logger.Log.SSH,"Client '%v' Auth Failed : Unknown User '%v'\n",conn.RemoteAddr(),conn.User())
130
+		return nil,fmt.Errorf("Password Error or User '%v' Does Not Exist..",conn.User())
131
+	}
132
+	err := bcrypt.CompareHashAndPassword([]byte(val),password)
133
+	if(err != nil){
134
+		fmt.Fprintf(&Logger.Log.SSH,"Client '%v', User '%v', Auth Failed : Password Error, Detail: '%v'\n",conn.RemoteAddr(),conn.User(),err)
135
+		return nil,fmt.Errorf("Password Error or User '%v' Does Not Exist..",conn.User())
136
+	}
137
+	return nil,nil
138
+}
139
+
140
+func SSHPublicKeyCallback(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error){
141
+	return nil,fmt.Errorf("PublicKey Auth Not Support Yet.")
142
+}
143
+
144
+func SSHAuthLogCallback(conn ssh.ConnMetadata, method string, err error){
145
+	fmt.Fprintf(&Logger.Log.SSH,"AuthFailed. Info: client='%v', user='%v', method='%v'. Err: %v\n",conn.RemoteAddr(),conn.User(),method,err)
146
+}
147
+
148
+func GenerateRSAKey(keyfn string,keyLength int) {
149
+	privateKey, err := rsa.GenerateKey(rand.Reader, keyLength)
150
+	if err != nil {
151
+		fmt.Fprintln(&Logger.Log.SysFatal,"Failed to Generate RSA Private Key: ", err)
152
+		mainThreadBlockChan <- 1
153
+		return
154
+	}
155
+	derStream := x509.MarshalPKCS1PrivateKey(privateKey)
156
+	block := &pem.Block{
157
+		Type:  "RSA PRIVATE KEY",
158
+		Bytes: derStream,
159
+	}
160
+	file, err := os.Create(keyfn)
161
+	if err != nil {
162
+		fmt.Fprintln(&Logger.Log.SysFatal,"Failed to Create Key File: ", err)
163
+		mainThreadBlockChan <- 1
164
+		return
165
+	}
166
+	err = pem.Encode(file, block)
167
+	if err != nil {
168
+		fmt.Fprintln(&Logger.Log.SysFatal,"Failed to Encode Key: ", err)
169
+		mainThreadBlockChan <- 1
170
+		return
171
+	}
172
+	fmt.Fprintln(&Logger.Log.SysInfo,"SSH Host Key Generated Successfully..")
173
+	fmt.Println("SSH Host Key Generated Successfully..")
174
+}

+ 113 - 0
Terminal/CommandParser.go

@@ -0,0 +1,113 @@
1
+package Terminal
2
+
3
+import (
4
+	"golang.org/x/crypto/ssh/terminal"
5
+	"strings"
6
+	"github.com/swzry/go.TSmap"
7
+	"fmt"
8
+	"git.swzry.com/NSMCServerLauncher/Logger"
9
+	"git.swzry.com/NSMCServerLauncher/Utils"
10
+)
11
+
12
+const HELP_MAX_LINE_WIDTH  = 80
13
+
14
+var CommandList TSmap.TSmap
15
+var HelpCommandList string
16
+
17
+func CommandSystemInit()  {
18
+	CommandList = &TSmap.NewTSmap{
19
+		ConMap: make(map[interface{}]interface{}),
20
+	}
21
+}
22
+
23
+func RegistCommand(name string, reginfo RegistedCommand)  {
24
+	CommandList.Set(name,reginfo)
25
+}
26
+
27
+func GenerateHelpCommandList(){
28
+	linecnt := 0
29
+	CommandList.ForEach(func(k, v interface{}) {
30
+		key,ok := k.(string)
31
+		if(!ok){
32
+			return
33
+		}
34
+		if len(key) + linecnt + 1 <= HELP_MAX_LINE_WIDTH {
35
+			HelpCommandList += " " + key
36
+			linecnt += (len(key) + 1)
37
+		}else{
38
+			HelpCommandList += "\n" + key
39
+			linecnt = len(key)
40
+		}
41
+	})
42
+}
43
+
44
+type RegistedCommand struct {
45
+	CmdFunc  func(args []string, term *terminal.Terminal,context *Utils.UserContextType)
46
+	HelpFunc func(topic string, term *terminal.Terminal)
47
+	Intro    string
48
+	Usage    string
49
+}
50
+
51
+func ExecuteCommandLine(cmdline string, term *terminal.Terminal,context *Utils.UserContextType){
52
+	splwords := strings.Split(cmdline," ")
53
+	if(splwords[0] == "help"){
54
+		GetHelp(splwords[1:],term)
55
+		return
56
+	}
57
+	vf,ok := CommandList.Get(splwords[0])
58
+	if(!ok){
59
+		term.Write([]byte("NSMC Server Launcher Shell: Invalid Command! Use 'help' command to get help.\n"))
60
+		return
61
+	}
62
+	rcv,ok := vf.(RegistedCommand)
63
+	if(!ok){
64
+		fmt.Fprintf(&Logger.Log.SysWarning,"Command '%v' Registry Invalid\n",splwords[0])
65
+		term.Write([]byte("NSMC Server Launcher Shell: Invalid Command!\n"))
66
+		return
67
+	}
68
+	rcv.CmdFunc(splwords[1:],term,context)
69
+	term.SetPrompt("NSMC " + context.PWD + " >")
70
+}
71
+
72
+func GetHelp(args []string, term *terminal.Terminal){
73
+	switch len(args) {
74
+	case 1:
75
+		vf,ok := CommandList.Get(args[0])
76
+		if(!ok){
77
+			term.Write([]byte("help: Invalid Command!\n"))
78
+			return
79
+		}
80
+		rcv,ok := vf.(RegistedCommand)
81
+		if(!ok){
82
+			fmt.Fprintf(&Logger.Log.SysWarning,"Command '%v' Registry Invalid\n",args[0])
83
+			term.Write([]byte("NSMC Server Launcher Shell: Invalid Command!\n"))
84
+			return
85
+		}
86
+		term.Write([]byte(fmt.Sprintf("%s - %s\n\nUsage:\n%s\n\n",args[0],rcv.Intro,rcv.Usage)))
87
+		rcv.HelpFunc("",term)
88
+		term.Write([]byte("\n"))
89
+		break
90
+	case 2:
91
+		vf,ok := CommandList.Get(args[0])
92
+		if(!ok){
93
+			term.Write([]byte("help: Invalid Command!\n"))
94
+			return
95
+		}
96
+		rcv,ok := vf.(RegistedCommand)
97
+		if(!ok){
98
+			fmt.Fprintf(&Logger.Log.SysWarning,"Command '%v' Registry Invalid\n",args[0])
99
+			term.Write([]byte("NSMC Server Launcher Shell: Invalid Command!\n"))
100
+			return
101
+		}
102
+		term.Write([]byte(fmt.Sprintf("Help Topic: %s -> %s\n\n",args[0],args[1])))
103
+		rcv.HelpFunc(args[1],term)
104
+		term.Write([]byte("\n"))
105
+		break
106
+	default:
107
+		term.Write([]byte("You can get detail infomations by using 'help <command>' or 'help <commmand> <topic>'\n\n"))
108
+		term.Write([]byte("Available Commands:\n"))
109
+		term.Write([]byte(HelpCommandList))
110
+		term.Write([]byte("\n\n"))
111
+		break
112
+	}
113
+}

+ 60 - 0
Terminal/Terminal.go

@@ -0,0 +1,60 @@
1
+package Terminal
2
+
3
+import (
4
+	"net"
5
+	"git.swzry.com/NSMCServerLauncher/Logger"
6
+	"fmt"
7
+	"github.com/swzry/go.TSmap"
8
+	"git.swzry.com/NSMCServerLauncher/Utils"
9
+)
10
+
11
+func HandlerTerminal(clientList TSmap.TSmap,conn net.Conn, chnum int){
12
+	clobj,ok := clientList.Get(conn)
13
+	if(!ok){
14
+		fmt.Fprintf(&Logger.Log.SSH,"Client '%v', Channels %v, Failed Handling Terminal : Client Not Found.\n",conn.RemoteAddr(),chnum)
15
+		return
16
+	}
17
+	clientConn, ok := clobj.(*Utils.ClientConnection)
18
+	if(!ok){
19
+		fmt.Fprintf(&Logger.Log.SSH,"Client '%v', Channels %v, Failed Handling Terminal : Internal Error: Can't Convert '%T' into 'Utils.ClientConnection'.\n",conn.RemoteAddr(),chnum,clobj)
20
+		return
21
+	}
22
+	chlist, ok := clientConn.Channels.(TSmap.TSmap)
23
+	if(!ok){
24
+		fmt.Fprintf(&Logger.Log.SSH,"Client '%v', Channels %v, Failed Handling Terminal : Internal Error: Can't Convert '%T' into 'TSMap.TSMap'.\n",conn.RemoteAddr(),chnum,clientConn.Channels)
25
+		return
26
+	}
27
+	chobj,ok := chlist.Get(chnum)
28
+	if(!ok){
29
+		fmt.Fprintf(&Logger.Log.SSH,"Client '%v', Channels %v, Failed Handling Terminal : Channel Not Found.\n",conn.RemoteAddr(),chnum)
30
+		return
31
+	}
32
+	channel,ok := chobj.(Utils.AvaliableChannel)
33
+	if(!ok){
34
+		fmt.Fprintf(&Logger.Log.SSH,"Client '%v', Channels %v, Failed Handling Terminal : Internal Error: Can't Convert '%T' into 'Utils.AvaliableChannel'.\n",conn.RemoteAddr(),chnum,chobj)
35
+		return
36
+	}
37
+	channel.Term.Write([]byte("NSMC Server Launcher V1.0 - Shell\n"))
38
+	channel.Term.SetPrompt("NSMC / >")
39
+	for {
40
+		line,err := channel.Term.ReadLine()
41
+		if( err != nil){
42
+			fmt.Fprintf(&Logger.Log.SSH,"Client '%v', Channels %v, Discard. Detail: %v.\n",conn.RemoteAddr(),chnum,err)
43
+			break
44
+		}
45
+		switch line {
46
+		case "exit":
47
+			clientList.Delete(conn)
48
+			conn.Close()
49
+			break
50
+		case "about":
51
+			channel.Term.Write([]byte("NSMC Server Launcher V1.0\n"))
52
+			channel.Term.Write([]byte("(https://git.swzry.com/zry/NSMCServerLauncher/)\n"))
53
+			channel.Term.Write([]byte("By ZRY (https://www.swzry.com/)\n\n"))
54
+			break
55
+		default:
56
+			ExecuteCommandLine(line,channel.Term,&channel.UserContext)
57
+			break;
58
+		}
59
+	}
60
+}

+ 21 - 0
Utils/Types.go

@@ -0,0 +1,21 @@
1
+package Utils
2
+
3
+import (
4
+	"github.com/swzry/go.TSmap"
5
+	"golang.org/x/crypto/ssh"
6
+	"golang.org/x/crypto/ssh/terminal"
7
+)
8
+
9
+type ClientConnection struct {
10
+	Channels TSmap.TSmap
11
+}
12
+
13
+type UserContextType struct {
14
+	PWD string
15
+}
16
+
17
+type AvaliableChannel struct {
18
+	Channel ssh.Channel
19
+	Term    *terminal.Terminal
20
+	UserContext UserContextType
21
+}

+ 86 - 0
Utils/Utils.go

@@ -0,0 +1,86 @@
1
+package Utils
2
+
3
+import (
4
+	"os"
5
+	"path/filepath"
6
+	"strings"
7
+	"io"
8
+	"fmt"
9
+)
10
+
11
+func GetCurrentDirectory() (string,error) {
12
+	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
13
+	return strings.Replace(dir, "\\", "/", -1),err
14
+}
15
+
16
+func PathExists(path string) (bool, error) {
17
+	_, err := os.Stat(path)
18
+	if err == nil {
19
+		return true, nil
20
+	}
21
+	if os.IsNotExist(err) {
22
+		return false, nil
23
+	}
24
+	return false, err
25
+}
26
+
27
+func CopyFile(dstName, srcName string) (written int64, err error) {
28
+	src, err := os.Open(srcName)
29
+	if err != nil {
30
+		return
31
+	}
32
+	defer src.Close()
33
+	dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0644)
34
+	if err != nil {
35
+		return
36
+	}
37
+	defer dst.Close()
38
+	return io.Copy(dst, src)
39
+}
40
+
41
+func MkDirIfNotExist(path string) error{
42
+	if r,err := PathExists(path); ((!r) || (err != nil)) {
43
+		fmt.Printf("[StdOutLog][WARNING] Dir '%v' Not Exist! Will Create One.\r\n",path)
44
+		if err := os.MkdirAll(path,0777);err != nil {
45
+			fmt.Println("[StdOutLog][Fatal Error] Failed Create Dir '",path,"' : ",err)
46
+			return err
47
+		}
48
+	}
49
+	return nil
50
+}
51
+
52
+func StripSpaceAndQuote(path string) string{
53
+	s := strings.TrimSpace(path)
54
+	s = strings.Trim(s,`"`)
55
+	return s
56
+}
57
+
58
+func RestrictQuotedArgs(input []string) []string{
59
+	ostr := make([]string,0)
60
+	inqstr := ""
61
+	inQuoteFlag := false
62
+	for i := 0; i < len(input); i++ {
63
+		if inQuoteFlag{
64
+			if input[i][len(input[i])-1] == '"'{
65
+				inqstr += input[i][:(len(input[i])-1)]
66
+				ostr = append(ostr,StripSpaceAndQuote(inqstr))
67
+				inqstr = ""
68
+				inQuoteFlag = false
69
+			}else{
70
+				inqstr += input[i] + " "
71
+			}
72
+		}else{
73
+			if input[i][0] == '"'{
74
+				if input[i][len(input[i])-1] == '"'{
75
+					ostr = append(ostr,StripSpaceAndQuote(input[i]))
76
+				}else{
77
+					inQuoteFlag = true
78
+					inqstr += input[i][1:] + " "
79
+				}
80
+			}else{
81
+				ostr = append(ostr,StripSpaceAndQuote(input[i]))
82
+			}
83
+		}
84
+	}
85
+	return ostr
86
+}

+ 62 - 0
dist/sysfiles/conftpl/logger.conf

@@ -0,0 +1,62 @@
1
+[global]
2
+log_dir = "./data/log/"
3
+debug_log = true
4
+# The format of time display. e.g. "2006-01-02 15:04:05"
5
+# It is a strange way to express the format, but it is NOT MY FAULT.
6
+# It is just the STRANGE feature of GoLang.
7
+# See also https://golang.org/pkg/time/#Time.Format
8
+time_format = "2006-01-02 15:04:05.999999999 -0700 MST"
9
+
10
+# [system] For system log
11
+# [mclauncher.stdout] For minecraft server stdout log
12
+# [mclauncher.stderr] For minecraft server stderr log
13
+# [ssh] For ssh server log
14
+
15
+[system]
16
+# Filename is the file to write logs to.  Backup log files will be retained
17
+# in the same directory.
18
+Filename = "System.log"
19
+#MaxSize is the maximum size in megabytes of the log file before it gets
20
+# rotated.
21
+MaxSize = 20
22
+# MaxAge is the maximum number of days to retain old log files based on the
23
+# timestamp encoded in their filename.  Note that a day is defined as 24
24
+# hours and may not exactly correspond to calendar days due to daylight
25
+# savings, leap seconds, etc. The default is not to remove old log files
26
+# based on age.
27
+MaxAge = 365
28
+# MaxBackups is the maximum number of old log files to retain.  The default
29
+# is to retain all old log files (though MaxAge may still cause them to get
30
+# deleted.)
31
+MaxBackups = 300
32
+# LocalTime determines if the time used for formatting the timestamps in
33
+# backup files is the computer's local time.  The default is to use UTC
34
+# time.
35
+LocalTime = true
36
+# Compress determines if the rotated log files should be compressed
37
+# using gzip.
38
+Compress = true
39
+
40
+[mclauncher.stdout]
41
+Filename = "MCLauncherOut.log"
42
+MaxSize = 20
43
+MaxAge = 365
44
+MaxBackups = 300
45
+LocalTime = true
46
+Compress = true
47
+
48
+[mclauncher.stderr]
49
+Filename = "MCLauncherErr.log"
50
+MaxSize = 20
51
+MaxAge = 365
52
+MaxBackups = 300
53
+LocalTime = true
54
+Compress = true
55
+
56
+[ssh]
57
+Filename = "SSH.log"
58
+MaxSize = 20
59
+MaxAge = 365
60
+MaxBackups = 300
61
+LocalTime = true
62
+Compress = true

+ 28 - 0
dist/sysfiles/conftpl/sshd.conf

@@ -0,0 +1,28 @@
1
+[sshserver]
2
+bind_address = "0.0.0.0:2200"
3
+# The host key for SSH server. If it does not exist, a new
4
+# key will be generated.
5
+host_key_file = "./data/keys/sshhost.key"
6
+# If Host Key doesn't exist, how many bits will the new key
7
+# be generated.
8
+defult_key_length = 2048
9
+
10
+[auth]
11
+# The max times for trying bad passwords or certs.
12
+max_auth_tries = 3
13
+# The super user has permissions to manage users.
14
+super_user = admin
15
+
16
+# <username>:<bcrypt password>
17
+# One user per line.
18
+# You can use tools/bcryptGen to generated it.
19
+# e.g.:
20
+#
21
+# /home/gopath/git.swzry.com/zry/NSMCServerLauncher/tools $ ./bcryptGen admin admin
22
+# admin:$2a$10$F8XHjF/ZEtRF01VqAKBHOOO7cHXm3WcNY46Q..UWswXVlIEo23fuC
23
+# /home/gopath/git.swzry.com/zry/NSMCServerLauncher/tools $ ./bcryptGen test test123
24
+# test:$2a$10$jZ81hDAI4lTO5pBJBYbY4OJn5tuZAeqgFm.Kbe8waRfJpOxiGg.v.
25
+
26
+[users]
27
+admin:$2a$10$F8XHjF/ZEtRF01VqAKBHOOO7cHXm3WcNY46Q..UWswXVlIEo23fuC
28
+test:$2a$10$jZ81hDAI4lTO5pBJBYbY4OJn5tuZAeqgFm.Kbe8waRfJpOxiGg.v.

+ 86 - 0
main.go

@@ -0,0 +1,86 @@
1
+package main
2
+
3
+import (
4
+	"path"
5
+	"fmt"
6
+	"os"
7
+	"git.swzry.com/NSMCServerLauncher/Logger"
8
+	"git.swzry.com/NSMCServerLauncher/Utils"
9
+	"git.swzry.com/NSMCServerLauncher/SSHServer"
10
+	"git.swzry.com/NSMCServerLauncher/Commands"
11
+)
12
+
13
+var CurrentPath string
14
+var MainThreadBlockChan chan byte
15
+
16
+func main(){
17
+	cp,err := Utils.GetCurrentDirectory()
18
+	if(err != nil){
19
+		fmt.Println("[StdOutLog][Fatal Error] Failed Get PWD: ",err)
20
+		return
21
+	}
22
+	CurrentPath = cp
23
+	if r,err := Utils.PathExists(path.Join(CurrentPath,"sysfiles")); ((!r) || (err != nil)) {
24
+		fmt.Println("[StdOutLog][Fatal Error] System File Dir './sysfiles/' Not Exist! ")
25
+		return
26
+	}
27
+	isinit := false
28
+	if r,err := Utils.PathExists(path.Join(CurrentPath,"data")); ((!r) || (err != nil)) {
29
+		fmt.Println("[StdOutLog][WARNING] Dir './data/' Not Exist! Will Create One.")
30
+		isinit = true
31
+		if err := os.MkdirAll(path.Join(CurrentPath,"data"),0777);err != nil {
32
+			fmt.Println("[StdOutLog][Fatal Error] Failed Create Dir './data/' : ",err)
33
+			return
34
+		}
35
+	}
36
+	if r,err := Utils.PathExists(path.Join(CurrentPath,"data","conf")); ((!r) || (err != nil)) {
37
+		fmt.Println("[StdOutLog][WARNING] Config Dir './data/conf/' Not Exist! Will Create One.")
38
+		isinit = true
39
+		if err := os.MkdirAll(path.Join(CurrentPath,"data","conf"),0777);err != nil {
40
+			fmt.Println("[StdOutLog][Fatal Error] Failed Create Dir './data/conf/' : ",err)
41
+			return
42
+		}
43
+	}
44
+	if r,err := Utils.PathExists(path.Join(CurrentPath,"data","conf", "logger.conf")); ((!r) || (err != nil)) {
45
+		fmt.Println("[StdOutLog][WARNING] Config File './data/conf/logger.conf' Not Exist! Will Create A Template Config File..")
46
+		isinit = true
47
+		if _,err := Utils.CopyFile(path.Join(CurrentPath,"data","conf", "logger.conf"),path.Join(CurrentPath,"sysfiles","conftpl", "logger.conf"));err != nil {
48
+			fmt.Println("[StdOutLog][Fatal Error] Failed Copy Template Config File './data/conf/logger.conf' : ",err)
49
+			return
50
+		}
51
+	}
52
+	if r,err := Utils.PathExists(path.Join(CurrentPath,"data","conf", "sshd.conf")); ((!r) || (err != nil)) {
53
+		fmt.Println("[StdOutLog][WARNING] Config File './data/conf/sshd.conf' Not Exist! Will Create A Template Config File..")
54
+		isinit = true
55
+		if _,err := Utils.CopyFile(path.Join(CurrentPath,"data","conf", "sshd.conf"),path.Join(CurrentPath,"sysfiles","conftpl", "sshd.conf"));err != nil {
56
+			fmt.Println("[StdOutLog][Fatal Error] Failed Copy Template Config File './data/conf/sshd.conf' : ",err)
57
+			return
58
+		}
59
+	}
60
+	// TODO: Other Config File Process Code Here
61
+	if(isinit){
62
+		fmt.Println("[StdOutLog][WARNING] At this time, we had created template config files for you, you should edit them and restart this server..")
63
+		fmt.Println("[StdOutLog][INFO] Server Exit.")
64
+		return
65
+	}
66
+	if Logger.LoadLoggerConfig(path.Join(CurrentPath,"data","conf", "logger.conf")) != nil{
67
+		return
68
+	}
69
+	if Logger.InitLogger() != nil {
70
+		return
71
+	}
72
+	fmt.Fprintln(&Logger.Log.SysInfo,"NSMC Server Launcher System Start.")
73
+	if err := Utils.MkDirIfNotExist(path.Join(CurrentPath,"data","keys")); err != nil {
74
+		fmt.Println("[StdOutLog][Fatal Error] Failed Create Dir '",path.Join(CurrentPath,"data","keys"),"' : ",err)
75
+		return
76
+	}
77
+	if SSHServer.LoadSSHConfig(path.Join(CurrentPath,"data","conf", "sshd.conf")) != nil{
78
+		return
79
+	}
80
+	fmt.Fprintln(&Logger.Log.SysInfo,"Regist Commands....")
81
+	Commands.RegistAllCommands()
82
+	fmt.Fprintln(&Logger.Log.SysInfo,"Start SSH Server...")
83
+	go SSHServer.StartSSHServer(MainThreadBlockChan)
84
+	<-MainThreadBlockChan
85
+}
86
+

+ 20 - 0
tools/bcryptGen/bcryptGen.go

@@ -0,0 +1,20 @@
1
+package main
2
+
3
+import (
4
+	"os"
5
+	"fmt"
6
+	"golang.org/x/crypto/bcrypt"
7
+)
8
+
9
+func main()  {
10
+	if len(os.Args) != 3{
11
+		fmt.Println("Usage: bcryptGen <username> <password>")
12
+		return
13
+	}
14
+	psb,err := bcrypt.GenerateFromPassword([]byte(os.Args[2]),10)
15
+	if(err != nil){
16
+		fmt.Println("Err: ",err.Error())
17
+		return
18
+	}
19
+	fmt.Printf("%s:%s",os.Args[1],string(psb))
20
+}