2021-01-24 05:00:26 -08:00
|
|
|
package main
|
2021-01-09 13:01:36 -08:00
|
|
|
|
|
|
|
import (
|
2021-03-29 09:57:30 -07:00
|
|
|
"bytes"
|
2021-01-09 13:01:36 -08:00
|
|
|
"crypto/subtle"
|
|
|
|
"encoding/binary"
|
2021-03-02 08:47:07 -08:00
|
|
|
"errors"
|
2021-03-29 09:57:30 -07:00
|
|
|
"io"
|
2021-01-09 13:01:36 -08:00
|
|
|
"log"
|
2021-01-20 12:44:35 -08:00
|
|
|
"net"
|
2021-01-09 13:01:36 -08:00
|
|
|
"strings"
|
|
|
|
"time"
|
2021-01-18 13:08:22 -08:00
|
|
|
|
|
|
|
"github.com/HimbeerserverDE/srp"
|
|
|
|
"github.com/anon55555/mt/rudp"
|
2021-01-09 13:01:36 -08:00
|
|
|
)
|
|
|
|
|
2021-03-29 13:20:12 -07:00
|
|
|
// Init completes the initialisation of a connection to a server or client c2
|
2021-03-29 09:57:30 -07:00
|
|
|
func Init(c, c2 *Conn, ignMedia, noAccessDenied bool, fin chan *Conn) {
|
2021-01-09 13:01:36 -08:00
|
|
|
defer close(fin)
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
if c2.IsSrv() {
|
2021-01-09 13:01:36 -08:00
|
|
|
// We're trying to connect to a server
|
|
|
|
// INIT
|
2021-03-29 09:57:30 -07:00
|
|
|
data := make([]byte, 11+len(c.Username()))
|
2021-01-09 13:01:36 -08:00
|
|
|
data[0] = uint8(0x00)
|
2021-01-19 11:37:35 -08:00
|
|
|
data[1] = uint8(ToServerInit)
|
2021-01-09 13:01:36 -08:00
|
|
|
data[2] = uint8(0x1c)
|
|
|
|
binary.BigEndian.PutUint16(data[3:5], uint16(0x0000))
|
2021-03-13 08:15:07 -08:00
|
|
|
binary.BigEndian.PutUint16(data[5:7], uint16(ProtoMin))
|
|
|
|
binary.BigEndian.PutUint16(data[7:9], uint16(ProtoLatest))
|
2021-03-29 09:57:30 -07:00
|
|
|
binary.BigEndian.PutUint16(data[9:11], uint16(len(c.Username())))
|
|
|
|
copy(data[11:], []byte(c.Username()))
|
2021-01-09 13:01:36 -08:00
|
|
|
|
|
|
|
time.Sleep(250 * time.Millisecond)
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
if _, err := c2.Send(rudp.Pkt{
|
|
|
|
Reader: bytes.NewReader(data),
|
|
|
|
PktInfo: rudp.PktInfo{
|
|
|
|
Channel: 1,
|
|
|
|
Unrel: true,
|
|
|
|
},
|
|
|
|
}); err != nil {
|
2021-01-09 13:01:36 -08:00
|
|
|
log.Print(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for {
|
2021-03-29 09:57:30 -07:00
|
|
|
pkt, err := c2.Recv()
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
2021-03-02 08:47:07 -08:00
|
|
|
if errors.Is(err, net.ErrClosed) {
|
2021-03-29 09:57:30 -07:00
|
|
|
if err = c2.WhyClosed(); err != nil {
|
|
|
|
log.Print(c2.Addr().String(), " disconnected with error: ", err)
|
|
|
|
} else {
|
|
|
|
log.Print(c2.Addr().String(), " disconnected")
|
2021-01-09 13:01:36 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
r := ByteReader(pkt)
|
|
|
|
|
2021-04-01 14:10:31 -07:00
|
|
|
switch cmd := ReadUint16(r); cmd {
|
2021-01-14 10:06:40 -08:00
|
|
|
case ToClientHello:
|
2021-03-29 09:57:30 -07:00
|
|
|
r.Seek(5, io.SeekStart)
|
2021-04-01 14:10:31 -07:00
|
|
|
c2.protoVer = ReadUint16(r)
|
2021-03-29 09:57:30 -07:00
|
|
|
r.Seek(10, io.SeekStart)
|
2021-04-01 14:10:31 -07:00
|
|
|
authMech := ReadUint8(r)
|
2021-03-13 08:15:07 -08:00
|
|
|
|
2021-04-01 14:10:31 -07:00
|
|
|
if authMech&AuthMechSRP > 0 {
|
2021-01-09 13:01:36 -08:00
|
|
|
// Compute and send SRP_BYTES_A
|
2021-03-29 09:57:30 -07:00
|
|
|
_, _, err := srp.NewClient([]byte(strings.ToLower(c.Username())), passPhrase)
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
A, a, err := srp.InitiateHandshake()
|
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
c.srp_A = A
|
|
|
|
c.srp_a = a
|
2021-01-09 13:01:36 -08:00
|
|
|
|
2021-04-01 14:10:31 -07:00
|
|
|
w := bytes.NewBuffer([]byte{0x00, ToServerSrpBytesA})
|
|
|
|
WriteBytes16(w, c.srp_A)
|
|
|
|
WriteUint8(w, 1)
|
2021-03-29 09:57:30 -07:00
|
|
|
|
|
|
|
ack, err := c2.Send(rudp.Pkt{
|
2021-04-01 14:10:31 -07:00
|
|
|
Reader: w,
|
2021-03-29 09:57:30 -07:00
|
|
|
PktInfo: rudp.PktInfo{
|
|
|
|
Channel: 1,
|
|
|
|
},
|
|
|
|
})
|
2021-01-09 13:01:36 -08:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
<-ack
|
|
|
|
} else {
|
|
|
|
// Compute and send s and v
|
2021-03-29 09:57:30 -07:00
|
|
|
s, v, err := srp.NewClient([]byte(strings.ToLower(c.Username())), passPhrase)
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-04-01 14:10:31 -07:00
|
|
|
w := bytes.NewBuffer([]byte{0x00, ToServerFirstSrp})
|
|
|
|
WriteBytes16(w, s)
|
|
|
|
WriteBytes16(w, v)
|
|
|
|
WriteUint8(w, 0)
|
2021-01-09 13:01:36 -08:00
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
ack, err := c2.Send(rudp.Pkt{
|
2021-04-02 02:53:19 -07:00
|
|
|
Reader: w,
|
2021-03-29 09:57:30 -07:00
|
|
|
PktInfo: rudp.PktInfo{
|
|
|
|
Channel: 1,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
<-ack
|
|
|
|
}
|
2021-01-14 10:06:40 -08:00
|
|
|
case ToClientSrpBytesSB:
|
2021-01-09 13:01:36 -08:00
|
|
|
// Compute and send SRP_BYTES_M
|
2021-04-01 14:10:31 -07:00
|
|
|
s := ReadBytes16(r)
|
2021-03-29 09:57:30 -07:00
|
|
|
r.Seek(2, io.SeekCurrent)
|
|
|
|
B := make([]byte, r.Len())
|
|
|
|
r.Read(B)
|
|
|
|
|
|
|
|
K, err := srp.CompleteHandshake(c.srp_A, c.srp_a, []byte(strings.ToLower(c.Username())), passPhrase, s, B)
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
c.srp_K = K
|
2021-01-09 13:01:36 -08:00
|
|
|
|
2021-03-31 10:27:50 -07:00
|
|
|
M := srp.ClientProof([]byte(c.Username()), s, c.srp_A, B, c.srp_K)
|
2021-01-09 13:01:36 -08:00
|
|
|
|
2021-04-01 14:10:31 -07:00
|
|
|
w := bytes.NewBuffer([]byte{0x00, ToServerSrpBytesM})
|
|
|
|
WriteBytes16(w, M)
|
2021-01-09 13:01:36 -08:00
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
ack, err := c2.Send(rudp.Pkt{
|
2021-04-02 02:53:19 -07:00
|
|
|
Reader: w,
|
2021-03-29 09:57:30 -07:00
|
|
|
PktInfo: rudp.PktInfo{
|
|
|
|
Channel: 1,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
<-ack
|
2021-01-14 10:06:40 -08:00
|
|
|
case ToClientAccessDenied:
|
2021-01-09 13:01:36 -08:00
|
|
|
// Auth failed for some reason
|
2021-03-09 13:23:41 -08:00
|
|
|
servers := ConfKey("servers").(map[interface{}]interface{})
|
2021-03-02 08:21:43 -08:00
|
|
|
var srv string
|
|
|
|
for server := range servers {
|
2021-03-29 09:57:30 -07:00
|
|
|
if ConfKey("servers:"+server.(string)+":address") == c2.Addr().String() {
|
2021-03-02 08:21:43 -08:00
|
|
|
srv = server.(string)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Print("authentication failed for server " + srv)
|
2021-01-09 13:01:36 -08:00
|
|
|
|
2021-01-16 10:14:31 -08:00
|
|
|
if noAccessDenied {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-01-09 13:01:36 -08:00
|
|
|
data := []byte{
|
2021-01-19 11:37:35 -08:00
|
|
|
0, ToClientAccessDenied,
|
|
|
|
AccessDeniedServerFail, 0, 0, 0, 0,
|
2021-01-09 13:01:36 -08:00
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
ack, err := c.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
}
|
|
|
|
<-ack
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
c.Close()
|
2021-01-09 13:01:36 -08:00
|
|
|
return
|
2021-01-14 10:06:40 -08:00
|
|
|
case ToClientAuthAccept:
|
2021-01-09 13:01:36 -08:00
|
|
|
// Auth succeeded
|
2021-03-14 05:52:31 -07:00
|
|
|
defer func() {
|
2021-03-29 09:57:30 -07:00
|
|
|
fin <- c2
|
2021-03-14 05:52:31 -07:00
|
|
|
}()
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
ack, err := c2.Send(rudp.Pkt{
|
|
|
|
Reader: bytes.NewReader([]byte{0, ToServerInit2, 0, 0}),
|
|
|
|
PktInfo: rudp.PktInfo{
|
|
|
|
Channel: 1,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
<-ack
|
|
|
|
|
|
|
|
if !ignMedia {
|
|
|
|
return
|
|
|
|
}
|
2021-01-14 10:06:40 -08:00
|
|
|
case ToClientCsmRestrictionFlags:
|
2021-01-09 13:01:36 -08:00
|
|
|
// Definitions sent (by server)
|
|
|
|
if !ignMedia {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
v := []byte("5.4.0-dev-dd5a732fa")
|
|
|
|
|
2021-04-01 14:10:31 -07:00
|
|
|
w := bytes.NewBuffer([]byte{0x00, ToServerClientReady})
|
|
|
|
w.Write([]byte{5, 4, 0, 0})
|
|
|
|
WriteBytes16(w, v)
|
2021-01-09 13:01:36 -08:00
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
_, err := c2.Send(rudp.Pkt{
|
2021-04-02 03:38:46 -07:00
|
|
|
Reader: w,
|
2021-03-29 09:57:30 -07:00
|
|
|
PktInfo: rudp.PktInfo{
|
|
|
|
Channel: 1,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2021-03-29 13:20:12 -07:00
|
|
|
// We're trying to initialize a client
|
2021-01-09 13:01:36 -08:00
|
|
|
for {
|
2021-03-29 09:57:30 -07:00
|
|
|
pkt, err := c2.Recv()
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
2021-03-02 08:47:07 -08:00
|
|
|
if errors.Is(err, net.ErrClosed) {
|
2021-03-29 09:57:30 -07:00
|
|
|
if err = c2.WhyClosed(); err != nil {
|
|
|
|
log.Print(c2.Addr().String(), " disconnected with error: ", err)
|
|
|
|
} else {
|
|
|
|
log.Print(c2.Addr().String(), " disconnected")
|
2021-01-09 13:01:36 -08:00
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
connectedConnsMu.Lock()
|
|
|
|
connectedConns--
|
|
|
|
connectedConnsMu.Unlock()
|
2021-01-10 13:37:42 -08:00
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
processLeave(c2)
|
2021-01-09 13:01:36 -08:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
r := ByteReader(pkt)
|
|
|
|
|
2021-04-01 14:10:31 -07:00
|
|
|
switch cmd := ReadUint16(r); cmd {
|
2021-01-14 10:06:40 -08:00
|
|
|
case ToServerInit:
|
2021-01-09 13:01:36 -08:00
|
|
|
// Process data
|
2021-04-02 03:38:46 -07:00
|
|
|
r.Seek(9, io.SeekStart)
|
2021-04-01 14:10:31 -07:00
|
|
|
c2.username = string(ReadBytes16(r))
|
2021-03-29 09:57:30 -07:00
|
|
|
r.Seek(5, io.SeekStart)
|
2021-01-09 13:01:36 -08:00
|
|
|
|
2021-03-13 08:15:07 -08:00
|
|
|
// Find protocol version
|
2021-04-01 14:10:31 -07:00
|
|
|
cliProtoMin := ReadUint16(r)
|
|
|
|
cliProtoMax := ReadUint16(r)
|
2021-03-29 09:57:30 -07:00
|
|
|
|
2021-03-13 08:15:07 -08:00
|
|
|
var protov uint16
|
|
|
|
if cliProtoMax >= ProtoMin || cliProtoMin <= ProtoLatest {
|
|
|
|
if cliProtoMax > ProtoLatest {
|
|
|
|
protov = ProtoLatest
|
|
|
|
} else {
|
|
|
|
protov = ProtoLatest
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
c2.protoVer = protov
|
2021-03-13 08:15:07 -08:00
|
|
|
|
2021-03-29 13:20:12 -07:00
|
|
|
if strict, ok := ConfKey("force_latest_proto").(bool); (ok && strict) && (protov != ProtoLatest) || protov < ProtoMin || protov > ProtoLatest {
|
2021-03-13 08:15:07 -08:00
|
|
|
data := []byte{
|
|
|
|
0, ToClientAccessDenied,
|
|
|
|
AccessDeniedWrongVersion, 0, 0, 0, 0,
|
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
ack, err := c2.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
|
2021-03-13 08:15:07 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
}
|
|
|
|
<-ack
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
c2.Close()
|
|
|
|
fin <- c
|
2021-03-13 08:15:07 -08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-01-09 13:01:36 -08:00
|
|
|
// Send HELLO
|
2021-03-29 09:57:30 -07:00
|
|
|
data := make([]byte, 13+len(c2.Username()))
|
2021-01-09 13:01:36 -08:00
|
|
|
data[0] = uint8(0x00)
|
2021-01-14 10:06:40 -08:00
|
|
|
data[1] = uint8(ToClientHello)
|
2021-01-09 13:01:36 -08:00
|
|
|
data[2] = uint8(0x1c)
|
|
|
|
binary.BigEndian.PutUint16(data[3:5], uint16(0x0000))
|
2021-03-13 08:15:07 -08:00
|
|
|
binary.BigEndian.PutUint16(data[5:7], uint16(protov))
|
2021-01-09 13:01:36 -08:00
|
|
|
|
2021-02-28 04:12:28 -08:00
|
|
|
// Check if user is banned
|
2021-03-29 09:57:30 -07:00
|
|
|
banned, bname, err := c2.IsBanned()
|
2021-02-28 04:12:28 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if banned {
|
2021-03-29 09:57:30 -07:00
|
|
|
log.Print("Banned user " + bname + " at " + c2.Addr().String() + " tried to connect")
|
2021-03-02 08:02:25 -08:00
|
|
|
|
2021-02-28 04:12:28 -08:00
|
|
|
reason := []byte("Your IP address is banned. Banned name is " + bname)
|
|
|
|
|
2021-04-01 14:10:31 -07:00
|
|
|
w := bytes.NewBuffer([]byte{0x00, ToClientAccessDenied})
|
|
|
|
WriteUint8(w, AccessDeniedCustomString)
|
|
|
|
WriteBytes16(w, reason)
|
|
|
|
WriteUint8(w, 0)
|
2021-02-28 04:12:28 -08:00
|
|
|
|
2021-04-01 14:10:31 -07:00
|
|
|
ack, err := c2.Send(rudp.Pkt{Reader: w})
|
2021-02-28 04:12:28 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
}
|
|
|
|
<-ack
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
c2.Close()
|
|
|
|
fin <- c
|
2021-02-28 04:12:28 -08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-01-14 10:06:40 -08:00
|
|
|
// Check if user is already connected
|
2021-03-29 09:57:30 -07:00
|
|
|
if IsOnline(c2.Username()) {
|
2021-01-14 10:06:40 -08:00
|
|
|
data := []byte{
|
2021-01-19 11:37:35 -08:00
|
|
|
0, ToClientAccessDenied,
|
|
|
|
AccessDeniedAlreadyConnected, 0, 0, 0, 0,
|
2021-01-14 10:06:40 -08:00
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
ack, err := c2.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
|
2021-01-14 10:06:40 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
<-ack
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
c2.Close()
|
|
|
|
fin <- c
|
2021-01-14 10:06:40 -08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-01-29 07:21:43 -08:00
|
|
|
// Check if username is reserved for media or RPC
|
2021-03-29 09:57:30 -07:00
|
|
|
if c2.Username() == "media" || c2.Username() == "rpc" {
|
2021-01-29 07:21:43 -08:00
|
|
|
data := []byte{
|
|
|
|
0, ToClientAccessDenied,
|
|
|
|
AccessDeniedWrongName, 0, 0, 0, 0,
|
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
ack, err := c2.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
|
2021-01-29 07:21:43 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
<-ack
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
c2.Close()
|
|
|
|
fin <- c
|
2021-01-29 07:21:43 -08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-01-09 13:01:36 -08:00
|
|
|
db, err := initAuthDB()
|
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
pwd, err := readAuthItem(db, c2.Username())
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
db.Close()
|
|
|
|
|
|
|
|
if pwd == "" {
|
|
|
|
// New player
|
2021-03-29 09:57:30 -07:00
|
|
|
c2.authMech = AuthMechFirstSRP
|
2021-01-09 13:01:36 -08:00
|
|
|
binary.BigEndian.PutUint32(data[7:11], uint32(AuthMechFirstSRP))
|
|
|
|
} else {
|
|
|
|
// Existing player
|
2021-03-29 09:57:30 -07:00
|
|
|
c2.authMech = AuthMechSRP
|
2021-01-09 13:01:36 -08:00
|
|
|
binary.BigEndian.PutUint32(data[7:11], uint32(AuthMechSRP))
|
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
binary.BigEndian.PutUint16(data[11:13], uint16(len(c2.Username())))
|
|
|
|
copy(data[13:], []byte(c2.Username()))
|
2021-01-09 13:01:36 -08:00
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
ack, err := c2.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
<-ack
|
2021-01-14 10:06:40 -08:00
|
|
|
case ToServerFirstSrp:
|
2021-01-09 13:01:36 -08:00
|
|
|
// Process data
|
|
|
|
// Make sure the client is allowed to use AuthMechFirstSRP
|
2021-03-29 09:57:30 -07:00
|
|
|
if c2.authMech != AuthMechFirstSRP {
|
|
|
|
log.Print(c2.Addr().String() + " used unsupported AuthMechFirstSRP")
|
2021-01-09 13:01:36 -08:00
|
|
|
|
|
|
|
// Send ACCESS_DENIED
|
|
|
|
data := []byte{
|
2021-01-19 11:37:35 -08:00
|
|
|
0, ToClientAccessDenied,
|
|
|
|
AccessDeniedUnexpectedData, 0, 0, 0, 0,
|
2021-01-09 13:01:36 -08:00
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
ack, err := c2.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
<-ack
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
c2.Close()
|
|
|
|
fin <- c
|
2021-01-09 13:01:36 -08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is a new player, save verifier and salt
|
2021-04-01 14:10:31 -07:00
|
|
|
s := ReadBytes16(r)
|
|
|
|
v := ReadBytes16(r)
|
2021-03-29 09:57:30 -07:00
|
|
|
|
2021-04-01 14:10:31 -07:00
|
|
|
empty := ReadUint8(r)
|
2021-01-09 13:01:36 -08:00
|
|
|
|
2021-03-07 01:12:25 -08:00
|
|
|
// Also make sure to check for an empty password
|
2021-03-09 13:23:41 -08:00
|
|
|
disallow, ok := ConfKey("disallow_empty_passwords").(bool)
|
2021-04-01 14:10:31 -07:00
|
|
|
if ok && disallow && empty > 0 {
|
2021-03-29 09:57:30 -07:00
|
|
|
log.Print(c2.Addr().String() + " used an empty password but disallow_empty_passwords is true")
|
2021-03-07 01:12:25 -08:00
|
|
|
|
|
|
|
// Send ACCESS_DENIED
|
|
|
|
data := []byte{
|
|
|
|
0, ToClientAccessDenied,
|
|
|
|
AccessDeniedEmptyPassword, 0, 0, 0, 0,
|
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
ack, err := c2.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
|
2021-03-07 01:12:25 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
<-ack
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
c2.Close()
|
|
|
|
fin <- c
|
2021-03-07 01:12:25 -08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-01-09 13:01:36 -08:00
|
|
|
pwd := encodeVerifierAndSalt(s, v)
|
|
|
|
|
|
|
|
db, err := initAuthDB()
|
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
err = addAuthItem(db, c2.Username(), pwd)
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
err = addPrivItem(db, c2.Username())
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
db.Close()
|
|
|
|
|
|
|
|
// Send AUTH_ACCEPT
|
|
|
|
data := []byte{
|
2021-01-19 11:37:35 -08:00
|
|
|
0, ToClientAuthAccept,
|
2021-01-09 13:01:36 -08:00
|
|
|
// Position stuff
|
2021-01-19 11:37:35 -08:00
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
2021-01-09 13:01:36 -08:00
|
|
|
// Map seed
|
2021-01-19 11:37:35 -08:00
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
2021-01-09 13:01:36 -08:00
|
|
|
// Send interval
|
2021-01-19 11:37:35 -08:00
|
|
|
0x3D, 0xB8, 0x51, 0xEC,
|
2021-01-09 13:01:36 -08:00
|
|
|
// Sudo mode mechs
|
2021-01-19 11:37:35 -08:00
|
|
|
0, 0, 0, AuthMechSRP,
|
2021-01-09 13:01:36 -08:00
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
ack, err := c2.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
<-ack
|
2021-01-14 10:06:40 -08:00
|
|
|
case ToServerSrpBytesA:
|
2021-01-09 13:01:36 -08:00
|
|
|
// Process data
|
|
|
|
// Make sure the client is allowed to use AuthMechSRP
|
2021-03-29 09:57:30 -07:00
|
|
|
if c2.authMech != AuthMechSRP {
|
|
|
|
log.Print(c2.Addr().String() + " used unsupported AuthMechSRP")
|
2021-01-09 13:01:36 -08:00
|
|
|
|
|
|
|
// Send ACCESS_DENIED
|
|
|
|
data := []byte{
|
2021-01-19 11:37:35 -08:00
|
|
|
0, ToClientAccessDenied,
|
|
|
|
AccessDeniedUnexpectedData, 0, 0, 0, 0,
|
2021-01-09 13:01:36 -08:00
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
ack, err := c2.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
|
|
|
|
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
<-ack
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
c2.Close()
|
2021-01-09 13:01:36 -08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-04-01 14:10:31 -07:00
|
|
|
A := ReadBytes16(r)
|
2021-01-09 13:01:36 -08:00
|
|
|
|
|
|
|
db, err := initAuthDB()
|
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
pwd, err := readAuthItem(db, c2.Username())
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
db.Close()
|
|
|
|
|
|
|
|
s, v, err := decodeVerifierAndSalt(pwd)
|
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
B, _, K, err := srp.Handshake(A, v)
|
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
c2.srp_s = s
|
|
|
|
c2.srp_A = A
|
|
|
|
c2.srp_B = B
|
|
|
|
c2.srp_K = K
|
2021-01-09 13:01:36 -08:00
|
|
|
|
|
|
|
// Send SRP_BYTES_S_B
|
|
|
|
data := make([]byte, 6+len(s)+len(B))
|
|
|
|
data[0] = uint8(0x00)
|
2021-01-14 10:06:40 -08:00
|
|
|
data[1] = uint8(ToClientSrpBytesSB)
|
2021-01-09 13:01:36 -08:00
|
|
|
binary.BigEndian.PutUint16(data[2:4], uint16(len(s)))
|
|
|
|
copy(data[4:4+len(s)], s)
|
|
|
|
binary.BigEndian.PutUint16(data[4+len(s):6+len(s)], uint16(len(B)))
|
|
|
|
copy(data[6+len(s):6+len(s)+len(B)], B)
|
|
|
|
|
2021-04-01 14:10:31 -07:00
|
|
|
w := bytes.NewBuffer([]byte{0x00, ToClientSrpBytesSB})
|
|
|
|
WriteBytes16(w, s)
|
|
|
|
WriteBytes16(w, B)
|
|
|
|
|
|
|
|
ack, err := c2.Send(rudp.Pkt{Reader: w})
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
<-ack
|
2021-01-14 10:06:40 -08:00
|
|
|
case ToServerSrpBytesM:
|
2021-01-09 13:01:36 -08:00
|
|
|
// Process data
|
|
|
|
// Make sure the client is allowed to use AuthMechSRP
|
2021-03-29 09:57:30 -07:00
|
|
|
if c2.authMech != AuthMechSRP {
|
|
|
|
log.Print(c2.Addr().String() + " used unsupported AuthMechSRP")
|
2021-01-09 13:01:36 -08:00
|
|
|
|
|
|
|
// Send ACCESS_DENIED
|
|
|
|
data := []byte{
|
2021-01-19 11:37:35 -08:00
|
|
|
0, ToClientAccessDenied,
|
|
|
|
AccessDeniedUnexpectedData, 0, 0, 0, 0,
|
2021-01-09 13:01:36 -08:00
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
ack, err := c2.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
<-ack
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
c2.Close()
|
|
|
|
fin <- c
|
2021-01-09 13:01:36 -08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-04-01 14:10:31 -07:00
|
|
|
M := ReadBytes16(r)
|
2021-03-31 10:27:50 -07:00
|
|
|
M2 := srp.ClientProof([]byte(c2.Username()), c2.srp_s, c2.srp_A, c2.srp_B, c2.srp_K)
|
2021-01-09 13:01:36 -08:00
|
|
|
|
|
|
|
if subtle.ConstantTimeCompare(M, M2) == 1 {
|
|
|
|
// Password is correct
|
|
|
|
// Send AUTH_ACCEPT
|
|
|
|
data := []byte{
|
2021-01-19 11:37:35 -08:00
|
|
|
0, ToClientAuthAccept,
|
2021-01-09 13:01:36 -08:00
|
|
|
// Position stuff
|
2021-01-19 11:37:35 -08:00
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
2021-01-09 13:01:36 -08:00
|
|
|
// Map seed
|
2021-01-19 11:37:35 -08:00
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
2021-01-09 13:01:36 -08:00
|
|
|
// Send interval
|
2021-01-19 11:37:35 -08:00
|
|
|
0x3D, 0xB8, 0x51, 0xEC,
|
2021-01-09 13:01:36 -08:00
|
|
|
// Sudo mode mechs
|
2021-01-19 11:37:35 -08:00
|
|
|
0, 0, 0, AuthMechSRP,
|
2021-01-09 13:01:36 -08:00
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
ack, err := c2.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
<-ack
|
|
|
|
} else {
|
|
|
|
// Client supplied wrong password
|
2021-03-29 09:57:30 -07:00
|
|
|
log.Print("User " + c2.Username() + " at " + c2.Addr().String() + " supplied wrong password")
|
2021-01-09 13:01:36 -08:00
|
|
|
|
|
|
|
// Send ACCESS_DENIED
|
|
|
|
data := []byte{
|
2021-01-19 11:37:35 -08:00
|
|
|
0, ToClientAccessDenied,
|
|
|
|
AccessDeniedWrongPassword, 0, 0, 0, 0,
|
2021-01-09 13:01:36 -08:00
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
ack, err := c2.Send(rudp.Pkt{Reader: bytes.NewReader(data)})
|
2021-01-09 13:01:36 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
<-ack
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
c2.Close()
|
|
|
|
fin <- c
|
2021-01-09 13:01:36 -08:00
|
|
|
return
|
|
|
|
}
|
2021-01-14 10:06:40 -08:00
|
|
|
case ToServerInit2:
|
2021-03-29 09:57:30 -07:00
|
|
|
c2.announceMedia()
|
2021-01-16 10:14:31 -08:00
|
|
|
case ToServerRequestMedia:
|
2021-04-01 11:27:58 -07:00
|
|
|
c2.sendMedia(r)
|
2021-01-16 10:14:31 -08:00
|
|
|
case ToServerClientReady:
|
2021-03-13 09:58:51 -08:00
|
|
|
defaultSrv := ConfKey("default_server").(string)
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
defSrv := func() *Conn {
|
2021-03-13 09:58:51 -08:00
|
|
|
defaultSrvAddr := ConfKey("servers:" + defaultSrv + ":address").(string)
|
|
|
|
|
|
|
|
srvaddr, err := net.ResolveUDPAddr("udp", defaultSrvAddr)
|
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
conn, err := net.DialUDP("udp", nil, srvaddr)
|
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
srv, err := Connect(conn)
|
2021-03-13 09:58:51 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
fin2 := make(chan *Conn) // close-only
|
|
|
|
go Init(c2, srv, ignMedia, noAccessDenied, fin2)
|
2021-03-17 09:18:21 -07:00
|
|
|
<-fin2
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
go processJoin(c2)
|
2021-03-13 09:58:51 -08:00
|
|
|
|
|
|
|
return srv
|
|
|
|
}
|
|
|
|
|
2021-03-09 13:23:41 -08:00
|
|
|
if forceDefaultServer, ok := ConfKey("force_default_server").(bool); !forceDefaultServer || !ok {
|
2021-03-29 09:57:30 -07:00
|
|
|
srvname, err := StorageKey("server:" + c2.Username())
|
2021-01-20 12:44:35 -08:00
|
|
|
if err != nil {
|
2021-03-09 13:23:41 -08:00
|
|
|
srvname, ok = ConfKey("servers:" + ConfKey("default_server").(string) + ":address").(string)
|
2021-01-20 12:44:35 -08:00
|
|
|
if !ok {
|
2021-03-29 09:57:30 -07:00
|
|
|
go c2.SendChatMsg("Could not connect you to your last server!")
|
2021-01-20 12:44:35 -08:00
|
|
|
|
2021-03-13 09:58:51 -08:00
|
|
|
fin <- defSrv()
|
2021-01-20 12:44:35 -08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-09 13:23:41 -08:00
|
|
|
straddr, ok := ConfKey("servers:" + srvname + ":address").(string)
|
2021-01-20 12:44:35 -08:00
|
|
|
if !ok {
|
2021-03-29 09:57:30 -07:00
|
|
|
go c2.SendChatMsg("Could not connect you to your last server!")
|
2021-01-20 12:44:35 -08:00
|
|
|
|
2021-03-13 09:58:51 -08:00
|
|
|
fin <- defSrv()
|
2021-01-20 12:44:35 -08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
srvaddr, err := net.ResolveUDPAddr("udp", straddr)
|
|
|
|
if err != nil {
|
2021-03-29 09:57:30 -07:00
|
|
|
go c2.SendChatMsg("Could not connect you to your last server!")
|
2021-01-20 12:44:35 -08:00
|
|
|
|
2021-03-13 09:58:51 -08:00
|
|
|
fin <- defSrv()
|
2021-01-20 12:44:35 -08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
conn, err := net.DialUDP("udp", nil, srvaddr)
|
|
|
|
if err != nil {
|
2021-03-29 09:57:30 -07:00
|
|
|
go c2.SendChatMsg("Could not connect you to your last server!")
|
2021-01-20 12:44:35 -08:00
|
|
|
|
2021-03-13 09:58:51 -08:00
|
|
|
fin <- defSrv()
|
2021-01-20 12:44:35 -08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-03-13 09:58:51 -08:00
|
|
|
if srvname != defaultSrv {
|
2021-03-29 09:57:30 -07:00
|
|
|
srv, err := Connect(conn)
|
2021-01-20 12:44:35 -08:00
|
|
|
if err != nil {
|
2021-03-29 09:57:30 -07:00
|
|
|
go c2.SendChatMsg("Could not connect you to your last server!")
|
2021-01-20 12:44:35 -08:00
|
|
|
|
2021-03-13 09:58:51 -08:00
|
|
|
fin <- defSrv()
|
2021-01-20 12:44:35 -08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
fin2 := make(chan *Conn) // close-only
|
|
|
|
go Init(c2, srv, ignMedia, noAccessDenied, fin2)
|
2021-03-14 05:52:31 -07:00
|
|
|
<-fin2
|
|
|
|
|
2021-03-29 09:57:30 -07:00
|
|
|
go c2.updateDetachedInvs(srvname)
|
|
|
|
go processJoin(c2)
|
2021-01-20 12:44:35 -08:00
|
|
|
|
|
|
|
fin <- srv
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-13 09:58:51 -08:00
|
|
|
fin <- defSrv()
|
2021-01-09 13:01:36 -08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|