Skip to content

Commit efbbb81

Browse files
committed
DownloadManager: Always use Nintendo servers + additional streamlining
- Download manager now always uses Nintendo servers. Requires only a valid OTP and SEEPROM dump so you can use it in combination with a Pretendo setup even without a NNID - Account drop down removed from download manager since it's not required - Internally all our API requests now support overriding which service to use - Drop support for act-url and ecs-url command line parameters. Usage of network_services.xml ("custom" option in the UI) is preferred
1 parent 989e2b8 commit efbbb81

29 files changed

+323
-338
lines changed

src/Cafe/IOSU/legacy/iosu_boss.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ namespace iosu
498498
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, task_header_callback);
499499
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &(*it));
500500
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 0x3C);
501-
if (GetNetworkConfig().disablesslver.GetValue() && ActiveSettings::GetNetworkService() == NetworkService::Custom || ActiveSettings::GetNetworkService() == NetworkService::Pretendo) // remove Pretendo Function once SSL is in the Service
501+
if (IsNetworkServiceSSLDisabled(ActiveSettings::GetNetworkService()))
502502
{
503503
curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,0L);
504504
}

src/Cafe/IOSU/legacy/iosu_crypto.cpp

-10
Original file line numberDiff line numberDiff line change
@@ -292,16 +292,6 @@ void iosuCrypto_generateDeviceCertificate()
292292
BN_CTX_free(context);
293293
}
294294

295-
bool iosuCrypto_hasAllDataForLogin()
296-
{
297-
if (hasOtpMem == false)
298-
return false;
299-
if (hasSeepromMem == false)
300-
return false;
301-
// todo - check if certificates are available
302-
return true;
303-
}
304-
305295
sint32 iosuCrypto_getDeviceCertificateBase64Encoded(char* output)
306296
{
307297
iosuCrypto_base64Encode((uint8*)&g_wiiuDeviceCert, sizeof(g_wiiuDeviceCert), output);

src/Cafe/IOSU/legacy/iosu_crypto.h

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
void iosuCrypto_init();
44

5-
bool iosuCrypto_hasAllDataForLogin();
65
bool iosuCrypto_getDeviceId(uint32* deviceId);
76
void iosuCrypto_getDeviceSerialString(char* serialString);
87

src/Cafe/IOSU/legacy/iosu_nim.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ namespace iosu
228228
}
229229
}
230230

231-
auto result = NAPI::IDBE_Request(titleId);
231+
auto result = NAPI::IDBE_Request(ActiveSettings::GetNetworkService(), titleId);
232232
if (!result)
233233
{
234234
memset(idbeIconOutput, 0, sizeof(NAPI::IDBEIconDataV0));

src/Cafe/OS/libs/nn_idbe/nn_idbe.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ namespace nn
4242

4343
void asyncDownloadIconFile(uint64 titleId, nnIdbeEncryptedIcon_t* iconOut, OSThread_t* thread)
4444
{
45-
std::vector<uint8> idbeData = NAPI::IDBE_RequestRawEncrypted(titleId);
45+
std::vector<uint8> idbeData = NAPI::IDBE_RequestRawEncrypted(ActiveSettings::GetNetworkService(), titleId);
4646
if (idbeData.size() != sizeof(nnIdbeEncryptedIcon_t))
4747
{
4848
// icon does not exist or has the wrong size

src/Cafe/OS/libs/nn_olv/nn_olv_DownloadCommunityTypes.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ namespace nn
4343
return res;
4444

4545
CurlRequestHelper req;
46-
req.initate(reqUrl, CurlRequestHelper::SERVER_SSL_CONTEXT::OLIVE);
46+
req.initate(ActiveSettings::GetNetworkService(), reqUrl, CurlRequestHelper::SERVER_SSL_CONTEXT::OLIVE);
4747
InitializeOliveRequest(req);
4848

4949
StackAllocator<coreinit::OSEvent> requestDoneEvent;

src/Cafe/OS/libs/nn_olv/nn_olv_InitializeTypes.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ namespace nn
195195
break;
196196
}
197197

198-
req.initate(requestUrl, CurlRequestHelper::SERVER_SSL_CONTEXT::OLIVE);
198+
req.initate(ActiveSettings::GetNetworkService(), requestUrl, CurlRequestHelper::SERVER_SSL_CONTEXT::OLIVE);
199199
InitializeOliveRequest(req);
200200

201201
StackAllocator<coreinit::OSEvent> requestDoneEvent;

src/Cafe/OS/libs/nn_olv/nn_olv_UploadCommunityTypes.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ namespace nn
5050

5151

5252
CurlRequestHelper req;
53-
req.initate(requestUrl, CurlRequestHelper::SERVER_SSL_CONTEXT::OLIVE);
53+
req.initate(ActiveSettings::GetNetworkService(), requestUrl, CurlRequestHelper::SERVER_SSL_CONTEXT::OLIVE);
5454
InitializeOliveRequest(req);
5555

5656
StackAllocator<coreinit::OSEvent> requestDoneEvent;

src/Cafe/OS/libs/nn_olv/nn_olv_UploadFavoriteTypes.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ namespace nn
4040
snprintf(requestUrl, sizeof(requestUrl), "%s/v1/communities/%lu.favorite", g_DiscoveryResults.apiEndpoint, pParam->communityId.value());
4141

4242
CurlRequestHelper req;
43-
req.initate(requestUrl, CurlRequestHelper::SERVER_SSL_CONTEXT::OLIVE);
43+
req.initate(ActiveSettings::GetNetworkService(), requestUrl, CurlRequestHelper::SERVER_SSL_CONTEXT::OLIVE);
4444
InitializeOliveRequest(req);
4545

4646
StackAllocator<coreinit::OSEvent> requestDoneEvent;

src/Cemu/Tools/DownloadManager/DownloadManager.cpp

+41-89
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,7 @@ void DownloadManager::downloadTitleVersionList()
3333
{
3434
if (m_hasTitleVersionList)
3535
return;
36-
NAPI::AuthInfo authInfo;
37-
authInfo.accountId = m_authInfo.nnidAccountName;
38-
authInfo.passwordHash = m_authInfo.passwordHash;
39-
authInfo.deviceId = m_authInfo.deviceId;
40-
authInfo.serial = m_authInfo.serial;
41-
authInfo.country = m_authInfo.country;
42-
authInfo.region = m_authInfo.region;
43-
authInfo.deviceCertBase64 = m_authInfo.deviceCertBase64;
36+
NAPI::AuthInfo authInfo = GetAuthInfo(false);
4437
auto versionListVersionResult = NAPI::TAG_GetVersionListVersion(authInfo);
4538
if (!versionListVersionResult.isValid)
4639
return;
@@ -195,23 +188,14 @@ struct StoredTokenInfo : public SerializerHelper
195188

196189
bool DownloadManager::_connect_refreshIASAccountIdAndDeviceToken()
197190
{
198-
NAPI::AuthInfo authInfo;
199-
authInfo.accountId = m_authInfo.nnidAccountName;
200-
authInfo.passwordHash = m_authInfo.passwordHash;
201-
authInfo.deviceId = m_authInfo.deviceId;
202-
authInfo.serial = m_authInfo.serial;
203-
authInfo.country = m_authInfo.country;
204-
authInfo.region = m_authInfo.region;
205-
authInfo.deviceCertBase64 = m_authInfo.deviceCertBase64;
206-
191+
NAPI::AuthInfo authInfo = GetAuthInfo(false);
207192
// query IAS/ECS account id and device token (if not cached)
208193
auto rChallenge = NAPI::IAS_GetChallenge(authInfo);
209194
if (rChallenge.apiError != NAPI_RESULT::SUCCESS)
210195
return false;
211196
auto rRegistrationInfo = NAPI::IAS_GetRegistrationInfo_QueryInfo(authInfo, rChallenge.challenge);
212197
if (rRegistrationInfo.apiError != NAPI_RESULT::SUCCESS)
213198
return false;
214-
215199
m_iasToken.serviceAccountId = rRegistrationInfo.accountId;
216200
m_iasToken.deviceToken = rRegistrationInfo.deviceToken;
217201
// store to cache
@@ -221,24 +205,13 @@ bool DownloadManager::_connect_refreshIASAccountIdAndDeviceToken()
221205
std::vector<uint8> serializedData;
222206
if (!storedTokenInfo.serialize(serializedData))
223207
return false;
224-
s_nupFileCache->AddFileAsync({ fmt::format("{}/token_info", m_authInfo.nnidAccountName) }, serializedData.data(), serializedData.size());
208+
s_nupFileCache->AddFileAsync({ fmt::format("{}/token_info", m_authInfo.cachefileName) }, serializedData.data(), serializedData.size());
225209
return true;
226210
}
227211

228212
bool DownloadManager::_connect_queryAccountStatusAndServiceURLs()
229213
{
230-
NAPI::AuthInfo authInfo;
231-
authInfo.accountId = m_authInfo.nnidAccountName;
232-
authInfo.passwordHash = m_authInfo.passwordHash;
233-
authInfo.deviceId = m_authInfo.deviceId;
234-
authInfo.serial = m_authInfo.serial;
235-
authInfo.country = m_authInfo.country;
236-
authInfo.region = m_authInfo.region;
237-
authInfo.deviceCertBase64 = m_authInfo.deviceCertBase64;
238-
239-
authInfo.IASToken.accountId = m_iasToken.serviceAccountId;
240-
authInfo.IASToken.deviceToken = m_iasToken.deviceToken;
241-
214+
NAPI::AuthInfo authInfo = GetAuthInfo(true);
242215
NAPI::NAPI_ECSGetAccountStatus_Result accountStatusResult = NAPI::ECS_GetAccountStatus(authInfo);
243216
if (accountStatusResult.apiError != NAPI_RESULT::SUCCESS)
244217
{
@@ -291,7 +264,7 @@ void DownloadManager::loadTicketCache()
291264
m_ticketCache.clear();
292265
cemu_assert_debug(m_ticketCache.empty());
293266
std::vector<uint8> ticketCacheBlob;
294-
if (!s_nupFileCache->GetFile({ fmt::format("{}/eticket_cache", m_authInfo.nnidAccountName) }, ticketCacheBlob))
267+
if (!s_nupFileCache->GetFile({ fmt::format("{}/eticket_cache", m_authInfo.cachefileName) }, ticketCacheBlob))
295268
return;
296269
MemStreamReader memReader(ticketCacheBlob.data(), ticketCacheBlob.size());
297270
uint8 version = memReader.readBE<uint8>();
@@ -343,23 +316,12 @@ void DownloadManager::storeTicketCache()
343316
memWriter.writePODVector(cert);
344317
}
345318
auto serializedBlob = memWriter.getResult();
346-
s_nupFileCache->AddFileAsync({ fmt::format("{}/eticket_cache", m_authInfo.nnidAccountName) }, serializedBlob.data(), serializedBlob.size());
319+
s_nupFileCache->AddFileAsync({ fmt::format("{}/eticket_cache", m_authInfo.cachefileName) }, serializedBlob.data(), serializedBlob.size());
347320
}
348321

349322
bool DownloadManager::syncAccountTickets()
350323
{
351-
NAPI::AuthInfo authInfo;
352-
authInfo.accountId = m_authInfo.nnidAccountName;
353-
authInfo.passwordHash = m_authInfo.passwordHash;
354-
authInfo.deviceId = m_authInfo.deviceId;
355-
authInfo.serial = m_authInfo.serial;
356-
authInfo.country = m_authInfo.country;
357-
authInfo.region = m_authInfo.region;
358-
authInfo.deviceCertBase64 = m_authInfo.deviceCertBase64;
359-
360-
authInfo.IASToken.accountId = m_iasToken.serviceAccountId;
361-
authInfo.IASToken.deviceToken = m_iasToken.deviceToken;
362-
324+
NAPI::AuthInfo authInfo = GetAuthInfo(true);
363325
// query TIV list from server
364326
NAPI::NAPI_ECSAccountListETicketIds_Result resultTicketIds = NAPI::ECS_AccountListETicketIds(authInfo);
365327
if (!resultTicketIds.isValid())
@@ -425,19 +387,7 @@ bool DownloadManager::syncAccountTickets()
425387
bool DownloadManager::syncSystemTitleTickets()
426388
{
427389
setStatusMessage(_("Downloading system tickets...").utf8_string(), DLMGR_STATUS_CODE::CONNECTING);
428-
// todo - add GetAuth() function
429-
NAPI::AuthInfo authInfo;
430-
authInfo.accountId = m_authInfo.nnidAccountName;
431-
authInfo.passwordHash = m_authInfo.passwordHash;
432-
authInfo.deviceId = m_authInfo.deviceId;
433-
authInfo.serial = m_authInfo.serial;
434-
authInfo.country = m_authInfo.country;
435-
authInfo.region = m_authInfo.region;
436-
authInfo.deviceCertBase64 = m_authInfo.deviceCertBase64;
437-
438-
authInfo.IASToken.accountId = m_iasToken.serviceAccountId;
439-
authInfo.IASToken.deviceToken = m_iasToken.deviceToken;
440-
390+
NAPI::AuthInfo authInfo = GetAuthInfo(true);
441391
auto querySystemTitleTicket = [&](uint64 titleId) -> void
442392
{
443393
// check if cached already
@@ -520,8 +470,7 @@ bool DownloadManager::syncUpdateTickets()
520470
if (findTicketByTitleIdAndVersion(itr.titleId, itr.availableTitleVersion))
521471
continue;
522472

523-
NAPI::AuthInfo dummyAuth;
524-
auto cetkResult = NAPI::CCS_GetCETK(dummyAuth, itr.titleId, itr.availableTitleVersion);
473+
auto cetkResult = NAPI::CCS_GetCETK(GetDownloadMgrNetworkService(), itr.titleId, itr.availableTitleVersion);
525474
if (!cetkResult.isValid)
526475
continue;
527476
NCrypto::ETicketParser ticketParser;
@@ -657,7 +606,7 @@ void DownloadManager::_handle_connect()
657606
if (s_nupFileCache)
658607
{
659608
std::vector<uint8> serializationBlob;
660-
if (s_nupFileCache->GetFile({ fmt::format("{}/token_info", m_authInfo.nnidAccountName) }, serializationBlob))
609+
if (s_nupFileCache->GetFile({ fmt::format("{}/token_info", m_authInfo.cachefileName) }, serializationBlob))
661610
{
662611
StoredTokenInfo storedTokenInfo;
663612
if (storedTokenInfo.deserialize(serializationBlob))
@@ -683,7 +632,7 @@ void DownloadManager::_handle_connect()
683632
if (!_connect_queryAccountStatusAndServiceURLs())
684633
{
685634
m_connectState.store(CONNECT_STATE::FAILED);
686-
setStatusMessage(_("Failed to query account status. Invalid account information?").utf8_string(), DLMGR_STATUS_CODE::FAILED);
635+
setStatusMessage(_("Failed to query account status").utf8_string(), DLMGR_STATUS_CODE::FAILED);
687636
return;
688637
}
689638
// load ticket cache and sync
@@ -692,7 +641,7 @@ void DownloadManager::_handle_connect()
692641
if (!syncTicketCache())
693642
{
694643
m_connectState.store(CONNECT_STATE::FAILED);
695-
setStatusMessage(_("Failed to request tickets (invalid NNID?)").utf8_string(), DLMGR_STATUS_CODE::FAILED);
644+
setStatusMessage(_("Failed to request tickets").utf8_string(), DLMGR_STATUS_CODE::FAILED);
696645
return;
697646
}
698647
searchForIncompleteDownloads();
@@ -713,22 +662,10 @@ void DownloadManager::connect(
713662
std::string_view serial,
714663
std::string_view deviceCertBase64)
715664
{
716-
if (nnidAccountName.empty())
717-
{
718-
m_connectState.store(CONNECT_STATE::FAILED);
719-
setStatusMessage(_("This account is not linked with an NNID").utf8_string(), DLMGR_STATUS_CODE::FAILED);
720-
return;
721-
}
722665
runManager();
723666
m_authInfo.nnidAccountName = nnidAccountName;
724667
m_authInfo.passwordHash = passwordHash;
725-
if (std::all_of(m_authInfo.passwordHash.begin(), m_authInfo.passwordHash.end(), [](uint8 v) { return v == 0; }))
726-
{
727-
cemuLog_log(LogType::Force, "DLMgr: Invalid password hash");
728-
m_connectState.store(CONNECT_STATE::FAILED);
729-
setStatusMessage(_("Failed. Account does not have password set").utf8_string(), DLMGR_STATUS_CODE::FAILED);
730-
return;
731-
}
668+
m_authInfo.cachefileName = nnidAccountName.empty() ? "DefaultName" : nnidAccountName;
732669
m_authInfo.region = region;
733670
m_authInfo.country = country;
734671
m_authInfo.deviceCertBase64 = deviceCertBase64;
@@ -744,6 +681,31 @@ bool DownloadManager::IsConnected() const
744681
return m_connectState.load() != CONNECT_STATE::UNINITIALIZED;
745682
}
746683

684+
NetworkService DownloadManager::GetDownloadMgrNetworkService()
685+
{
686+
return NetworkService::Nintendo;
687+
}
688+
689+
NAPI::AuthInfo DownloadManager::GetAuthInfo(bool withIasToken)
690+
{
691+
NAPI::AuthInfo authInfo;
692+
authInfo.serviceOverwrite = GetDownloadMgrNetworkService();
693+
authInfo.accountId = m_authInfo.nnidAccountName;
694+
authInfo.passwordHash = m_authInfo.passwordHash;
695+
authInfo.deviceId = m_authInfo.deviceId;
696+
authInfo.serial = m_authInfo.serial;
697+
authInfo.country = m_authInfo.country;
698+
authInfo.region = m_authInfo.region;
699+
authInfo.deviceCertBase64 = m_authInfo.deviceCertBase64;
700+
if(withIasToken)
701+
{
702+
cemu_assert_debug(!m_iasToken.serviceAccountId.empty());
703+
authInfo.IASToken.accountId = m_iasToken.serviceAccountId;
704+
authInfo.IASToken.deviceToken = m_iasToken.deviceToken;
705+
}
706+
return authInfo;
707+
}
708+
747709
/* package / downloading */
748710

749711
// start/resume/retry download
@@ -1022,17 +984,7 @@ void DownloadManager::reportPackageProgress(Package* package, uint32 currentProg
1022984

1023985
void DownloadManager::asyncPackageDownloadTMD(Package* package)
1024986
{
1025-
NAPI::AuthInfo authInfo;
1026-
authInfo.accountId = m_authInfo.nnidAccountName;
1027-
authInfo.passwordHash = m_authInfo.passwordHash;
1028-
authInfo.deviceId = m_authInfo.deviceId;
1029-
authInfo.serial = m_authInfo.serial;
1030-
authInfo.country = m_authInfo.country;
1031-
authInfo.region = m_authInfo.region;
1032-
authInfo.deviceCertBase64 = m_authInfo.deviceCertBase64;
1033-
authInfo.IASToken.accountId = m_iasToken.serviceAccountId;
1034-
authInfo.IASToken.deviceToken = m_iasToken.deviceToken;
1035-
987+
NAPI::AuthInfo authInfo = GetAuthInfo(true);
1036988
TitleIdParser titleIdParser(package->titleId);
1037989
NAPI::NAPI_CCSGetTMD_Result tmdResult;
1038990
if (titleIdParser.GetType() == TitleIdParser::TITLE_TYPE::AOC)
@@ -1196,7 +1148,7 @@ void DownloadManager::asyncPackageDownloadContentFile(Package* package, uint16 i
11961148
setPackageError(package, _("Cannot create file").utf8_string());
11971149
return;
11981150
}
1199-
if (!NAPI::CCS_GetContentFile(titleId, contentId, CallbackInfo::writeCallback, &callbackInfoData))
1151+
if (!NAPI::CCS_GetContentFile(GetDownloadMgrNetworkService(), titleId, contentId, CallbackInfo::writeCallback, &callbackInfoData))
12001152
{
12011153
setPackageError(package, _("Download failed").utf8_string());
12021154
delete callbackInfoData.fileOutput;
@@ -1490,7 +1442,7 @@ void DownloadManager::prepareIDBE(uint64 titleId)
14901442
if (s_nupFileCache->GetFile({ fmt::format("idbe/{0:016x}", titleId) }, idbeFile) && idbeFile.size() == sizeof(NAPI::IDBEIconDataV0))
14911443
return addToCache(titleId, (NAPI::IDBEIconDataV0*)(idbeFile.data()));
14921444
// not cached, query from server
1493-
std::optional<NAPI::IDBEIconDataV0> iconData = NAPI::IDBE_Request(titleId);
1445+
std::optional<NAPI::IDBEIconDataV0> iconData = NAPI::IDBE_Request(GetDownloadMgrNetworkService(), titleId);
14941446
if (!iconData)
14951447
return;
14961448
s_nupFileCache->AddFileAsync({ fmt::format("idbe/{0:016x}", titleId) }, (uint8*)&(*iconData), sizeof(NAPI::IDBEIconDataV0));

src/Cemu/Tools/DownloadManager/DownloadManager.h

+8-8
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,14 @@
22
#include "util/helpers/Semaphore.h"
33
#include "Cemu/ncrypto/ncrypto.h"
44
#include "Cafe/TitleList/TitleId.h"
5-
65
#include "util/helpers/ConcurrentQueue.h"
6+
#include "config/NetworkSettings.h"
77

8-
#include <functional>
9-
#include <optional>
10-
11-
#include <future>
12-
8+
// forward declarations
139
namespace NAPI
1410
{
1511
struct IDBEIconDataV0;
12+
struct AuthInfo;
1613
}
1714

1815
namespace NCrypto
@@ -86,7 +83,6 @@ class DownloadManager
8683

8784
bool IsConnected() const;
8885

89-
9086
private:
9187
/* connect / login */
9288

@@ -101,6 +97,7 @@ class DownloadManager
10197

10298
struct
10399
{
100+
std::string cachefileName;
104101
std::string nnidAccountName;
105102
std::array<uint8, 32> passwordHash;
106103
std::string deviceCertBase64;
@@ -122,7 +119,10 @@ class DownloadManager
122119
void _handle_connect();
123120
bool _connect_refreshIASAccountIdAndDeviceToken();
124121
bool _connect_queryAccountStatusAndServiceURLs();
125-
122+
123+
NetworkService GetDownloadMgrNetworkService();
124+
NAPI::AuthInfo GetAuthInfo(bool withIasToken);
125+
126126
/* idbe cache */
127127
public:
128128
void prepareIDBE(uint64 titleId);

0 commit comments

Comments
 (0)