kinnay / NintendoClients

Python package to communicate with Switch, Wii U and 3DS servers
MIT License
537 stars 63 forks source link

Add support for system version 15.0.0 #90

Closed kinnay closed 1 year ago

kinnay commented 1 year ago

AAuth was updated.

kinnay commented 1 year ago

For digital titles, the cert_key parameter was removed and it is no longer necessary to dump the application certificate. Instead, the Switch requests a contents authorization token from the dragons server.

kinnay commented 1 year ago

I implemented 15.0.0 and 15.0.1 support locally. Things to do:

TheGreatRambler commented 1 year ago

Let me know when you push these changes

kinnay commented 1 year ago

@TheGreatRambler I pushed my changes. It's become a bit more complicated because of the dragons thing (6 requests are required instead of 4 now).

TheGreatRambler commented 1 year ago

Thank you for your awesome reverse engineering work, I'll take a look

TheGreatRambler commented 1 year ago

Quick question about getting elicenses, what is the device id or did needed to obtain them? In this header NintendoSDK Firmware/%s (platform:NX; did:%016x; eid:lp1).

TheGreatRambler commented 1 year ago

Figured it out. For anyone else its

# Obtain device ID from prodinfo
device_id = None
with open("ConsoleData/PRODINFO.dec", mode="rb") as file:
    data = file.read()
    device_id = int(data[0x546:0x556].decode("ascii"), 16)
TheGreatRambler commented 1 year ago

I'm still unsure about NA_ID however

TheGreatRambler commented 1 year ago

ERROR:nintendo.dragons:Dragons server returned an error: {'type': 'https://problems.dragons.nintendo.net/errors/v1/400/invalid_parameter', 'title': 'Parameter is invalid', 'detail': '', 'number': 400} with account_id.

kinnay commented 1 year ago

Huh weird, I hope you're not banned. On my system, the na_id is indeed the same as the account_id of the elicense. Maybe check if you got it right with a man-in-the-middle on your Switch?

TheGreatRambler commented 1 year ago

I can't actually MITM this one since the physical switch is with someone else, oh no

TheGreatRambler commented 1 year ago

Which elicense_id should I use since there are many? I've been doing the first

TheGreatRambler commented 1 year ago

None of them work anyway.

kinnay commented 1 year ago

Did you check the rights id? This should be the same as the title id.

There are some exceptions, but in general, I have only one elicense for a given rights id.

kinnay commented 1 year ago

I just tested it again, with Tetris 99. Works fine here.

TheGreatRambler commented 1 year ago

Interesting, it does not.

TheGreatRambler commented 1 year ago

Aha, apparently Super Mario Maker 2 is not on this switch (anymore?) I think I'll figure this out now

TheGreatRambler commented 1 year ago

Okay I've confirmed Super Mario Maker 2 is on the switch, the only games that have elicenses however are Smash Ultimate DLCs and Among Us. Do elicenses not get automatically generated for every game you go online in?

TheGreatRambler commented 1 year ago

When downloaded Tetris99 does not show up as an elicense either.

kinnay commented 1 year ago

I think I got the elicense right after I downloaded the game. I have no idea why it doesn't work for you :confused:

kinnay commented 1 year ago

I would really recommend doing a mitm if there is any way that you can get your hands on the Switch. That is the safest way to figure out what your Switch is doing, and what's different.

TheGreatRambler commented 1 year ago

I can't do it myself but I'll help the owner do that

TheGreatRambler commented 1 year ago

Do you have some example code of using publish_device_linked_elicenses btw?

TheGreatRambler commented 1 year ago

I've isolated it down to the header AccountAuthorization in /v1/rights/publish_elicenses. Getting a token with dauth.ACCOUNT returns invalid token however. The request returns no elicenses currently. [image: image.png]

On Sat, Nov 19, 2022 at 2:18 PM Yannik Marchand @.***> wrote:

I would really recommend doing a mitm if there is any way that you can get your hands on the Switch. That is the safest way to figure out what your Switch is doing, and what's different.

— Reply to this email directly, view it on GitHub https://github.com/kinnay/NintendoClients/issues/90#issuecomment-1320961424, or unsubscribe https://github.com/notifications/unsubscribe-auth/AHTNY2GUX3BP7ODWHWGDUATWJEYYLANCNFSM6AAAAAARDGSXCM . You are receiving this because you were mentioned.Message ID: @.***>

kinnay commented 1 year ago

Yeah the AccountAuthorization header is not a dauth token. It is an id token from https://accounts.nintendo.com.

I can't see your image btw.

Do you have some example code of using publish_device_linked_elicenses btw?

Maybe something like this:

from nintendo.dauth import DAuthClient
from nintendo.dragons import DragonsClient
from nintendo import switch
import anyio

async def main():
    keys = switch.load_keys("/path/to/prod.keys")

    info = switch.ProdInfo(keys, "/path/to/PRODINFO")
    cert = info.get_tls_cert()
    pkey = info.get_tls_key()

    dauth = DAuthClient(keys)
    dauth.set_certificate(cert, pkey)
    response = await dauth.device_token(dauth.DRAGONS)
    device_token = response["device_auth_token"]

    dragons = DragonsClient(info.get_device_id())
    dragons.set_certificate(cert, pkey)
    print(await dragons.publish_device_linked_elicenses(device_token))
anyio.run(main)
TheGreatRambler commented 1 year ago

It looked exactly like that (I've since removed it from my codebase but it did follow that structure), but I learned why my elicense doesn't show. Mine is marked as temporary and not a device elicense, so it can only be seen in publish_elicences which shows more than just device elicenses. publish_elicences also have expiration times you have to respect. The image I shared is here, it's just the headers captured during this session https://imgur.com/a/hp6ZkWU. How can I obtain that id token btw?

On Thu, Dec 1, 2022 at 4:27 PM Yannik Marchand @.***> wrote:

Yeah the AccountAuthorization header is not a dauth token. It is an id token from https://accounts.nintendo.com.

I can't see your image btw.

Do you have some example code of using publish_device_linked_elicenses btw?

Maybe something like this:

from nintendo.dauth import DAuthClientfrom nintendo.dragons import DragonsClientfrom nintendo import switchimport anyio async def main(): keys = switch.load_keys("/path/to/prod.keys")

info = switch.ProdInfo(keys, "/path/to/PRODINFO")
cert = info.get_tls_cert()
pkey = info.get_tls_key()

dauth = DAuthClient(keys)
dauth.set_certificate(cert, pkey)
response = await dauth.device_token(dauth.DRAGONS)
device_token = response["device_auth_token"]

dragons = DragonsClient(info.get_device_id())
dragons.set_certificate(cert, pkey)
print(await dragons.publish_device_linked_elicenses(device_token))anyio.run(main)

— Reply to this email directly, view it on GitHub https://github.com/kinnay/NintendoClients/issues/90#issuecomment-1334527762, or unsubscribe https://github.com/notifications/unsubscribe-auth/AHTNY2ELCP5WO3TIJEL6PRDWLEQ5XANCNFSM6AAAAAARDGSXCM . You are receiving this because you were mentioned.Message ID: @.***>

kinnay commented 1 year ago

Is it possible that this is a non-primary Switch? That might explain why your license is temporary. This sounds like you only get a permanent license on the primary Switch.

https://accounts.nintendo.com uses OAuth. A bit of it is explained here, but I don't really know the details yet.