81 lines
3.7 KiB
C
81 lines
3.7 KiB
C
// Entwickler-Werkzeuge nur für Admins - und nur, wenn der Server es gerade bestätigt hat:
|
|
// 1. Die App liest aus dem Konto-Dienst (act) die Tokens des angemeldeten MBMNET-Kontos. Die hat nur ein 3DS,
|
|
// auf dem man sich wirklich mit diesem Konto angemeldet hat (ausgestellt vom MBMNET-Account-Server).
|
|
// 2. Sie schickt sie per HTTPS (MBMNET-CA) an /mbmnet/admin-check. Der Server prüft sie gegen seine
|
|
// Datenbank und antwortet admin=1 nur für Admins.
|
|
// Nichts wird gemerkt: Ohne Antwort vom Server (offline, Nintendo aktiv, kein MBMNET-Konto) keine Werkzeuge.
|
|
#include <3ds.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "admin.h"
|
|
#include "https.h"
|
|
|
|
#define OLD_CACHE_FILE "sdmc:/3ds/mbmnet/admin" // gemerkte Antwort älterer Versionen (wird gelöscht)
|
|
|
|
static volatile bool isAdmin;
|
|
static char server[64];
|
|
static char why[96] = "Werkzeuge: kein MBMNET-Konto angemeldet."; // warum (noch) keine Werkzeuge
|
|
static Result lastAct; // letzter Fehler von act (für die Wiederholung)
|
|
static bool wanted; // MBMNET-Konto angemeldet: prüfen
|
|
|
|
// Liest die Tokens des angemeldeten Kontos aus dem Konto-Dienst (lokal, ohne Server-Anfrage von act) und lässt
|
|
// sie vom MBMNET-Server prüfen. Die Tokens hat dieser Server beim Anmelden ausgestellt, er kann sie selbst prüfen.
|
|
// (Früher: Service-Token über act angefordert - act lehnte das mit "ungültiger Zustand" ab, C8A14F4B.)
|
|
static void check_once(void)
|
|
{
|
|
lastAct = 0;
|
|
u8 slot = 0;
|
|
ACT_GetCommonInfo(&slot, sizeof(slot), INFO_TYPE_COMMON_CURRENT_ACCOUNT_SLOT);
|
|
static AccountAccessToken at;
|
|
memset(&at, 0, sizeof(at));
|
|
Result rc = ACT_GetAccountInfo(&at, sizeof(at), slot, INFO_TYPE_ACCOUNT_ACCESS_TOKEN);
|
|
if (R_FAILED(rc) || (!at.accessToken[0] && !at.refreshToken[0])) {
|
|
lastAct = rc;
|
|
snprintf(why, sizeof(why), "Werkzeuge: keine Anmeldung im Konto-Dienst (%08lX).\nEinmal online gehen und neu öffnen.", (unsigned long)rc);
|
|
return;
|
|
}
|
|
static char tokens[0x50];
|
|
snprintf(tokens, sizeof(tokens), "%s %s", at.accessToken[0] ? at.accessToken : "-", at.refreshToken);
|
|
memset(&at, 0, sizeof(at));
|
|
|
|
// Vom Server prüfen lassen (nur HTTPS, MBMNET-CA)
|
|
char body[32];
|
|
u32 len = 0;
|
|
Result hrc = 0;
|
|
u32 code = https_request(server, "/mbmnet/admin-check", NULL, "X-NN-Tokens", tokens, body, sizeof(body), &len, NULL, 0, &hrc);
|
|
memset(tokens, 0, sizeof(tokens));
|
|
isAdmin = code == 200 && strncmp(body, "admin=1", 7) == 0;
|
|
if (isAdmin) why[0] = 0;
|
|
else if (code == 200) snprintf(why, sizeof(why), "Werkzeuge gibt es nur für Admins.");
|
|
else if (code) snprintf(why, sizeof(why), "Werkzeuge: Server antwortet HTTP %lu.", (unsigned long)code);
|
|
else snprintf(why, sizeof(why), "Werkzeuge: keine HTTPS-Verbindung zum Server (%08lX).", (unsigned long)hrc);
|
|
}
|
|
|
|
const char *admin_why(void) { return why; }
|
|
|
|
void admin_prepare(const char *srv, bool mbmnetLoggedIn)
|
|
{
|
|
isAdmin = false;
|
|
wanted = mbmnetLoggedIn;
|
|
snprintf(why, sizeof(why), mbmnetLoggedIn ? "Werkzeuge: Server prüft noch ..."
|
|
: "Werkzeuge: nur bei aktivem MBMNET mit angemeldetem Admin-Konto.");
|
|
remove(OLD_CACHE_FILE);
|
|
snprintf(server, sizeof(server), "%s", srv);
|
|
}
|
|
|
|
void admin_check(void)
|
|
{
|
|
if (!wanted) return;
|
|
// act noch mit etwas anderem beschäftigt ("ungültiger Zustand"): kurz warten und noch einmal
|
|
for (int attempt = 0; attempt < 4; attempt++) {
|
|
check_once();
|
|
if (isAdmin || !lastAct || ((lastAct >> 21) & 0x3F) != 5) break; // 5 = InvalidState
|
|
svcSleepThread(1000ULL * 1000 * 1000);
|
|
}
|
|
}
|
|
|
|
bool admin_is(void) { return isAdmin; }
|
|
|
|
bool admin_finish(void) { return true; } // kein eigener Thread mehr (läuft im Auffrischen)
|