diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f655bb0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/exe/ diff --git a/build-all b/build-all index 1654c5a..ffc0eb3 100755 --- a/build-all +++ b/build-all @@ -1,3 +1,3 @@ #!/bin/sh -go build ./cmd/... +go build -o ./exe ./cmd/... diff --git a/cmd/shserver/main.go b/cmd/shserver/main.go index 858c617..84099e5 100644 --- a/cmd/shserver/main.go +++ b/cmd/shserver/main.go @@ -22,11 +22,11 @@ func main() { os.Exit(1) } - server, err := servers.NewServer(addr) + server, err := servers.NewServer(servers.ServerConfig{}) if err != nil { log.Fatalf("servers.New(...): %s\n", err) } log.Printf("Trying to serve at %q\n", addr) - server.ListenAndServe() + server.ListenAndServe(addr) } diff --git a/cmd/shutil/main.go b/cmd/shutil/main.go new file mode 100644 index 0000000..8e14dd4 --- /dev/null +++ b/cmd/shutil/main.go @@ -0,0 +1,36 @@ +package main + +import ( + "log" + "os" + + "surdeus.su/core/cli/mtool" + "surdeus.su/util/shelldoor/servers" +) + +var HashTool = mtool.T("hash"). + Func(func(flags *mtool.Flags) { + passwords := flags.Parse() + if len(passwords) < 1 { + flags.Usage() + os.Exit(1) + } + for _, password := range passwords { + hash, err := servers.HashPassword( + servers.Password(password), + ) + if err != nil { + log.Printf("HashPassword(...): %s\n", err) + continue + } + log.Printf("%s\n", hash) + } + }) + +var Tool = mtool.T("shutil").Subs( + HashTool, +) + +func main() { + Tool.Run(os.Args[1:]) +} diff --git a/go.mod b/go.mod index 96317b2..630a0de 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,8 @@ module surdeus.su/util/shelldoor go 1.22.7 + +require ( + golang.org/x/crypto v0.27.0 + surdeus.su/core/cli v0.8.0 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..3f90ccc --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +surdeus.su/core/cli v0.8.0 h1:HGmRqWl6W5DxFX1nVkUpS+cK0BgYYJdYrZY3VTq3C4k= +surdeus.su/core/cli v0.8.0/go.mod h1:r9JtQz3aEJzpYzMaNUNQHJoYkoWKNPi047qhd5uGlmA= diff --git a/servers/client.go b/servers/client.go index f5149fb..f31def7 100644 --- a/servers/client.go +++ b/servers/client.go @@ -2,10 +2,19 @@ package servers import "net" +// The type represents authentication request +// from clients. +type ClientAuthRequest struct { + Login Login + Password Password +} + +// The type represents the controlling client. type Client struct { conn net.Conn } +// Returns the new client on the specified connection. func NewClient(conn net.Conn) *Client { ret := &Client{} ret.conn = conn diff --git a/servers/config.go b/servers/config.go new file mode 100644 index 0000000..83878b8 --- /dev/null +++ b/servers/config.go @@ -0,0 +1,20 @@ +package servers + +// The type represents unique bot authentication +// token which is needed to connect to the bot net. +type BotAuthToken int64 + +// More or less secure storage for passwords +// identifying them by login. +type PasswordMap map[Login]PasswordHash + +// The type represents sever configuration. +type ServerConfig struct { + // The map stores clients that can login + // and the credentials. + Auth PasswordMap `json:"auth"` + + // The token must be unique so only + // needed bots can join the bot net. + BotAuthToken BotAuthToken `json:"bot_auth_token"` +} diff --git a/servers/hash.go b/servers/hash.go new file mode 100644 index 0000000..4e9f69f --- /dev/null +++ b/servers/hash.go @@ -0,0 +1,24 @@ +package servers + +import "golang.org/x/crypto/bcrypt" + +// The type represents login used to login. +type Login string + +// The type represents passwords used to login. +type Password string + +// The type represents hash of the password. +type PasswordHash string + +// Simple hashing password function. +func HashPassword(password Password) (PasswordHash, error) { + bts, err := bcrypt.GenerateFromPassword([]byte(password), 14) + return PasswordHash(bts), err +} + +// Check for password to match the hash. +func PasswordMatchHash(password Password, hash PasswordHash) bool { + err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) + return err == nil +} diff --git a/servers/server.go b/servers/server.go index 04fc3db..98635b5 100644 --- a/servers/server.go +++ b/servers/server.go @@ -5,43 +5,41 @@ import ( "net" ) -type BotRequest struct { -} - -type BotResponse struct { -} - -type ClientRequest struct { -} - -type ClientResponse struct { - Error string - Text string -} - +// The type represents server that connects +// clients and the bots together. type Server struct { addr string listenner net.Listener bots []*Bot clients []*Client + config ServerConfig } -func NewServer(addr string) (*Server, error) { +// Returns the new server with the specified configuration. +func NewServer(config ServerConfig) (*Server, error) { srv := &Server{} - srv.addr = addr + srv.config = config return srv, nil } +// The method handles the specified connection +// checking out if it is client or a bot. func (srv *Server) HandleConn(conn net.Conn) { defer conn.Close() + + for { + + } } -func (srv *Server) ListenAndServe() error { +// Start listening and serve both clients and bots. +func (srv *Server) ListenAndServe(addr string) error { var err error - srv.listenner, err = net.Listen("tcp", srv.addr) + srv.listenner, err = net.Listen("tcp", addr) if err != nil { return err } + srv.addr = addr for { conn, err := srv.listenner.Accept()