parent
6155f28671
commit
eb9162d44b
2
LICENSE
2
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:
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
4
go.mod
4
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
|
||||
)
|
||||
|
|
33
go.sum
33
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=
|
||||
|
|
26
main.go
26
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("")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue