friends/nex/account-management/nintendo_create_account.go
2025-02-15 23:31:32 -05:00

85 lines
3.2 KiB
Go

package nex_account_management
import (
"crypto/hmac"
"crypto/md5"
"encoding/base64"
"encoding/binary"
"encoding/hex"
"strings"
"github.com/PretendoNetwork/friends/globals"
"github.com/PretendoNetwork/friends/utility"
nex "github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
account_management "github.com/PretendoNetwork/nex-protocols-go/v2/account-management"
account_management_types "github.com/PretendoNetwork/nex-protocols-go/v2/account-management/types"
)
func NintendoCreateAccount(err error, packet nex.PacketInterface, callID uint32, strPrincipalName types.String, strKey types.String, uiGroups types.UInt32, strEmail types.String, oAuthData types.DataHolder) (*nex.RMCMessage, *nex.Error) {
if err != nil {
globals.Logger.Error(err.Error())
return nil, nex.NewError(nex.ResultCodes.Core.InvalidArgument, "") // TODO - Add error message
}
var tokenBase64 string
oAuthDataType := oAuthData.Object.DataObjectID().(types.String)
switch oAuthDataType {
case "NintendoCreateAccountData": // * Wii U
nintendoCreateAccountData := oAuthData.Object.Copy().(account_management_types.NintendoCreateAccountData)
tokenBase64 = string(nintendoCreateAccountData.Token)
case "AccountExtraInfo": // * 3DS
accountExtraInfo := oAuthData.Object.Copy().(account_management_types.AccountExtraInfo)
tokenBase64 = string(accountExtraInfo.NEXToken)
tokenBase64 = strings.Replace(tokenBase64, ".", "+", -1)
tokenBase64 = strings.Replace(tokenBase64, "-", "/", -1)
tokenBase64 = strings.Replace(tokenBase64, "*", "=", -1)
default:
globals.Logger.Errorf("Invalid oAuthData data type %s!", oAuthDataType)
return nil, nex.NewError(nex.ResultCodes.Authentication.TokenParseError, "") // TODO - Add error message
}
encryptedToken, err := base64.StdEncoding.DecodeString(tokenBase64)
if err != nil {
globals.Logger.Error(err.Error())
return nil, nex.NewError(nex.ResultCodes.Authentication.TokenParseError, "") // TODO - Add error message
}
decryptedToken, err := utility.DecryptToken(encryptedToken)
if err != nil {
globals.Logger.Error(err.Error())
return nil, nex.NewError(nex.ResultCodes.Authentication.TokenParseError, "") // TODO - Add error message
}
pid := types.NewPID(uint64(decryptedToken.UserPID))
pidByteArray := make([]byte, 4)
binary.LittleEndian.PutUint32(pidByteArray, uint32(pid))
mac := hmac.New(md5.New, []byte(strKey))
_, err = mac.Write(pidByteArray)
if err != nil {
globals.Logger.Error(err.Error())
return nil, nex.NewError(nex.ResultCodes.Authentication.Unknown, "") // TODO - Add error message
}
pidHmac := types.NewString(hex.EncodeToString(mac.Sum(nil)))
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
pid.WriteTo(rmcResponseStream)
pidHmac.WriteTo(rmcResponseStream)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
rmcResponse.ProtocolID = account_management.ProtocolID
rmcResponse.MethodID = account_management.MethodNintendoCreateAccount
rmcResponse.CallID = callID
return rmcResponse, nil
}