From eb9162d44bf62401e072ee2feef2cff41618e89a Mon Sep 17 00:00:00 2001 From: jolheiser Date: Mon, 6 Dec 2021 16:43:07 -0600 Subject: [PATCH] Initial Commit Signed-off-by: jolheiser --- LICENSE | 2 +- _hooks/mcm/mcm.go | 67 +++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 4 +-- go.sum | 33 ++++++++++++++++++++--- main.go | 26 ++++++++++++------ server/ping.go | 4 +-- server/server.go | 50 ++++++++++++++++++++++++----------- 7 files changed, 153 insertions(+), 33 deletions(-) create mode 100644 _hooks/mcm/mcm.go diff --git a/LICENSE b/LICENSE index 82b4eb1..8b9a29c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2020 Etzelia +Copyright 2021 John Olheiser Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/_hooks/mcm/mcm.go b/_hooks/mcm/mcm.go new file mode 100644 index 0000000..3661a0d --- /dev/null +++ b/_hooks/mcm/mcm.go @@ -0,0 +1,67 @@ +package main + +import ( + "encoding/json" + "flag" + "fmt" + "net/http" + "net/url" + "os" + "strings" + + "github.com/peterbourgon/ff/v3" +) + +type profile struct { + ID string `json:"id"` + Name string `json:"name"` + IP string `json:"ip"` +} + +func (p *profile) UUID() string { + return fmt.Sprintf("%s-%s-%s-%s-%s", p.ID[:8], p.ID[8:12], p.ID[12:16], p.ID[16:20], p.ID[20:32]) +} + +func main() { + fs := flag.NewFlagSet("mcm", flag.ExitOnError) + baseFlag := fs.String("base", "", "Base URL for MCM API") + tokenFlag := fs.String("token", "", "MCM API Token") + if err := ff.Parse(fs, os.Args[1:], + ff.WithEnvVarPrefix("MCM_REGISTER"), + ); err != nil { + panic(err) + } + + var profile profile + if err := json.NewDecoder(os.Stdin).Decode(&profile); err != nil { + panic(err) + } + + baseURL := strings.TrimSuffix(*baseFlag, "/") + + u := fmt.Sprintf("%s/plugin/register", baseURL) + resp, err := http.PostForm(u, url.Values{ + "api": []string{*tokenFlag}, + "uuid": []string{profile.UUID()}, + "username": []string{profile.Name}, + "ip": []string{profile.IP}, + }) + if err != nil { + panic(err) + } + + if resp.StatusCode != 200 { + panic("invalid response from MCM") + } + + s := struct { + Status bool `json:"status"` + Message string `json:"message"` + }{} + if err := json.NewDecoder(resp.Body).Decode(&s); err != nil { + panic(err) + } + defer resp.Body.Close() + + fmt.Println(s.Message) +} diff --git a/go.mod b/go.mod index 40dd5ef..5fba8c1 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module git.canopymc.net/Etzelia/mineauth +module git.jojodev.com/Canopy/mineauth go 1.16 @@ -6,5 +6,5 @@ require ( github.com/Tnze/go-mc v1.17.1-0.20210806203433-99081e1b9cfb github.com/google/uuid v1.1.1 github.com/peterbourgon/ff/v3 v3.1.0 - go.jolheiser.com/beaver v1.1.2 + github.com/rs/zerolog v1.26.0 ) diff --git a/go.sum b/go.sum index 3b4207c..3c0a511 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,10 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Tnze/go-mc v1.17.1-0.20210806203433-99081e1b9cfb h1:jf5lM8mkIpYLFF2cORRGYVK9Mv/xuomG1hmR0b4EzXU= github.com/Tnze/go-mc v1.17.1-0.20210806203433-99081e1b9cfb/go.mod h1:t0AI38F1BEmmy8/uLhr9RCOUeDbBj3oUNQH9akjzMc0= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/iancoleman/strcase v0.1.3 h1:dJBk1m2/qjL1twPLf68JND55vvivMupZ4wIzE8CTdBw= @@ -14,12 +16,35 @@ github.com/pelletier/go-toml v1.6.0 h1:aetoXYr0Tv7xRU/V4B4IZJ2QcbtMUFoNb3ORp7TzI github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= github.com/peterbourgon/ff/v3 v3.1.0 h1:5JAeDK5j/zhKFjyHEZQXwXBoDijERaos10RE+xamOsY= github.com/peterbourgon/ff/v3 v3.1.0/go.mod h1:XNJLY8EIl6MjMVjBS4F0+G0LYoAqs0DTa4rmHHukKDE= -go.jolheiser.com/beaver v1.1.2 h1:X8voMSTy+8QUFzHlvG89EUVZY/xPQe6fQLVjUPjTvWY= -go.jolheiser.com/beaver v1.1.2/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.26.0 h1:ORM4ibhEZeTeQlCojCK2kPz1ogAY4bGs4tD+SaAdGaE= +github.com/rs/zerolog v1.26.0/go.mod h1:yBiM87lvSqX8h0Ww4sdzNSkVYZ8dL2xjZJG1lAuGZEo= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go index 13885d4..ee74f7b 100644 --- a/main.go +++ b/main.go @@ -2,14 +2,16 @@ package main import ( "flag" - "git.canopymc.net/Etzelia/mineauth/server" "net/http" "os" "time" + "git.jojodev.com/Canopy/mineauth/server" + "github.com/peterbourgon/ff/v3" "github.com/peterbourgon/ff/v3/fftoml" - "go.jolheiser.com/beaver" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" ) func main() { @@ -18,23 +20,30 @@ func main() { timeoutFlag := fs.Int("timeout", 15, "HTTP timeout") pingMessageFlag := fs.String("ping", "Login to authenticate!", "Message for the server list") communityFlag := fs.String("community", "", "URL to community") + faviconFlag := fs.String("favicon", "", "Path to a favicon image for server list ping") hooksFlag := make([]string, 0) fs.Func("hook", "Hook to run", func(hook string) error { hooksFlag = append(hooksFlag, hook) return nil }) debugFlag := fs.Bool("debug", false, "Debug Logging") + jsonFlag := fs.Bool("json", false, "JSON Logging") if err := ff.Parse(fs, os.Args[1:], - ff.WithEnvVarPrefix("MCM_REGISTER"), + ff.WithEnvVarPrefix("MINEAUTH"), ff.WithConfigFileFlag("config"), ff.WithAllowMissingConfigFile(true), ff.WithConfigFileParser(fftoml.New().Parse), ); err != nil { - beaver.Fatal(err) + panic(err) return } + if *debugFlag { - beaver.Console.Level = beaver.DEBUG + zerolog.SetGlobalLevel(zerolog.DebugLevel) + } + + if !*jsonFlag { + log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stdout}) } http.DefaultClient.Timeout = time.Second * time.Duration(*timeoutFlag) @@ -42,15 +51,16 @@ func main() { serv, err := server.New(server.Options{ PingMessage: *pingMessageFlag, CommunityURL: *communityFlag, + FaviconPath: *faviconFlag, Hooks: hooksFlag, }) if err != nil { - beaver.Error(err) + log.Err(err).Msg("") return } - beaver.Infof("Listening on http://localhost:%d", *portFlag) + log.Info().Msgf("Listening on http://localhost:%d", *portFlag) if err := serv.Start(*portFlag); err != nil { - beaver.Error(err) + log.Err(err).Msg("") } } diff --git a/server/ping.go b/server/ping.go index 3c811ea..a6840c3 100644 --- a/server/ping.go +++ b/server/ping.go @@ -10,7 +10,7 @@ import ( "github.com/Tnze/go-mc/net" pk "github.com/Tnze/go-mc/net/packet" "github.com/google/uuid" - "go.jolheiser.com/beaver" + "github.com/rs/zerolog/log" ) func (s *Server) acceptListPing(conn net.Conn) { @@ -64,7 +64,7 @@ func (s *Server) listResp() string { data, err := json.Marshal(list) if err != nil { - beaver.Errorf("could not marshal JSON: %v", err) + log.Err(err).Msg("could not marshal JSON") } return string(data) } diff --git a/server/server.go b/server/server.go index 86ab2af..4eee33f 100644 --- a/server/server.go +++ b/server/server.go @@ -8,14 +8,17 @@ import ( _ "embed" "encoding/json" "fmt" + "io" + gonet "net" + "os" + "os/exec" + "strings" + "github.com/Tnze/go-mc/chat" "github.com/Tnze/go-mc/net" pk "github.com/Tnze/go-mc/net/packet" "github.com/google/uuid" - "go.jolheiser.com/beaver" - gonet "net" - "os/exec" - "strings" + "github.com/rs/zerolog/log" ) //go:embed favicon.png @@ -24,12 +27,14 @@ var favicon []byte type Server struct { privateKey *rsa.PrivateKey publicKey []byte + favicon []byte opts Options } type Options struct { CommunityURL string PingMessage string + FaviconPath string Hooks []string } @@ -46,9 +51,23 @@ func New(opts Options) (*Server, error) { private.Precompute() + icon := favicon + if opts.FaviconPath != "" { + fi, err := os.Open(opts.FaviconPath) + if err != nil { + return nil, err + } + defer fi.Close() + icon, err = io.ReadAll(fi) + if err != nil { + return nil, err + } + } + return &Server{ privateKey: private, publicKey: public, + favicon: icon, opts: opts, }, nil } @@ -62,7 +81,7 @@ func (s *Server) Start(port int) error { for { conn, err := l.Accept() if err != nil { - beaver.Errorf("Accept error: %v", err) + log.Err(err).Msg("accept error") } go s.acceptConn(conn) } @@ -73,13 +92,13 @@ func (s *Server) acceptConn(conn net.Conn) { // handshake _, intention, err := s.handshake(conn) if err != nil { - beaver.Errorf("Handshake error: %v", err) + log.Err(err).Msg("handshake error") return } switch intention { default: - beaver.Errorf("Unknown handshake intention: %v", intention) + log.Err(err).Msg("unknown handshake intention") case 1: s.acceptListPing(conn) case 2: @@ -90,31 +109,31 @@ func (s *Server) acceptConn(conn net.Conn) { func (s *Server) handlePlaying(conn net.Conn) { info, err := s.acceptLogin(conn) if err != nil { - beaver.Errorf("login failed: %v", err) + log.Err(err).Msg("login failed") return } verify, err := s.encryptionRequest(conn) if err != nil { - beaver.Errorf("could not send encryption request: %v", err) + log.Err(err).Msg("could not send encryption request") return } profile, secret, err := s.encryptionResponse(conn, info.Name, verify) if err != nil { - beaver.Errorf("could not get encryption response: %v", err) + log.Err(err).Msg("could not get encryption response") return } profile.IP, _, err = gonet.SplitHostPort(conn.Socket.RemoteAddr().String()) if err != nil { - beaver.Errorf("could not get user IP: %v", err) + log.Err(err).Msg("could not get user IP") return } payload, err := json.Marshal(profile) if err != nil { - beaver.Errorf("could not marshal payload: %v", err) + log.Err(err).Msg("could not marshal payload") return } @@ -129,15 +148,14 @@ func (s *Server) handlePlaying(conn net.Conn) { cmd.Stdin = bytes.NewReader(payload) out, err := cmd.CombinedOutput() if err != nil { - beaver.Errorf("could not run hook `%s`: %v", h, err) - beaver.Warn(string(out)) + log.Err(err).Str("hook", h).Str("output", string(out)).Msg("could not run hook") } }(hook) } econn, err := encryptedConn(conn, secret) if err != nil { - beaver.Errorf("could not create encrypted connection: %v", err) + log.Err(err).Msg("could not create encrypted connection") return } @@ -149,7 +167,7 @@ func (s *Server) handlePlaying(conn net.Conn) { chat.Message{Text: msg}, ) if err := packet.Pack(econn, 0); err != nil { - beaver.Errorf("could not disconnect player: %v", err) + log.Err(err).Msg("could not disconnect player") } }