mirror of
https://github.com/PretendoNetwork/friends.git
synced 2026-03-21 18:04:11 -05:00
feat: Implement token validation from common protocols
We have to do special handling for guest accounts, so the insecure method is enabled on both TicketGranting and SecureConnection. Alongside that, we override the RegisterEx function to do the additional processing required by friends.
This commit is contained in:
parent
5560c1d7f2
commit
66c6e6028a
28
go.mod
28
go.mod
|
|
@ -7,35 +7,33 @@ toolchain go1.23.6
|
|||
require (
|
||||
github.com/PretendoNetwork/grpc-go v1.0.2
|
||||
github.com/PretendoNetwork/nex-go/v2 v2.1.3
|
||||
github.com/PretendoNetwork/nex-protocols-common-go/v2 v2.2.2
|
||||
github.com/PretendoNetwork/nex-protocols-common-go/v2 v2.4.0
|
||||
github.com/PretendoNetwork/nex-protocols-go/v2 v2.2.1
|
||||
github.com/PretendoNetwork/plogger-go v1.0.4
|
||||
github.com/PretendoNetwork/plogger-go v1.1.0
|
||||
github.com/PretendoNetwork/sql-manager v1.0.0
|
||||
github.com/golang/protobuf v1.5.4
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/lib/pq v1.10.9
|
||||
google.golang.org/grpc v1.70.0
|
||||
google.golang.org/grpc v1.71.1
|
||||
)
|
||||
|
||||
replace google.golang.org/genproto => google.golang.org/genproto v0.0.0-20240520151616-dc85e6b867a5
|
||||
|
||||
require (
|
||||
github.com/dolthub/maphash v0.1.0 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/jwalton/go-supportscolor v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/lxzan/gws v1.8.8 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/rasky/go-lzo v0.0.0-20200203143853-96a758eda86e // indirect
|
||||
github.com/superwhiskers/crunch/v3 v3.5.7 // indirect
|
||||
golang.org/x/exp v0.0.0-20250215185904-eff6e970281f // indirect
|
||||
golang.org/x/mod v0.23.0 // indirect
|
||||
golang.org/x/net v0.35.0 // indirect
|
||||
golang.org/x/sync v0.11.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/term v0.29.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b // indirect
|
||||
google.golang.org/protobuf v1.36.5 // indirect
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
|
||||
golang.org/x/mod v0.24.0 // indirect
|
||||
golang.org/x/net v0.39.0 // indirect
|
||||
golang.org/x/sync v0.13.0 // indirect
|
||||
golang.org/x/sys v0.32.0 // indirect
|
||||
golang.org/x/term v0.31.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
)
|
||||
|
|
|
|||
76
go.sum
76
go.sum
|
|
@ -1,15 +1,13 @@
|
|||
github.com/PretendoNetwork/grpc-go v1.0.2 h1:9TvKmX7dCOANyoHEra1MMYqS1N/RGav66TRG4SHInvo=
|
||||
github.com/PretendoNetwork/grpc-go v1.0.2/go.mod h1:XZjEsij9lL7HJBNkH6JPbBIkUSq/1rjflvjGdv+DAj0=
|
||||
github.com/PretendoNetwork/nex-go/v2 v2.1.2 h1:OJFAS6U6VNzZ4YzteKqUEZ5aJMwWIHODeRrLwNbN7nw=
|
||||
github.com/PretendoNetwork/nex-go/v2 v2.1.2/go.mod h1:3LyJzsv3AataJW8D0binp15Q8ZH22MWTYly1VNtXi64=
|
||||
github.com/PretendoNetwork/nex-go/v2 v2.1.3 h1:hdi8PbJIWbpr3WOc1fGJ5ssF76kTxFJ3Wnz46WJYvVs=
|
||||
github.com/PretendoNetwork/nex-go/v2 v2.1.3/go.mod h1:3LyJzsv3AataJW8D0binp15Q8ZH22MWTYly1VNtXi64=
|
||||
github.com/PretendoNetwork/nex-protocols-common-go/v2 v2.2.2 h1:rBJNZDJ92pa9fU3Og0sanyizJTWnELPoGR0Tjz8zlws=
|
||||
github.com/PretendoNetwork/nex-protocols-common-go/v2 v2.2.2/go.mod h1:iuNMuBK/zww+44d6ajfLsOusXx/6Llj3zSkmhJwMuuM=
|
||||
github.com/PretendoNetwork/nex-protocols-common-go/v2 v2.4.0 h1:EhXj1EDbNgdg40BPx/7n1HHsAy/DayGIWthu81UNyvI=
|
||||
github.com/PretendoNetwork/nex-protocols-common-go/v2 v2.4.0/go.mod h1:tNtZly5sL3wfy4LVgybS2efm00L/wNgyvcrBV59S/YM=
|
||||
github.com/PretendoNetwork/nex-protocols-go/v2 v2.2.1 h1:/dsuP0W7bZNvrXoXH0ZRdxpxonfbWmmson51WCQdpEQ=
|
||||
github.com/PretendoNetwork/nex-protocols-go/v2 v2.2.1/go.mod h1:+soBHmwX6ixGxj6cphLuCvfJqxcZPuowc/5e7Qi9Bz0=
|
||||
github.com/PretendoNetwork/plogger-go v1.0.4 h1:PF7xHw9eDRHH+RsAP9tmAE7fG0N0p6H4iPwHKnsoXwc=
|
||||
github.com/PretendoNetwork/plogger-go v1.0.4/go.mod h1:7kD6M4vPq1JL4LTuPg6kuB1OvUBOwQOtAvTaUwMbwvU=
|
||||
github.com/PretendoNetwork/plogger-go v1.1.0 h1:x2XgyeeM8zDFGy+NcIZd3SYC2fNrVWpBBbkqTejOfiM=
|
||||
github.com/PretendoNetwork/plogger-go v1.1.0/go.mod h1:wpltahp91IXr9nOvWgwep8zGtUKDeCVwm+/Wa484lQ4=
|
||||
github.com/PretendoNetwork/sql-manager v1.0.0 h1:g0SYpQgi6Kk4ptufrLTSmDxvqaYioTcfXaDH+uXC+a0=
|
||||
github.com/PretendoNetwork/sql-manager v1.0.0/go.mod h1:NaEdDC0S/9J8eoxCDvuHB8fofv0svh44lWvgCdtuMq0=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
|
@ -32,8 +30,8 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
|||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/jwalton/go-supportscolor v1.2.0 h1:g6Ha4u7Vm3LIsQ5wmeBpS4gazu0UP1DRDE8y6bre4H8=
|
||||
github.com/jwalton/go-supportscolor v1.2.0/go.mod h1:hFVUAZV2cWg+WFFC4v8pT2X/S2qUUBYMioBD9AINXGs=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lxzan/gws v1.8.8 h1:st193ZG8qN8sSw8/g/UituFhs7etmKzS7jUqhijg5wM=
|
||||
|
|
@ -50,39 +48,41 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
|
|||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/superwhiskers/crunch/v3 v3.5.7 h1:N9RLxaR65C36i26BUIpzPXGy2f6pQ7wisu2bawbKNqg=
|
||||
github.com/superwhiskers/crunch/v3 v3.5.7/go.mod h1:4ub2EKgF1MAhTjoOCTU4b9uLMsAweHEa89aRrfAypXA=
|
||||
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
|
||||
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
|
||||
go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
|
||||
go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
|
||||
go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
|
||||
go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
|
||||
go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
|
||||
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
|
||||
golang.org/x/exp v0.0.0-20250215185904-eff6e970281f h1:oFMYAjX0867ZD2jcNiLBrI9BdpmEkvPyi5YrBGXbamg=
|
||||
golang.org/x/exp v0.0.0-20250215185904-eff6e970281f/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk=
|
||||
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
|
||||
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
|
||||
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
|
||||
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
|
||||
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
|
||||
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
|
||||
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
|
||||
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
|
||||
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
|
||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
|
||||
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b h1:FQtJ1MxbXoIIrZHZ33M+w5+dAP9o86rgpjoKr/ZmT7k=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
|
||||
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
|
||||
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
|
||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
|
||||
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e h1:ztQaXfzEXTmCBvbtWYRhJxW+0iJcz2qXfd38/e9l7bA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI=
|
||||
google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
|
|||
|
|
@ -3,56 +3,26 @@ 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
|
||||
return nil, nex.NewError(nex.ResultCodes.Core.InvalidArgument, err.Error())
|
||||
}
|
||||
|
||||
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
|
||||
decryptedToken, nexError := utility.ValidateNintendoCreateAccountToken(oAuthData)
|
||||
if nexError != nil {
|
||||
globals.Logger.Error(nexError.Error())
|
||||
return nil, nexError
|
||||
}
|
||||
|
||||
pid := types.NewPID(uint64(decryptedToken.UserPID))
|
||||
|
|
@ -64,7 +34,7 @@ func NintendoCreateAccount(err error, packet nex.PacketInterface, callID uint32,
|
|||
_, err = mac.Write(pidByteArray)
|
||||
if err != nil {
|
||||
globals.Logger.Error(err.Error())
|
||||
return nil, nex.NewError(nex.ResultCodes.Authentication.Unknown, "") // TODO - Add error message
|
||||
return nil, nex.NewError(nex.ResultCodes.Authentication.Unknown, err.Error())
|
||||
}
|
||||
|
||||
pidHmac := types.NewString(hex.EncodeToString(mac.Sum(nil)))
|
||||
|
|
|
|||
|
|
@ -9,8 +9,12 @@ import (
|
|||
|
||||
func registerCommonSecureServerProtocols() {
|
||||
secureConnectionProtocol := secure_connection.NewProtocol()
|
||||
common_secure_connection.NewCommonProtocol(secureConnectionProtocol)
|
||||
commonSecureConnectionProtocol := common_secure_connection.NewCommonProtocol(secureConnectionProtocol)
|
||||
|
||||
// * On account creation the console logs in with a guest account and uses the Register method
|
||||
commonSecureConnectionProtocol.EnableInsecureRegister()
|
||||
|
||||
// * Override RegisterEx so that we can register the user into the ConnectedUsers map
|
||||
secureConnectionProtocol.RegisterEx = nex_secure_connection.RegisterEx
|
||||
|
||||
globals.SecureEndpoint.RegisterServiceProtocol(secureConnectionProtocol)
|
||||
|
|
|
|||
|
|
@ -3,77 +3,144 @@ package nex_secure_connection
|
|||
import (
|
||||
"net"
|
||||
|
||||
"github.com/PretendoNetwork/nex-go/v2"
|
||||
"github.com/PretendoNetwork/nex-go/v2/constants"
|
||||
"github.com/PretendoNetwork/nex-go/v2/types"
|
||||
secure_connection "github.com/PretendoNetwork/nex-protocols-go/v2/secure-connection"
|
||||
common_globals "github.com/PretendoNetwork/nex-protocols-common-go/v2/globals"
|
||||
|
||||
database_3ds "github.com/PretendoNetwork/friends/database/3ds"
|
||||
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
friends_types "github.com/PretendoNetwork/friends/types"
|
||||
nex "github.com/PretendoNetwork/nex-go/v2"
|
||||
"github.com/PretendoNetwork/nex-go/v2/types"
|
||||
secure_connection "github.com/PretendoNetwork/nex-protocols-go/v2/secure-connection"
|
||||
)
|
||||
|
||||
func RegisterEx(err error, packet nex.PacketInterface, callID uint32, vecMyURLs types.List[types.StationURL], hCustomData types.DataHolder) (*nex.RMCMessage, *nex.Error) {
|
||||
if err != nil {
|
||||
globals.Logger.Error(err.Error())
|
||||
return nil, nex.NewError(nex.ResultCodes.Core.InvalidArgument, "")
|
||||
common_globals.Logger.Error(err.Error())
|
||||
return nil, nex.NewError(nex.ResultCodes.Core.InvalidArgument, err.Error())
|
||||
}
|
||||
|
||||
connection := packet.Sender().(*nex.PRUDPConnection)
|
||||
endpoint := connection.Endpoint()
|
||||
|
||||
retval := types.NewQResultSuccess(nex.ResultCodes.Core.Unknown)
|
||||
|
||||
// TODO - Validate loginData
|
||||
pid := uint32(connection.PID())
|
||||
|
||||
user := friends_types.NewConnectedUser()
|
||||
user.PID = pid
|
||||
user.Connection = connection
|
||||
|
||||
lastOnline := types.NewDateTime(0).Now()
|
||||
loginDataType := hCustomData.Object.DataObjectID().(types.String)
|
||||
|
||||
switch loginDataType {
|
||||
case "NintendoLoginData":
|
||||
user.Platform = friends_types.WUP // * Platform is Wii U
|
||||
|
||||
err = database_wiiu.UpdateUserLastOnlineTime(pid, lastOnline)
|
||||
if err != nil {
|
||||
globals.Logger.Critical(err.Error())
|
||||
retval = types.NewQResultError(nex.ResultCodes.Authentication.Unknown)
|
||||
}
|
||||
case "AccountExtraInfo":
|
||||
user.Platform = friends_types.CTR // * Platform is 3DS
|
||||
|
||||
err = database_3ds.UpdateUserLastOnlineTime(pid, lastOnline)
|
||||
if err != nil {
|
||||
globals.Logger.Critical(err.Error())
|
||||
retval = types.NewQResultError(nex.ResultCodes.Authentication.Unknown)
|
||||
}
|
||||
default:
|
||||
globals.Logger.Errorf("Unknown loginData data type %s!", loginDataType)
|
||||
retval = types.NewQResultError(nex.ResultCodes.Authentication.ValidationFailed)
|
||||
}
|
||||
|
||||
var retval types.QResult
|
||||
pidConnectionID := types.NewUInt32(0)
|
||||
urlPublic := types.NewString("")
|
||||
|
||||
if retval.IsSuccess() {
|
||||
globals.ConnectedUsers.Set(pid, user)
|
||||
errorCode := common_globals.ValidatePretendoLoginData(connection.PID(), hCustomData, globals.AESKey)
|
||||
if errorCode != nil {
|
||||
common_globals.Logger.Error(errorCode.Message)
|
||||
retval = types.NewQResultError(errorCode.ResultCode)
|
||||
} else {
|
||||
// * vecMyURLs may contain multiple StationURLs. Search them all
|
||||
var localStation *types.StationURL
|
||||
var publicStation *types.StationURL
|
||||
|
||||
localStation := vecMyURLs[0]
|
||||
for _, stationURL := range vecMyURLs {
|
||||
natf, ok := stationURL.NATFiltering()
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
address := connection.Address().(*net.UDPAddr)
|
||||
natm, ok := stationURL.NATMapping()
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
localStation.SetAddress(address.IP.String())
|
||||
localStation.SetPortNumber(uint16(address.Port))
|
||||
// * Station reports itself as being non-public (local)
|
||||
if localStation == nil && !stationURL.IsPublic() {
|
||||
localStation = &stationURL
|
||||
}
|
||||
|
||||
localStationURL := localStation.URL()
|
||||
// * Still did not find the station, trying heuristics
|
||||
if localStation == nil && natf == constants.UnknownNATFiltering && natm == constants.UnknownNATMapping {
|
||||
localStation = &stationURL
|
||||
}
|
||||
|
||||
pidConnectionID = types.NewUInt32(connection.ID)
|
||||
urlPublic = types.NewString(localStationURL)
|
||||
if publicStation == nil && stationURL.IsPublic() {
|
||||
publicStation = &stationURL
|
||||
}
|
||||
}
|
||||
|
||||
if localStation == nil {
|
||||
common_globals.Logger.Error("Failed to find local station")
|
||||
return nil, nex.NewError(nex.ResultCodes.Core.InvalidArgument, "change_error")
|
||||
}
|
||||
|
||||
if publicStation == nil {
|
||||
publicStation = localStation
|
||||
|
||||
var address string
|
||||
var port uint16
|
||||
|
||||
// * We have to duplicate this because Go automatically breaks on switch statements
|
||||
switch clientAddress := connection.Address().(type) {
|
||||
case *net.UDPAddr:
|
||||
address = clientAddress.IP.String()
|
||||
port = uint16(clientAddress.Port)
|
||||
case *net.TCPAddr:
|
||||
address = clientAddress.IP.String()
|
||||
port = uint16(clientAddress.Port)
|
||||
}
|
||||
|
||||
publicStation.SetAddress(address)
|
||||
publicStation.SetPortNumber(port)
|
||||
publicStation.SetNATFiltering(constants.UnknownNATFiltering)
|
||||
publicStation.SetNATMapping(constants.UnknownNATMapping)
|
||||
publicStation.SetType(uint8(constants.StationURLFlagPublic) | uint8(constants.StationURLFlagBehindNAT))
|
||||
}
|
||||
|
||||
localStation.SetPrincipalID(connection.PID())
|
||||
publicStation.SetPrincipalID(connection.PID())
|
||||
|
||||
localStation.SetRVConnectionID(connection.ID)
|
||||
publicStation.SetRVConnectionID(connection.ID)
|
||||
|
||||
connection.StationURLs = append(connection.StationURLs, *localStation)
|
||||
connection.StationURLs = append(connection.StationURLs, *publicStation)
|
||||
|
||||
pid := uint32(connection.PID())
|
||||
|
||||
user := friends_types.NewConnectedUser()
|
||||
user.PID = pid
|
||||
user.Connection = connection
|
||||
|
||||
lastOnline := types.NewDateTime(0).Now()
|
||||
loginDataType := hCustomData.Object.DataObjectID().(types.String)
|
||||
|
||||
switch loginDataType {
|
||||
case "NintendoLoginData":
|
||||
user.Platform = friends_types.WUP // * Platform is Wii U
|
||||
|
||||
err = database_wiiu.UpdateUserLastOnlineTime(pid, lastOnline)
|
||||
if err != nil {
|
||||
globals.Logger.Critical(err.Error())
|
||||
retval = types.NewQResultError(nex.ResultCodes.Authentication.Unknown)
|
||||
}
|
||||
case "AccountExtraInfo":
|
||||
user.Platform = friends_types.CTR // * Platform is 3DS
|
||||
|
||||
err = database_3ds.UpdateUserLastOnlineTime(pid, lastOnline)
|
||||
if err != nil {
|
||||
globals.Logger.Critical(err.Error())
|
||||
retval = types.NewQResultError(nex.ResultCodes.Authentication.Unknown)
|
||||
}
|
||||
default:
|
||||
globals.Logger.Errorf("Unknown loginData data type %s!", loginDataType)
|
||||
retval = types.NewQResultError(nex.ResultCodes.Authentication.ValidationFailed)
|
||||
}
|
||||
|
||||
if !retval.IsError() {
|
||||
globals.ConnectedUsers.Set(pid, user)
|
||||
|
||||
retval = types.NewQResultSuccess(nex.ResultCodes.Core.Unknown)
|
||||
pidConnectionID = types.NewUInt32(connection.ID)
|
||||
urlPublic = types.NewString(publicStation.URL())
|
||||
}
|
||||
}
|
||||
|
||||
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
|
||||
rmcResponseStream := nex.NewByteStreamOut(endpoint.LibraryVersions(), endpoint.ByteStreamSettings())
|
||||
|
||||
retval.WriteTo(rmcResponseStream)
|
||||
pidConnectionID.WriteTo(rmcResponseStream)
|
||||
|
|
@ -81,7 +148,7 @@ func RegisterEx(err error, packet nex.PacketInterface, callID uint32, vecMyURLs
|
|||
|
||||
rmcResponseBody := rmcResponseStream.Bytes()
|
||||
|
||||
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
|
||||
rmcResponse := nex.NewRMCSuccess(endpoint, rmcResponseBody)
|
||||
rmcResponse.ProtocolID = secure_connection.ProtocolID
|
||||
rmcResponse.MethodID = secure_connection.MethodRegisterEx
|
||||
rmcResponse.CallID = callID
|
||||
|
|
|
|||
70
utility/authentication.go
Normal file
70
utility/authentication.go
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
package utility
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/PretendoNetwork/nex-go/v2"
|
||||
"github.com/PretendoNetwork/nex-go/v2/types"
|
||||
common_globals "github.com/PretendoNetwork/nex-protocols-common-go/v2/globals"
|
||||
account_management_types "github.com/PretendoNetwork/nex-protocols-go/v2/account-management/types"
|
||||
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
)
|
||||
|
||||
// ValidateNintendoCreateAccountToken validates the given Pretendo token for account creation
|
||||
func ValidateNintendoCreateAccountToken(token types.DataHolder) (*common_globals.NEXToken, *nex.Error) {
|
||||
var tokenBase64 string
|
||||
|
||||
tokenDataType := token.Object.DataObjectID().(types.String)
|
||||
|
||||
switch tokenDataType {
|
||||
case "NintendoCreateAccountData": // * Wii U
|
||||
nintendoCreateAccountData := token.Object.Copy().(account_management_types.NintendoCreateAccountData)
|
||||
|
||||
tokenBase64 = string(nintendoCreateAccountData.Token)
|
||||
case "AccountExtraInfo": // * 3DS
|
||||
accountExtraInfo := token.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 token data type %s!", tokenDataType)
|
||||
return nil, nex.NewError(nex.ResultCodes.Authentication.ValidationFailed, fmt.Sprintf("Invalid token data type %s!", tokenDataType))
|
||||
}
|
||||
|
||||
encryptedToken, err := base64.StdEncoding.DecodeString(tokenBase64)
|
||||
if err != nil {
|
||||
globals.Logger.Error(err.Error())
|
||||
return nil, nex.NewError(nex.ResultCodes.Authentication.ValidationFailed, err.Error())
|
||||
}
|
||||
|
||||
decryptedToken, nexError := common_globals.DecryptToken(encryptedToken, globals.AESKey)
|
||||
if nexError != nil {
|
||||
return nil, nexError
|
||||
}
|
||||
|
||||
// Check for NEX token type
|
||||
if decryptedToken.TokenType != 3 {
|
||||
return nil, nex.NewError(nex.ResultCodes.Authentication.ValidationFailed, "Invalid token type")
|
||||
}
|
||||
|
||||
// Expire time is in milliseconds
|
||||
expireTime := time.Unix(int64(decryptedToken.ExpireTime / 1000), 0)
|
||||
|
||||
if expireTime.Before(time.Now()) {
|
||||
return nil, nex.NewError(nex.ResultCodes.Authentication.TokenExpired, "Token expired")
|
||||
}
|
||||
|
||||
// PID isn't checked since account creation is done with a guest account
|
||||
|
||||
if decryptedToken.AccessLevel < 0 {
|
||||
return nil, nex.NewError(nex.ResultCodes.RendezVous.AccountDisabled, fmt.Sprintf("Account %d is banned", decryptedToken.UserPID))
|
||||
}
|
||||
|
||||
return decryptedToken, nil
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
package utility
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
"github.com/PretendoNetwork/friends/types"
|
||||
)
|
||||
|
||||
func DecryptToken(encryptedToken []byte) (*types.NEXToken, error) {
|
||||
// Decrypt the token body
|
||||
block, err := aes.NewCipher(globals.AESKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
expectedChecksum := binary.BigEndian.Uint32(encryptedToken[0:4])
|
||||
encryptedBody := encryptedToken[4:]
|
||||
|
||||
decrypted := make([]byte, len(encryptedBody))
|
||||
iv := make([]byte, 16)
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
mode.CryptBlocks(decrypted, encryptedBody)
|
||||
|
||||
paddingSize := int(decrypted[len(decrypted)-1])
|
||||
|
||||
if paddingSize < 0 || paddingSize >= len(decrypted) {
|
||||
return nil, fmt.Errorf("Invalid padding size %d for token %x", paddingSize, encryptedToken)
|
||||
}
|
||||
|
||||
decrypted = decrypted[:len(decrypted)-paddingSize]
|
||||
|
||||
table := crc32.MakeTable(crc32.IEEE)
|
||||
calculatedChecksum := crc32.Checksum(decrypted, table)
|
||||
|
||||
if expectedChecksum != calculatedChecksum {
|
||||
return nil, errors.New("Checksum did not match. Failed decrypt. Are you using the right key?")
|
||||
}
|
||||
|
||||
// Unpack the token body to struct
|
||||
token := &types.NEXToken{}
|
||||
tokenReader := bytes.NewBuffer(decrypted)
|
||||
|
||||
err = binary.Read(tokenReader, binary.LittleEndian, token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return token, nil
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user