@@ -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> |
@@ -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 |
+} |
@@ -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 |
+} |
@@ -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 |
+} |
@@ -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 |
+} |
@@ -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 |
+} |
@@ -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 |
+} |
@@ -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 |
+} |
@@ -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 |
+} |
@@ -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 |
+} |
@@ -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 |
+} |
@@ -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 |
@@ -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. |
@@ -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 |
+ |
@@ -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 |
+} |