ams_mitm: implement ns.mitm

This commit is contained in:
Michael Scire 2019-12-07 03:21:53 -08:00 committed by SciresM
parent 2bae1ad116
commit 66372e2b2e
10 changed files with 296 additions and 12 deletions

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2018-2019 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 <stratosphere.hpp>
#include "ns_am_mitm_service.hpp"
#include "ns_shim.h"
namespace ams::mitm::ns {
Result NsAmMitmService::GetApplicationContentPath(const sf::OutBuffer &out_path, ncm::ProgramId application_id, u8 content_type) {
return nsamGetApplicationContentPathFwd(this->forward_service.get(), out_path.GetPointer(), out_path.GetSize(), static_cast<u64>(application_id), static_cast<NcmContentType>(content_type));
}
Result NsAmMitmService::ResolveApplicationContentPath(ncm::ProgramId application_id, u8 content_type) {
/* Always succeed for web applets asking about HBL. */
/* This enables hbl html. */
bool is_hbl;
if (R_SUCCEEDED(pm::info::IsHblProgramId(&is_hbl, application_id)) && is_hbl) {
nsamResolveApplicationContentPathFwd(this->forward_service.get(), static_cast<u64>(application_id), static_cast<NcmContentType>(content_type));
return ResultSuccess();
}
return nsamResolveApplicationContentPathFwd(this->forward_service.get(), static_cast<u64>(application_id), static_cast<NcmContentType>(content_type));
}
Result NsAmMitmService::GetRunningApplicationProgramId(sf::Out<ncm::ProgramId> out, ncm::ProgramId application_id) {
return nsamGetRunningApplicationProgramIdFwd(this->forward_service.get(), reinterpret_cast<u64 *>(out.GetPointer()), static_cast<u64>(application_id));
}
}

View file

@ -18,23 +18,32 @@
namespace ams::mitm::ns { namespace ams::mitm::ns {
class NsAmMitmService : public sf::IMitmServiceObject { class NsAmMitmService : public sf::IMitmServiceObject {
private: private:
enum class CommandId { enum class CommandId {
/* TODO */ GetApplicationContentPath = 21,
ResolveApplicationContentPath = 23,
GetRunningApplicationProgramId = 92,
}; };
public: public:
static bool ShouldMitm(const sm::MitmProcessInfo &client_info) { static bool ShouldMitm(const sm::MitmProcessInfo &client_info) {
/* TODO */ /* We will mitm:
return false; * - web applets, to facilitate hbl web browser launching.
*/
return ncm::IsWebAppletProgramId(client_info.program_id);
} }
public: public:
SF_MITM_SERVICE_OBJECT_CTOR(NsAmMitmService) { /* ... */ } SF_MITM_SERVICE_OBJECT_CTOR(NsAmMitmService) { /* ... */ }
protected: protected:
/* TODO */ /* Actual command API. */
Result GetApplicationContentPath(const sf::OutBuffer &out_path, ncm::ProgramId application_id, u8 content_type);
Result ResolveApplicationContentPath(ncm::ProgramId application_id, u8 content_type);
Result GetRunningApplicationProgramId(sf::Out<ncm::ProgramId> out, ncm::ProgramId application_id);
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
/* TODO */ MAKE_SERVICE_COMMAND_META(GetApplicationContentPath),
MAKE_SERVICE_COMMAND_META(ResolveApplicationContentPath),
MAKE_SERVICE_COMMAND_META(GetRunningApplicationProgramId, hos::Version_600),
}; };
}; };

View file

