ams_mitm: add ns:web mitm for HBL web support

This commit is contained in:
Michael Scire 2019-03-26 11:35:50 -07:00
parent ad8acaefec
commit 4ccb39a228
12 changed files with 583 additions and 1 deletions

View file

@ -26,7 +26,7 @@ endif
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source source/fs_mitm source/set_mitm source/bpc_mitm
SOURCES := source source/fs_mitm source/set_mitm source/bpc_mitm source/ns_mitm
DATA := data
INCLUDES := include ../../common/include
EXEFS_SRC := exefs_src

View file

@ -24,6 +24,7 @@
#include "fs_mitm/fsmitm_main.hpp"
#include "set_mitm/setmitm_main.hpp"
#include "bpc_mitm/bpcmitm_main.hpp"
#include "ns_mitm/nsmitm_main.hpp"
static HosThread g_module_threads[MitmModuleId_Count];
@ -35,6 +36,7 @@ static const struct {
{ &FsMitmMain, FsMitmPriority, FsMitmStackSize }, /* FsMitm */
{ &SetMitmMain, SetMitmPriority, SetMitmStackSize }, /* SetMitm */
{ &BpcMitmMain, BpcMitmPriority, BpcMitmStackSize }, /* BpcMitm */
{ &NsMitmMain, NsMitmPriority, NsMitmStackSize }, /* NsMitm */
};
void LaunchAllMitmModules() {

View file

@ -20,6 +20,7 @@ enum MitmModuleId : u32 {
MitmModuleId_FsMitm = 0,
MitmModuleId_SetMitm = 1,
MitmModuleId_BpcMitm = 2,
MitmModuleId_NsMitm = 3,
/* Always keep this at the end. */
MitmModuleId_Count,

View file

@ -0,0 +1,189 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <switch.h>
#include "ns_shim.h"
/* Command forwarders. */
Result nsGetDocumentInterfaceFwd(Service* s, NsDocumentInterface* out) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 7999;
Result rc = serviceIpcDispatch(s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
serviceCreateSubservice(&out->s, s, &r, 0);
}
}
return rc;
}
Result nsamGetApplicationContentPathFwd(Service* s, void* out, size_t out_size, u64 app_id, FsStorageId storage_id) {
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvBuffer(&c, out, out_size, 0);
struct {
u64 magic;
u64 cmd_id;
u8 storage_id;
u64 app_id;
} *raw;
raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 21;
raw->storage_id = storage_id;
raw->app_id = app_id;
Result rc = serviceIpcDispatch(s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result nsamResolveApplicationContentPathFwd(Service* s, u64 title_id, FsStorageId storage_id) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u8 storage_id;
u64 title_id;
} *raw;
raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 23;
raw->storage_id = storage_id;
raw->title_id = title_id;
Result rc = serviceIpcDispatch(s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result nsamGetRunningApplicationProgramIdFwd(Service* s, u64* out_tid, u64 app_id) {
if (hosversionBefore(6, 0, 0)) {
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
}
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u64 app_id;
} *raw;
raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 92;
raw->app_id = app_id;
Result rc = serviceIpcDispatch(s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
u64 title_id;
} *resp;
serviceIpcParse(s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
if (out_tid) {
*out_tid = resp->title_id;
}
}
}
return rc;
}
/* Web forwarders */
Result nswebGetApplicationContentPath(NsDocumentInterface* doc, void* out, size_t out_size, u64 app_id, FsStorageId storage_id) {
return nsamGetApplicationContentPathFwd(&doc->s, out, out_size, app_id, storage_id);
}
Result nswebResolveApplicationContentPath(NsDocumentInterface* doc, u64 title_id, FsStorageId storage_id) {
return nsamResolveApplicationContentPathFwd(&doc->s, title_id, storage_id);
}
Result nswebGetRunningApplicationProgramId(NsDocumentInterface* doc, u64* out_tid, u64 app_id) {
return nsamGetRunningApplicationProgramIdFwd(&doc->s, out_tid, app_id);
}

View file

