123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- package SSHServer
- import (
- "git.swzry.com/NSMCServerLauncher/Utils"
- "fmt"
- "git.swzry.com/NSMCServerLauncher/Logger"
- "crypto/rsa"
- "crypto/rand"
- "crypto/x509"
- "encoding/pem"
- "os"
- "golang.org/x/crypto/ssh"
- "io/ioutil"
- "net"
- "github.com/swzry/go.TSmap"
- "golang.org/x/crypto/ssh/terminal"
- "git.swzry.com/NSMCServerLauncher/Terminal"
- "golang.org/x/crypto/bcrypt"
- )
- var mainThreadBlockChan chan byte
- var ServerConf *ssh.ServerConfig
- var _clientListRawMap map[interface{}]interface{}
- var ClientList TSmap.TSmap
- func StartSSHServer(mtbc chan byte) {
- mainThreadBlockChan = mtbc
- if r,err := Utils.PathExists(SSHServerConf.host_key_file); ((!r) || (err != nil)) {
- fmt.Fprintln(&Logger.Log.SysInfo,"Generating SSH Host Key......")
- fmt.Fprintln(&Logger.Log.SysInfo,"(It may takes a long time. Please wait.)")
- fmt.Println("Generating SSH Host Key......")
- fmt.Println("(It may takes a long time. Please wait.)")
- GenerateRSAKey(SSHServerConf.host_key_file, SSHServerConf.defult_key_length)
- }
- ServerConf = &ssh.ServerConfig{
- NoClientAuth: false,
- MaxAuthTries: SSHServerConf.max_auth_tries,
- PasswordCallback: SSHPasswordCallback,
- PublicKeyCallback: SSHPublicKeyCallback,
- AuthLogCallback: SSHAuthLogCallback,
- ServerVersion: "SSH-2.0-NSMCServerLauncher-SSH",
- }
- keyBytes, err := ioutil.ReadFile(SSHServerConf.host_key_file)
- if(err != nil){
- fmt.Fprintln(&Logger.Log.SysFatal,"Failed to Load Host Key File: ", err)
- mainThreadBlockChan <- 1
- return
- }
- key, err := ssh.ParsePrivateKey(keyBytes)
- if(err != nil){
- fmt.Fprintln(&Logger.Log.SysFatal,"Failed to Load Host Key: ", err)
- mainThreadBlockChan <- 1
- return
- }
- ServerConf.AddHostKey(key)
- listener,err := net.Listen("tcp", SSHServerConf.bind_addr)
- if(err != nil){
- fmt.Fprintln(&Logger.Log.SysFatal,"Failed to Bind Address '",SSHServerConf.bind_addr,"': ", err)
- mainThreadBlockChan <- 1
- return
- }
- fmt.Fprintln(&Logger.Log.SysInfo,"Listening At '",listener.Addr().String(),"'.")
- _clientListRawMap = make(map[interface{}]interface{})
- ClientList = &TSmap.NewTSmap{
- ConMap:_clientListRawMap,
- }
- for{
- tcpConn,err := listener.Accept()
- if(err == nil){
- fmt.Fprintf(&Logger.Log.SSH,"New Client '%v' Entered.\n",tcpConn.RemoteAddr())
- _, schan, reqchan, err := ssh.NewServerConn(tcpConn, ServerConf)
- if(err != nil){
- fmt.Fprintf(&Logger.Log.SSH,"Failed Handle Client '%v': %v\n",tcpConn.RemoteAddr(),err)
- tcpConn.Close()
- continue
- }else {
- ClientList.Set(tcpConn,&Utils.ClientConnection{
- Channels: &TSmap.NewTSmap{
- ConMap:make(map[interface{}]interface{}),
- },
- })
- go ssh.DiscardRequests(reqchan)
- go handleChannels(schan, tcpConn)
- }
- }
- }
- }
- func handleChannels(ch <-chan ssh.NewChannel, conn net.Conn) {
- cnt := 0
- chlist,ok := ClientList.Get(conn)
- if(!ok){
- fmt.Fprintf(&Logger.Log.SSH,"Failed Handle Client '%v': Channels Not Found.\n",conn.RemoteAddr())
- }
- for newchan := range ch {
- cnt++;
- fmt.Fprintf(&Logger.Log.SSH,"Client '%v', Channels %v, Handling.\n",conn.RemoteAddr(),cnt)
- go handleChannel(newchan,conn,cnt,chlist.(*Utils.ClientConnection))
- }
- }
- func handleChannel(nch ssh.NewChannel,conn net.Conn,num int,chlist *Utils.ClientConnection) {
- if(nch.ChannelType() == "session"){
- ch,req,err := nch.Accept()
- if(err != nil){
- fmt.Fprintf(&Logger.Log.SSH,"Client '%v', Channels %v, Failed Handling : %v\n",conn.RemoteAddr(),num,err)
- return
- }else{
- r:= <-req
- r.Reply(true,nil)
- chlist.Channels.Set(num,Utils.AvaliableChannel{
- Channel: ch,
- Term: terminal.NewTerminal(ch,"NSMC >"),
- UserContext: Utils.UserContextType{
- PWD: "/",
- },
- })
- go Terminal.HandlerTerminal(ClientList,conn, num)
- }
- }else{
- nch.Reject(ssh.UnknownChannelType, "Unknown Channel Type")
- fmt.Fprintf(&Logger.Log.SSH,"Client '%v', Channels %v, Rejected : Unknown Channel Type '%v'\n",conn.RemoteAddr(),num,nch.ChannelType())
- }
- }
- func SSHPasswordCallback(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
- val, ok := SSHServerConf.passwd[conn.User()]
- if(!ok){
- fmt.Fprintf(&Logger.Log.SSH,"Client '%v' Auth Failed : Unknown User '%v'\n",conn.RemoteAddr(),conn.User())
- return nil,fmt.Errorf("Password Error or User '%v' Does Not Exist..",conn.User())
- }
- err := bcrypt.CompareHashAndPassword([]byte(val),password)
- if(err != nil){
- fmt.Fprintf(&Logger.Log.SSH,"Client '%v', User '%v', Auth Failed : Password Error, Detail: '%v'\n",conn.RemoteAddr(),conn.User(),err)
- return nil,fmt.Errorf("Password Error or User '%v' Does Not Exist..",conn.User())
- }
- return nil,nil
- }
- func SSHPublicKeyCallback(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error){
- return nil,fmt.Errorf("PublicKey Auth Not Support Yet.")
- }
- func SSHAuthLogCallback(conn ssh.ConnMetadata, method string, err error){
- fmt.Fprintf(&Logger.Log.SSH,"AuthFailed. Info: client='%v', user='%v', method='%v'. Err: %v\n",conn.RemoteAddr(),conn.User(),method,err)
- }
- func GenerateRSAKey(keyfn string,keyLength int) {
- privateKey, err := rsa.GenerateKey(rand.Reader, keyLength)
- if err != nil {
- fmt.Fprintln(&Logger.Log.SysFatal,"Failed to Generate RSA Private Key: ", err)
- mainThreadBlockChan <- 1
- return
- }
- derStream := x509.MarshalPKCS1PrivateKey(privateKey)
- block := &pem.Block{
- Type: "RSA PRIVATE KEY",
- Bytes: derStream,
- }
- file, err := os.Create(keyfn)
- if err != nil {
- fmt.Fprintln(&Logger.Log.SysFatal,"Failed to Create Key File: ", err)
- mainThreadBlockChan <- 1
- return
- }
- err = pem.Encode(file, block)
- if err != nil {
- fmt.Fprintln(&Logger.Log.SysFatal,"Failed to Encode Key: ", err)
- mainThreadBlockChan <- 1
- return
- }
- fmt.Fprintln(&Logger.Log.SysInfo,"SSH Host Key Generated Successfully..")
- fmt.Println("SSH Host Key Generated Successfully..")
- }
|