@ -0,0 +1,85 @@
/*
* Copyright (c) 2018-2019 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) {
return serviceDispatch(s, 7999,
.out_num_objects = 1,
.out_objects = &out->s,
);
}
static Result _nsGetApplicationContentPath(Service *s, void* out, size_t out_size, u64 app_id, NcmContentType content_type) {
const struct {
u8 content_type;
u64 app_id;
} in = { content_type, app_id };
return serviceDispatchIn(s, 21, in,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { out, out_size } },
);
}
static Result _nsResolveApplicationContentPath(Service* s, u64 app_id, NcmContentType content_type) {
const struct {
u8 content_type;
u64 app_id;
} in = { content_type, app_id };
return serviceDispatchIn(s, 23, in);
}
static Result _nsGetRunningApplicationProgramId(Service* s, u64* out_program_id, u64 app_id) {
if (hosversionBefore(6, 0, 0)) {
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
}
return serviceDispatchInOut(s, 92, app_id, *out_program_id);
}
/* Application Manager forwarders. */
Result nsamGetApplicationContentPathFwd(Service* s, void* out, size_t out_size, u64 app_id, NcmContentType content_type) {
return _nsGetApplicationContentPath(s, out, out_size, app_id, content_type);
}
Result nsamResolveApplicationContentPathFwd(Service* s, u64 app_id, NcmContentType content_type) {
return _nsResolveApplicationContentPath(s, app_id, content_type);
}
Result nsamGetRunningApplicationProgramIdFwd(Service* s, u64* out_program_id, u64 app_id) {
return _nsGetRunningApplicationProgramId(s, out_program_id, app_id);
}
/* Web forwarders */
Result nswebGetApplicationContentPath(NsDocumentInterface* doc, void* out, size_t out_size, u64 app_id, NcmContentType content_type) {
return _nsGetApplicationContentPath(&doc->s, out, out_size, app_id, content_type);
}
Result nswebResolveApplicationContentPath(NsDocumentInterface* doc, u64 app_id, NcmContentType content_type) {
return _nsResolveApplicationContentPath(&doc->s, app_id, content_type);
}
Result nswebGetRunningApplicationProgramId(NsDocumentInterface* doc, u64* out_program_id, u64 app_id) {
return _nsGetRunningApplicationProgramId(&doc->s, out_program_id, app_id);
}
void nsDocumentInterfaceClose(NsDocumentInterface* doc) {
serviceClose(&doc->s);
}

View file

@ -0,0 +1,33 @@
/**
* @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, NcmContentType content_type);
Result nsamResolveApplicationContentPathFwd(Service* s, u64 app_id, NcmContentType content_type);
Result nsamGetRunningApplicationProgramIdFwd(Service* s, u64* out_program_id, u64 app_id);
Result nswebGetApplicationContentPath(NsDocumentInterface* doc, void* out, size_t out_size, u64 app_id, NcmContentType content_type);
Result nswebResolveApplicationContentPath(NsDocumentInterface* doc, u64 app_id, NcmContentType content_type);
Result nswebGetRunningApplicationProgramId(NsDocumentInterface* doc, u64* out_program_id, u64 app_id);
void nsDocumentInterfaceClose(NsDocumentInterface* doc);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2018-2019 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 <stratosphere.hpp>
#include "ns_web_mitm_service.hpp"
namespace ams::mitm::ns {
Result NsDocumentService::GetApplicationContentPath(const sf::OutBuffer &out_path, ncm::ProgramId application_id, u8 content_type) {
return nswebGetApplicationContentPath(this->srv.get(), out_path.GetPointer(), out_path.GetSize(), static_cast<u64>(application_id), static_cast<NcmContentType>(content_type));
}
Result NsDocumentService::ResolveApplicationContentPath(ncm::ProgramId application_id, u8 content_type) {
/* Always succeed for web applets asking about HBL. */
/* This enables hbl html. */
bool is_hbl;
if (R_SUCCEEDED(pm::info::IsHblProgramId(&is_hbl, application_id)) && is_hbl) {
nswebResolveApplicationContentPath(this->srv.get(), static_cast<u64>(application_id), static_cast<NcmContentType>(content_type));
return ResultSuccess();
}
return nswebResolveApplicationContentPath(this->srv.get(), static_cast<u64>(application_id), static_cast<NcmContentType>(content_type));
}
Result NsDocumentService::GetRunningApplicationProgramId(sf::Out<ncm::ProgramId> out, ncm::ProgramId application_id) {
return nswebGetRunningApplicationProgramId(this->srv.get(), reinterpret_cast<u64 *>(out.GetPointer()), static_cast<u64>(application_id));
}
Result NsWebMitmService::GetDocumentInterface(sf::Out<std::shared_ptr<NsDocumentService>> out) {
/* Open a document interface. */
NsDocumentInterface doc;
R_TRY(nsGetDocumentInterfaceFwd(this->forward_service.get(), &doc));
const sf::cmif::DomainObjectId target_object_id{serviceGetObjectId(&doc.s)};
out.SetValue(std::make_shared<NsDocumentService>(this->client_info, std::make_unique<NsDocumentInterface>(doc)), target_object_id);
return ResultSuccess();
}
}

View file