@ -0,0 +1,31 @@
/**
* @file ns_shim.h
* @brief Nintendo Shell Services (ns) IPC wrapper.
* @author SciresM
* @copyright libnx Authors
*/
#pragma once
#include <switch.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
Service s;
} NsDocumentInterface;
/* Command forwarders. */
Result nsGetDocumentInterfaceFwd(Service* s, NsDocumentInterface* out);
Result nsamGetApplicationContentPathFwd(Service* s, void* out, size_t out_size, u64 app_id, FsStorageId storage_id);
Result nsamResolveApplicationContentPathFwd(Service* s, u64 title_id, FsStorageId storage_id);
Result nsamGetRunningApplicationProgramIdFwd(Service* s, u64* out_tid, u64 app_id);
Result nswebGetApplicationContentPath(NsDocumentInterface* doc, void* out, size_t out_size, u64 app_id, FsStorageId storage_id);
Result nswebResolveApplicationContentPath(NsDocumentInterface* doc, u64 title_id, FsStorageId storage_id);
Result nswebGetRunningApplicationProgramId(NsDocumentInterface* doc, u64* out_tid, u64 app_id);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mutex>
#include <switch.h>
#include <stratosphere.hpp>
#include "nsmitm_am_service.hpp"
#include "ns_shim.h"
void NsAmMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx) {
/* Nothing to do here */
}
Result NsAmMitmService::GetApplicationContentPath(OutBuffer<u8> out_path, u64 app_id, u8 storage_type) {
return nsamGetApplicationContentPathFwd(this->forward_service.get(), out_path.buffer, out_path.num_elements, app_id, static_cast<FsStorageId>(storage_type));
}
Result NsAmMitmService::ResolveApplicationContentPath(u64 title_id, u8 storage_type) {
Result rc = nsamResolveApplicationContentPathFwd(this->forward_service.get(), title_id, static_cast<FsStorageId>(storage_type));
/* Always succeed for web applet asking about HBL. */
return (Utils::IsWebAppletTid(this->title_id) && Utils::IsHblTid(title_id)) ? 0 : rc;
}
Result NsAmMitmService::GetRunningApplicationProgramId(Out<u64> out_tid, u64 app_id) {
return nsamGetRunningApplicationProgramIdFwd(this->forward_service.get(), out_tid.GetPointer(), app_id);
}

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <switch.h>
#include <stratosphere.hpp>
#include "../utils.hpp"
#include "nsmitm_service_common.hpp"
class NsAmMitmService : public IMitmServiceObject {
public:
NsAmMitmService(std::shared_ptr<Service> s, u64 pid) : IMitmServiceObject(s, pid) {
/* ... */
}
static bool ShouldMitm(u64 pid, u64 tid) {
/* We will mitm:
* - web applets, to facilitate hbl web browser launching.
*/
return Utils::IsWebAppletTid(tid);
}
static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx);
protected:
/* Overridden commands. */
Result GetApplicationContentPath(OutBuffer<u8> out_path, u64 app_id, u8 storage_type);
Result ResolveApplicationContentPath(u64 title_id, u8 storage_type);
Result GetRunningApplicationProgramId(Out<u64> out_tid, u64 app_id);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MakeServiceCommandMeta<NsSrvCmd_GetApplicationContentPath, &NsAmMitmService::GetApplicationContentPath>(),
MakeServiceCommandMeta<NsSrvCmd_ResolveApplicationContentPath, &NsAmMitmService::ResolveApplicationContentPath>(),
MakeServiceCommandMeta<NsSrvCmd_GetRunningApplicationProgramId, &NsAmMitmService::GetRunningApplicationProgramId, FirmwareVersion_600>(),
};
};

View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <cstdint>
#include <cstring>
#include <malloc.h>
#include <switch.h>
#include <atmosphere.h>
#include <stratosphere.hpp>
#include "../utils.hpp"
#include "nsmitm_main.hpp"
#include "nsmitm_am_service.hpp"
#include "nsmitm_web_service.hpp"
void NsMitmMain(void *arg) {
/* Wait for initialization to occur */
Utils::WaitSdInitialized();
/* Ensure we can talk to NS. */
{
if (R_FAILED(nsInitialize())) {
std::abort();
}
nsExit();
}
/* Create server manager */
auto server_manager = new WaitableManager(1);
/* Create ns mitm. */
if (GetRuntimeFirmwareVersion() < FirmwareVersion_300) {
AddMitmServerToManager<NsAmMitmService>(server_manager, "ns:am", 5);
} else {
AddMitmServerToManager<NsWebMitmService>(server_manager, "ns:web", 5);
}
/* Loop forever, servicing our services. */
server_manager->Process();
delete server_manager;
}

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <cstdint>
#include <cstring>
#include <malloc.h>
#include <switch.h>
#include <atmosphere.h>
#include <stratosphere.hpp>
constexpr u32 NsMitmPriority = 48;
constexpr u32 NsMitmStackSize = 0x4000;
void NsMitmMain(void *arg);

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <switch.h>
#include <stratosphere.hpp>
#include "../utils.hpp"
enum NsGetterCmd : u32 {
NsGetterCmd_GetDocumentInterface = 7999,
};
enum NsSrvCmd : u32 {
NsSrvCmd_GetApplicationContentPath = 21,
NsSrvCmd_ResolveApplicationContentPath = 23,
NsSrvCmd_GetRunningApplicationProgramId = 92,
};

