mirror of
https://github.com/PretendoNetwork/wiiu-chat-authentication.git
synced 2026-04-25 07:37:35 -05:00
initial commit
This commit is contained in:
commit
07f4e2473d
19
.gitignore
vendored
Normal file
19
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
# custom
|
||||
build
|
||||
.env
|
||||
41
database.go
Normal file
41
database.go
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
var mongoClient *mongo.Client
|
||||
var mongoContext context.Context
|
||||
var mongoDatabase *mongo.Database
|
||||
var mongoCollection *mongo.Collection
|
||||
|
||||
func connectMongo() {
|
||||
mongoClient, _ = mongo.NewClient(options.Client().ApplyURI(os.Getenv("MONGO_URI")))
|
||||
mongoContext, _ = context.WithTimeout(context.Background(), 10*time.Second)
|
||||
_ = mongoClient.Connect(mongoContext)
|
||||
|
||||
mongoDatabase = mongoClient.Database("pretendo")
|
||||
mongoCollection = mongoDatabase.Collection("nexaccounts")
|
||||
}
|
||||
|
||||
func getNEXAccountByPID(pid uint32) bson.M {
|
||||
var result bson.M
|
||||
|
||||
err := mongoCollection.FindOne(context.TODO(), bson.D{{Key: "pid", Value: pid}}, options.FindOne()).Decode(&result)
|
||||
|
||||
if err != nil {
|
||||
if err == mongo.ErrNoDocuments {
|
||||
return nil
|
||||
}
|
||||
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
22
init.go
Normal file
22
init.go
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Mongo struct {
|
||||
}
|
||||
Cassandra struct{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
err := godotenv.Load()
|
||||
if err != nil {
|
||||
log.Fatal("Error loading .env file")
|
||||
}
|
||||
|
||||
connectMongo()
|
||||
}
|
||||
79
kerberos.go
Normal file
79
kerberos.go
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
nex "github.com/PretendoNetwork/nex-go"
|
||||
)
|
||||
|
||||
func generateKerberosTicket(userPID uint32, serverPID uint32, keySize int) ([]byte, int) {
|
||||
user := getNEXAccountByPID(userPID)
|
||||
if user == nil {
|
||||
return []byte{}, 0x80030064 // RendezVous::InvalidUsername
|
||||
}
|
||||
|
||||
userPassword := user["password"].(string)
|
||||
serverPassword := "password"
|
||||
|
||||
// Create session key and ticket keys
|
||||
sessionKey := make([]byte, keySize)
|
||||
|
||||
ticketInfoKey := make([]byte, 16) // key for encrypting the internal ticket info. Only used by server. TODO: Make this random!
|
||||
userKey := deriveKey(userPID, []byte(userPassword)) // Key for encrypting entire ticket. Used by client and server
|
||||
serverKey := deriveKey(serverPID, []byte(serverPassword))
|
||||
finalKey := nex.MD5Hash(append(serverKey, ticketInfoKey...))
|
||||
|
||||
//rand.Read(sessionKey) // Create a random session key
|
||||
|
||||
//fmt.Println("Using Session Key: " + hex.EncodeToString(sessionKey))
|
||||
|
||||
////////////////////////////////
|
||||
// Build internal ticket info //
|
||||
////////////////////////////////
|
||||
|
||||
expiration := nex.NewDateTime(0)
|
||||
ticketInfoStream := nex.NewStreamOut(nexServer)
|
||||
|
||||
ticketInfoStream.WriteUInt64LE(expiration.Now())
|
||||
ticketInfoStream.WriteUInt32LE(userPID)
|
||||
ticketInfoStream.Grow(int64(keySize))
|
||||
ticketInfoStream.WriteBytesNext(sessionKey)
|
||||
|
||||
// Encrypt internal ticket info
|
||||
|
||||
ticketInfoEncryption := nex.NewKerberosEncryption(nex.MD5Hash(finalKey))
|
||||
encryptedTicketInfo := ticketInfoEncryption.Encrypt(ticketInfoStream.Bytes())
|
||||
|
||||
///////////////////////////////////
|
||||
// Build ticket data New Version //
|
||||
///////////////////////////////////
|
||||
|
||||
ticketDataStream := nex.NewStreamOut(nexServer)
|
||||
|
||||
ticketDataStream.WriteBuffer(ticketInfoKey)
|
||||
ticketDataStream.WriteBuffer(encryptedTicketInfo)
|
||||
|
||||
///////////////////////////
|
||||
// Build Kerberos Ticket //
|
||||
///////////////////////////
|
||||
|
||||
ticketStream := nex.NewStreamOut(nexServer)
|
||||
|
||||
// Write session key
|
||||
ticketStream.Grow(int64(keySize))
|
||||
ticketStream.WriteBytesNext(sessionKey)
|
||||
ticketStream.WriteUInt32LE(serverPID)
|
||||
ticketStream.WriteBuffer(ticketDataStream.Bytes())
|
||||
|
||||
// Encrypt the ticket
|
||||
ticketEncryption := nex.NewKerberosEncryption(userKey)
|
||||
encryptedTicket := ticketEncryption.Encrypt(ticketStream.Bytes())
|
||||
|
||||
return encryptedTicket, 0
|
||||
}
|
||||
|
||||
func deriveKey(pid uint32, password []byte) []byte {
|
||||
for i := 0; i < 65000+int(pid)%1024; i++ {
|
||||
password = nex.MD5Hash(password)
|
||||
}
|
||||
|
||||
return password
|
||||
}
|
||||
69
login_ex.go
Normal file
69
login_ex.go
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
nex "github.com/PretendoNetwork/nex-go"
|
||||
nexproto "github.com/PretendoNetwork/nex-protocols-go"
|
||||
)
|
||||
|
||||
func loginEx(err error, client *nex.Client, callID uint32, username string, authenticationInfo *nexproto.AuthenticationInfo) {
|
||||
// TODO: Verify auth info
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
userPID, _ := strconv.Atoi(username)
|
||||
|
||||
serverPID := 1 // Quazal Rendez-Vous
|
||||
|
||||
encryptedTicket, errorCode := generateKerberosTicket(uint32(userPID), uint32(serverPID), nexServer.KerberosKeySize())
|
||||
|
||||
if errorCode != 0 {
|
||||
fmt.Println(errorCode)
|
||||
return
|
||||
}
|
||||
|
||||
// Build the response body
|
||||
stationURL := "prudps:/address=66.177.0.8;port=60005;CID=1;PID=2;sid=1;stream=10;type=2"
|
||||
serverName := "Pretendo WiiU Chat"
|
||||
|
||||
rvConnectionData := nex.NewRVConnectionData()
|
||||
rvConnectionData.SetStationURL(stationURL)
|
||||
rvConnectionData.SetSpecialProtocols([]byte{})
|
||||
rvConnectionData.SetStationURLSpecialProtocols("")
|
||||
serverTime := nex.NewDateTime(0)
|
||||
rvConnectionData.SetTime(serverTime.Now())
|
||||
|
||||
rmcResponseStream := nex.NewStreamOut(nexServer)
|
||||
|
||||
rmcResponseStream.WriteUInt32LE(0x10001) // success
|
||||
rmcResponseStream.WriteUInt32LE(uint32(userPID))
|
||||
rmcResponseStream.WriteBuffer(encryptedTicket)
|
||||
rmcResponseStream.WriteStructure(rvConnectionData)
|
||||
rmcResponseStream.WriteString(serverName)
|
||||
|
||||
rmcResponseBody := rmcResponseStream.Bytes()
|
||||
|
||||
// Build response packet
|
||||
rmcResponse := nex.NewRMCResponse(nexproto.AuthenticationProtocolID, callID)
|
||||
rmcResponse.SetSuccess(nexproto.AuthenticationMethodLoginEx, rmcResponseBody)
|
||||
|
||||
rmcResponseBytes := rmcResponse.Bytes()
|
||||
|
||||
responsePacket, _ := nex.NewPacketV1(client, nil)
|
||||
|
||||
responsePacket.SetVersion(1)
|
||||
responsePacket.SetSource(0xA1)
|
||||
responsePacket.SetDestination(0xAF)
|
||||
responsePacket.SetType(nex.DataPacket)
|
||||
responsePacket.SetPayload(rmcResponseBytes)
|
||||
|
||||
responsePacket.AddFlag(nex.FlagNeedsAck)
|
||||
responsePacket.AddFlag(nex.FlagReliable)
|
||||
|
||||
nexServer.Send(responsePacket)
|
||||
}
|
||||
34
main.go
Normal file
34
main.go
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
nex "github.com/PretendoNetwork/nex-go"
|
||||
nexproto "github.com/PretendoNetwork/nex-protocols-go"
|
||||
)
|
||||
|
||||
var nexServer *nex.Server
|
||||
|
||||
func main() {
|
||||
nexServer = nex.NewServer()
|
||||
nexServer.SetPrudpVersion(1)
|
||||
nexServer.SetNexVersion(2)
|
||||
nexServer.SetKerberosKeySize(32)
|
||||
nexServer.SetAccessKey("e7a47214")
|
||||
|
||||
nexServer.On("Data", func(packet *nex.PacketV1) {
|
||||
request := packet.RMCRequest()
|
||||
|
||||
fmt.Println("==WiiU Chat - Auth==")
|
||||
fmt.Printf("Protocol ID: %#v\n", request.ProtocolID())
|
||||
fmt.Printf("Method ID: %#v\n", request.MethodID())
|
||||
fmt.Println("====================")
|
||||
})
|
||||
|
||||
authenticationServer := nexproto.NewAuthenticationProtocol(nexServer)
|
||||
|
||||
authenticationServer.LoginEx(loginEx)
|
||||
authenticationServer.RequestTicket(requestTicket)
|
||||
|
||||
nexServer.Listen(":60004")
|
||||
}
|
||||
49
request_ticket.go
Normal file
49
request_ticket.go
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
nex "github.com/PretendoNetwork/nex-go"
|
||||
nexproto "github.com/PretendoNetwork/nex-protocols-go"
|
||||
)
|
||||
|
||||
func requestTicket(err error, client *nex.Client, callID uint32, userPID uint32, serverPID uint32) {
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
encryptedTicket, errorCode := generateKerberosTicket(userPID, serverPID, nexServer.KerberosKeySize())
|
||||
|
||||
if errorCode != 0 {
|
||||
fmt.Println(errorCode)
|
||||
return
|
||||
}
|
||||
|
||||
// Build the response body
|
||||
rmcResponseStream := nex.NewStreamOut(nexServer)
|
||||
|
||||
rmcResponseStream.WriteUInt32LE(0x10001) // success
|
||||
rmcResponseStream.WriteBuffer(encryptedTicket)
|
||||
|
||||
rmcResponseBody := rmcResponseStream.Bytes()
|
||||
|
||||
// Build response packet
|
||||
rmcResponse := nex.NewRMCResponse(nexproto.AuthenticationProtocolID, callID)
|
||||
rmcResponse.SetSuccess(nexproto.AuthenticationMethodRequestTicket, rmcResponseBody)
|
||||
|
||||
rmcResponseBytes := rmcResponse.Bytes()
|
||||
|
||||
responsePacket, _ := nex.NewPacketV1(client, nil)
|
||||
|
||||
responsePacket.SetVersion(1)
|
||||
responsePacket.SetSource(0xA1)
|
||||
responsePacket.SetDestination(0xAF)
|
||||
responsePacket.SetType(nex.DataPacket)
|
||||
responsePacket.SetPayload(rmcResponseBytes)
|
||||
|
||||
responsePacket.AddFlag(nex.FlagNeedsAck)
|
||||
responsePacket.AddFlag(nex.FlagReliable)
|
||||
|
||||
nexServer.Send(responsePacket)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user