@ -16,25 +16,58 @@
#pragma once #pragma once
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "ns_shim.h"
namespace ams::mitm::ns { namespace ams::mitm::ns {
class NsDocumentService : public sf::IServiceObject {
private:
enum class CommandId {
GetApplicationContentPath = 21,
ResolveApplicationContentPath = 23,
GetRunningApplicationProgramId = 92,
};
private:
sm::MitmProcessInfo client_info;
std::unique_ptr<::NsDocumentInterface> srv;
public:
NsDocumentService(const sm::MitmProcessInfo &cl, std::unique_ptr<::NsDocumentInterface> s) : client_info(cl), srv(std::move(s)) { /* .. */ }
virtual ~NsDocumentService() {
nsDocumentInterfaceClose(this->srv.get());
}
protected:
/* Actual command API. */
Result GetApplicationContentPath(const sf::OutBuffer &out_path, ncm::ProgramId application_id, u8 content_type);
Result ResolveApplicationContentPath(ncm::ProgramId application_id, u8 content_type);
Result GetRunningApplicationProgramId(sf::Out<ncm::ProgramId> out, ncm::ProgramId application_id);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetApplicationContentPath),
MAKE_SERVICE_COMMAND_META(ResolveApplicationContentPath),
MAKE_SERVICE_COMMAND_META(GetRunningApplicationProgramId, hos::Version_600),
};
};
class NsWebMitmService : public sf::IMitmServiceObject { class NsWebMitmService : public sf::IMitmServiceObject {
private: private:
enum class CommandId { enum class CommandId {
/* TODO */ GetDocumentInterface = 7999,
}; };
public: public:
static bool ShouldMitm(const sm::MitmProcessInfo &client_info) { static bool ShouldMitm(const sm::MitmProcessInfo &client_info) {
/* TODO */ /* We will mitm:
return false; * - web applets, to facilitate hbl web browser launching.
*/
return ncm::IsWebAppletProgramId(client_info.program_id);
} }
public: public:
SF_MITM_SERVICE_OBJECT_CTOR(NsWebMitmService) { /* ... */ } SF_MITM_SERVICE_OBJECT_CTOR(NsWebMitmService) { /* ... */ }
protected: protected:
/* TODO */ Result GetDocumentInterface(sf::Out<std::shared_ptr<NsDocumentService>> out);
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
/* TODO */ MAKE_SERVICE_COMMAND_META(GetDocumentInterface),
}; };
}; };

View file

@ -421,6 +421,14 @@ namespace ams::ncm {
return ProgramId::ApplicationStart <= program_id && program_id <= ProgramId::ApplicationEnd; return ProgramId::ApplicationStart <= program_id && program_id <= ProgramId::ApplicationEnd;
} }
inline constexpr bool IsWebAppletProgramId(const ProgramId &program_id) {
return program_id == ProgramId::AppletWeb ||
program_id == ProgramId::AppletShop ||
program_id == ProgramId::AppletOfflineWeb ||
program_id == ProgramId::AppletLoginShare ||
program_id == ProgramId::AppletWifiWebAuth;
}
static_assert(sizeof(ProgramId) == sizeof(u64) && std::is_pod<ProgramId>::value, "ProgramId definition!"); static_assert(sizeof(ProgramId) == sizeof(u64) && std::is_pod<ProgramId>::value, "ProgramId definition!");
/* Program Location. */ /* Program Location. */

View file

@ -31,4 +31,7 @@ namespace ams::pm::info {
/* Information convenience API. */ /* Information convenience API. */
bool HasLaunchedProgram(ncm::ProgramId program_id); bool HasLaunchedProgram(ncm::ProgramId program_id);
Result IsHblProcessId(bool *out, os::ProcessId process_id);
Result IsHblProgramId(bool *out, ncm::ProgramId program_id);
} }

View file

@ -20,7 +20,10 @@
namespace ams::sf { namespace ams::sf {
class IServiceObject{}; class IServiceObject {
public:
virtual ~IServiceObject() { /* ... */ }
};
class IMitmServiceObject : public IServiceObject { class IMitmServiceObject : public IServiceObject {
protected: protected:
@ -29,6 +32,8 @@ namespace ams::sf {
public: public:
IMitmServiceObject(std::shared_ptr<::Service> &&s, const sm::MitmProcessInfo &c) : forward_service(std::move(s)), client_info(c) { /* ... */ } IMitmServiceObject(std::shared_ptr<::Service> &&s, const sm::MitmProcessInfo &c) : forward_service(std::move(s)), client_info(c) { /* ... */ }
virtual ~IMitmServiceObject() { /* ... */ }
static bool ShouldMitm(os::ProcessId process_id, ncm::ProgramId program_id); static bool ShouldMitm(os::ProcessId process_id, ncm::ProgramId program_id);
}; };

View file

@ -73,4 +73,21 @@ namespace ams::pm::info {
return has_launched; return has_launched;
} }
Result IsHblProcessId(bool *out, os::ProcessId process_id) {
ncm::ProgramLocation loc;
cfg::OverrideStatus override_status;
R_TRY(GetProcessInfo(&loc, &override_status, process_id));
*out = override_status.IsHbl();
return ResultSuccess();
}
Result IsHblProgramId(bool *out, ncm::ProgramId program_id) {
os::ProcessId process_id;
R_TRY(GetProcessId(&process_id, program_id));
return IsHblProcessId(out, process_id);
}
} }