View file

@ -0,0 +1,66 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mutex>
#include <switch.h>
#include <stratosphere.hpp>
#include "nsmitm_web_service.hpp"
void NsWebMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx) {
/* Nothing to do here */
}
Result NsWebMitmService::GetDocumentInterface(Out<std::shared_ptr<NsDocumentService>> out_intf) {
std::shared_ptr<NsDocumentService> intf = nullptr;
u32 out_domain_id = 0;
Result rc = 0;
ON_SCOPE_EXIT {
if (R_SUCCEEDED(rc)) {
out_intf.SetValue(std::move(intf));
if (out_intf.IsDomain()) {
out_intf.ChangeObjectId(out_domain_id);
}
}
};
/* Mount the SD card using fs.mitm's session. */
NsDocumentInterface doc;
rc = nsGetDocumentInterfaceFwd(this->forward_service.get(), &doc);
if (R_SUCCEEDED(rc)) {
intf = std::make_shared<NsDocumentService>(this->title_id, doc);
if (out_intf.IsDomain()) {
out_domain_id = doc.s.object_id;
}
}
return rc;
}
Result NsDocumentService::GetApplicationContentPath(OutBuffer<u8> out_path, u64 app_id, u8 storage_type) {
return nswebGetApplicationContentPath(this->srv.get(), out_path.buffer, out_path.num_elements, app_id, static_cast<FsStorageId>(storage_type));
}
Result NsDocumentService::ResolveApplicationContentPath(u64 title_id, u8 storage_type) {
Result rc = nswebResolveApplicationContentPath(this->srv.get(), title_id, static_cast<FsStorageId>(storage_type));
/* Always succeed for web applet asking about HBL. */
return (Utils::IsWebAppletTid(this->title_id) && Utils::IsHblTid(title_id)) ? 0 : rc;
}
Result NsDocumentService::GetRunningApplicationProgramId(Out<u64> out_tid, u64 app_id) {
return nswebGetRunningApplicationProgramId(this->srv.get(), out_tid.GetPointer(), app_id);
}

View file

@ -0,0 +1,81 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <switch.h>
#include <stratosphere.hpp>
#include "../utils.hpp"
#include "nsmitm_service_common.hpp"
#include "ns_shim.h"
class NsDocumentService : public IServiceObject {
private:
u64 title_id;
std::unique_ptr<NsDocumentInterface> srv;
public:
NsDocumentService(u64 t, NsDocumentInterface *s) : title_id(t), srv(s) {
/* ... */
}
NsDocumentService(u64 t, std::unique_ptr<NsDocumentInterface> s) : title_id(t), srv(std::move(s)) {
/* ... */
}
NsDocumentService(u64 t, NsDocumentInterface s) : title_id(t) {
srv = std::make_unique<NsDocumentInterface>(s);
}
virtual ~NsDocumentService() {
serviceClose(&srv->s);
}
private:
/* Actual command API. */
Result GetApplicationContentPath(OutBuffer<u8> out_path, u64 app_id, u8 storage_type);
Result ResolveApplicationContentPath(u64 title_id, u8 storage_type);
Result GetRunningApplicationProgramId(Out<u64> out_tid, u64 app_id);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MakeServiceCommandMeta<NsSrvCmd_GetApplicationContentPath, &NsDocumentService::GetApplicationContentPath>(),
MakeServiceCommandMeta<NsSrvCmd_ResolveApplicationContentPath, &NsDocumentService::ResolveApplicationContentPath>(),
MakeServiceCommandMeta<NsSrvCmd_GetRunningApplicationProgramId, &NsDocumentService::GetRunningApplicationProgramId, FirmwareVersion_600>(),
};
};
class NsWebMitmService : public IMitmServiceObject {
public:
NsWebMitmService(std::shared_ptr<Service> s, u64 pid) : IMitmServiceObject(s, pid) {
/* ... */
}
static bool ShouldMitm(u64 pid, u64 tid) {
/* We will mitm:
* - web applets, to facilitate hbl web browser launching.
*/
return Utils::IsWebAppletTid(tid);
}
static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx);
protected:
/* Overridden commands. */
Result GetDocumentInterface(Out<std::shared_ptr<NsDocumentService>> out_intf);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MakeServiceCommandMeta<NsGetterCmd_GetDocumentInterface, &NsWebMitmService::GetDocumentInterface, FirmwareVersion_300>(),
};
};