@ -43,6 +43,10 @@ const ResultCode ERROR_TOO_MANY_CLIENT_CERTS = // 0xD8A0A0CB
ErrorLevel : : Permanent ) ;
const ResultCode ERROR_WRONG_CERT_ID = // 0xD8E0B839
ResultCode ( 57 , ErrorModule : : SSL , ErrorSummary : : InvalidArgument , ErrorLevel : : Permanent ) ;
const ResultCode ERROR_WRONG_CERT_HANDLE = // 0xD8A0A0C9
ResultCode ( 201 , ErrorModule : : HTTP , ErrorSummary : : InvalidState , ErrorLevel : : Permanent ) ;
const ResultCode ERROR_CERT_ALREADY_SET = // 0xD8A0A03D
ResultCode ( 61 , ErrorModule : : HTTP , ErrorSummary : : InvalidState , ErrorLevel : : Permanent ) ;
void HTTP_C : : Initialize ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx , 0x1 , 1 , 4 ) ;
@ -79,6 +83,8 @@ void HTTP_C::InitializeConnectionSession(Kernel::HLERequestContext& ctx) {
const Context : : Handle context_handle = rp . Pop < u32 > ( ) ;
u32 pid = rp . PopPID ( ) ;
LOG_DEBUG ( Service_HTTP , " called, context_id={} pid={} " , context_handle , pid ) ;
auto * session_data = GetSessionData ( ctx . Session ( ) ) ;
ASSERT ( session_data ) ;
@ -105,7 +111,96 @@ void HTTP_C::InitializeConnectionSession(Kernel::HLERequestContext& ctx) {
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( RESULT_SUCCESS ) ;
LOG_DEBUG ( Service_HTTP , " called, context_id={} pid={} " , context_handle , pid ) ;
}
void HTTP_C : : BeginRequest ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx , 0x9 , 1 , 0 ) ;
const Context : : Handle context_handle = rp . Pop < u32 > ( ) ;
LOG_WARNING ( Service_HTTP , " (STUBBED) called, context_id={} " , context_handle ) ;
auto * session_data = GetSessionData ( ctx . Session ( ) ) ;
ASSERT ( session_data ) ;
if ( ! session_data - > initialized ) {
LOG_ERROR ( Service_HTTP , " Tried to make a request on an uninitialized session " ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ERROR_STATE_ERROR ) ;
return ;
}
// This command can only be called with a bound context
if ( ! session_data - > current_http_context ) {
LOG_ERROR ( Service_HTTP , " Tried to make a request without a bound context " ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ResultCode ( ErrorDescription : : NotImplemented , ErrorModule : : HTTP ,
ErrorSummary : : Internal , ErrorLevel : : Permanent ) ) ;
return ;
}
if ( session_data - > current_http_context ! = context_handle ) {
LOG_ERROR (
Service_HTTP ,
" Tried to make a request on a mismatched session input context={} session context={} " ,
context_handle , * session_data - > current_http_context ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ERROR_STATE_ERROR ) ;
return ;
}
auto itr = contexts . find ( context_handle ) ;
ASSERT ( itr ! = contexts . end ( ) ) ;
// TODO(B3N30): Make the request
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( RESULT_SUCCESS ) ;
}
void HTTP_C : : BeginRequestAsync ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx , 0xA , 1 , 0 ) ;
const Context : : Handle context_handle = rp . Pop < u32 > ( ) ;
LOG_WARNING ( Service_HTTP , " (STUBBED) called, context_id={} " , context_handle ) ;
auto * session_data = GetSessionData ( ctx . Session ( ) ) ;
ASSERT ( session_data ) ;
if ( ! session_data - > initialized ) {
LOG_ERROR ( Service_HTTP , " Tried to make a request on an uninitialized session " ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ERROR_STATE_ERROR ) ;
return ;
}
// This command can only be called with a bound context
if ( ! session_data - > current_http_context ) {
LOG_ERROR ( Service_HTTP , " Tried to make a request without a bound context " ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ResultCode ( ErrorDescription : : NotImplemented , ErrorModule : : HTTP ,
ErrorSummary : : Internal , ErrorLevel : : Permanent ) ) ;
return ;
}
if ( session_data - > current_http_context ! = context_handle ) {
LOG_ERROR (
Service_HTTP ,
" Tried to make a request on a mismatched session input context={} session context={} " ,
context_handle , * session_data - > current_http_context ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ERROR_STATE_ERROR ) ;
return ;
}
auto itr = contexts . find ( context_handle ) ;
ASSERT ( itr ! = contexts . end ( ) ) ;
// TODO(B3N30): Make the request
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( RESULT_SUCCESS ) ;
}
void HTTP_C : : CreateContext ( Kernel : : HLERequestContext & ctx ) {
@ -238,6 +333,9 @@ void HTTP_C::AddRequestHeader(Kernel::HLERequestContext& ctx) {
std : : string value ( value_size - 1 , ' \0 ' ) ;
value_buffer . Read ( & value [ 0 ] , 0 , value_size - 1 ) ;
LOG_DEBUG ( Service_HTTP , " called, name={}, value={}, context_handle={} " , name , value ,
context_handle ) ;
auto * session_data = GetSessionData ( ctx . Session ( ) ) ;
ASSERT ( session_data ) ;
@ -294,9 +392,6 @@ void HTTP_C::AddRequestHeader(Kernel::HLERequestContext& ctx) {
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 2 ) ;
rb . Push ( RESULT_SUCCESS ) ;
rb . PushMappedBuffer ( value_buffer ) ;
LOG_DEBUG ( Service_HTTP , " called, name={}, value={}, context_handle={} " , name , value ,
context_handle ) ;
}
void HTTP_C : : AddPostDataAscii ( Kernel : : HLERequestContext & ctx ) {
@ -314,6 +409,9 @@ void HTTP_C::AddPostDataAscii(Kernel::HLERequestContext& ctx) {
std : : string value ( value_size - 1 , ' \0 ' ) ;
value_buffer . Read ( & value [ 0 ] , 0 , value_size - 1 ) ;
LOG_DEBUG ( Service_HTTP , " called, name={}, value={}, context_handle={} " , name , value ,
context_handle ) ;
auto * session_data = GetSessionData ( ctx . Session ( ) ) ;
ASSERT ( session_data ) ;
@ -369,9 +467,93 @@ void HTTP_C::AddPostDataAscii(Kernel::HLERequestContext& ctx) {
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 2 ) ;
rb . Push ( RESULT_SUCCESS ) ;
rb . PushMappedBuffer ( value_buffer ) ;
}
LOG_DEBUG ( Service_HTTP , " called, name={}, value={}, context_handle={} " , name , value ,
context_handle ) ;
void HTTP_C : : SetClientCertContext ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx , 0x29 , 2 , 0 ) ;
const u32 context_handle = rp . Pop < u32 > ( ) ;
const u32 client_cert_handle = rp . Pop < u32 > ( ) ;
LOG_DEBUG ( Service_HTTP , " called with context_handle={} client_cert_handle={} " , context_handle ,
client_cert_handle ) ;
auto * session_data = GetSessionData ( ctx . Session ( ) ) ;
ASSERT ( session_data ) ;
if ( ! session_data - > initialized ) {
LOG_ERROR ( Service_HTTP , " Tried to set client cert on an uninitialized session " ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ERROR_STATE_ERROR ) ;
return ;
}
// This command can only be called with a bound context
if ( ! session_data - > current_http_context ) {
LOG_ERROR ( Service_HTTP , " Tried to set client cert without a bound context " ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ResultCode ( ErrorDescription : : NotImplemented , ErrorModule : : HTTP ,
ErrorSummary : : Internal , ErrorLevel : : Permanent ) ) ;
return ;
}
if ( session_data - > current_http_context ! = context_handle ) {
LOG_ERROR ( Service_HTTP ,
" Tried to add set client cert on a mismatched session input context={} session "
" context={} " ,
context_handle , * session_data - > current_http_context ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ERROR_STATE_ERROR ) ;
return ;
}
auto http_context_itr = contexts . find ( context_handle ) ;
ASSERT ( http_context_itr ! = contexts . end ( ) ) ;
auto cert_context_itr = client_certs . find ( client_cert_handle ) ;
if ( cert_context_itr = = client_certs . end ( ) ) {
LOG_ERROR ( Service_HTTP , " called with wrong client_cert_handle {} " , client_cert_handle ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ERROR_WRONG_CERT_HANDLE ) ;
return ;
}
if ( http_context_itr - > second . ssl_config . client_cert_ctx . lock ( ) ) {
LOG_ERROR ( Service_HTTP ,
" Tried to set a client cert to a context that already has a client cert " ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ERROR_CERT_ALREADY_SET ) ;
return ;
}
if ( http_context_itr - > second . state ! = RequestState : : NotStarted ) {
LOG_ERROR ( Service_HTTP ,
" Tried to set a client cert on a context that has already been started. " ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ResultCode ( ErrCodes : : InvalidRequestState , ErrorModule : : HTTP ,
ErrorSummary : : InvalidState , ErrorLevel : : Permanent ) ) ;
return ;
}
http_context_itr - > second . ssl_config . client_cert_ctx = cert_context_itr - > second ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( RESULT_SUCCESS ) ;
}
void HTTP_C : : GetSSLError ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx , 0x2a , 2 , 0 ) ;
const u32 context_handle = rp . Pop < u32 > ( ) ;
const u32 unk = rp . Pop < u32 > ( ) ;
LOG_WARNING ( Service_HTTP , " (STUBBED) called, context_handle={}, unk={} " , context_handle , unk ) ;
auto http_context_itr = contexts . find ( context_handle ) ;
ASSERT ( http_context_itr ! = contexts . end ( ) ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 2 , 0 ) ;
rb . Push ( RESULT_SUCCESS ) ;
// Since we create the actual http/ssl context only when the request is submitted we can't check
// for SSL Errors here. Just submit no error.
rb . Push < u32 > ( 0 ) ;
}
void HTTP_C : : OpenClientCertContext ( Kernel : : HLERequestContext & ctx ) {
@ -381,6 +563,8 @@ void HTTP_C::OpenClientCertContext(Kernel::HLERequestContext& ctx) {
Kernel : : MappedBuffer & cert_buffer = rp . PopMappedBuffer ( ) ;
Kernel : : MappedBuffer & key_buffer = rp . PopMappedBuffer ( ) ;
LOG_DEBUG ( Service_HTTP , " called, cert_size {}, key_size {} " , cert_size , key_size ) ;
auto * session_data = GetSessionData ( ctx . Session ( ) ) ;
ASSERT ( session_data ) ;
@ -396,18 +580,17 @@ void HTTP_C::OpenClientCertContext(Kernel::HLERequestContext& ctx) {
LOG_ERROR ( Service_HTTP , " tried to load more then 2 client certs " ) ;
result = ERROR_TOO_MANY_CLIENT_CERTS ;
} else {
+ + client_certs_counter ;
client_certs [ client_certs_counter ] . handle = client_certs_counter ;
client_certs [ client_certs_counter ] . certificate . resize ( cert_size ) ;
cert_buffer . Read ( & client_certs [ client_certs_counter ] . certificate [ 0 ] , 0 , cert_size ) ;
client_certs [ client_certs_counter ] . private_key . resize ( key_size ) ;
cert_buffer . Read ( & client_certs [ client_certs_counter ] . private_key [ 0 ] , 0 , key_size ) ;
client_certs [ client_certs_counter ] . session_id = session_data - > session_id ;
client_certs [ + + client_certs_counter ] = std : : make_shared < ClientCertContext > ( ) ;
client_certs [ client_certs_counter ] - > handle = client_certs_counter ;
client_certs [ client_certs_counter ] - > certificate . resize ( cert_size ) ;
cert_buffer . Read ( & client_certs [ client_certs_counter ] - > certificate [ 0 ] , 0 , cert_size ) ;
client_certs [ client_certs_counter ] - > private_key . resize ( key_size ) ;
cert_buffer . Read ( & client_certs [ client_certs_counter ] - > private_key [ 0 ] , 0 , key_size ) ;
client_certs [ client_certs_counter ] - > session_id = session_data - > session_id ;
+ + session_data - > num_client_certs ;
}
LOG_DEBUG ( Service_HTTP , " called, cert_size {}, key_size {} " , cert_size , key_size ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 4 ) ;
rb . Push ( result ) ;
rb . PushMappedBuffer ( cert_buffer ) ;
@ -418,6 +601,8 @@ void HTTP_C::OpenDefaultClientCertContext(Kernel::HLERequestContext& ctx) {
IPC : : RequestParser rp ( ctx , 0x33 , 1 , 0 ) ;
u8 cert_id = rp . Pop < u8 > ( ) ;
LOG_DEBUG ( Service_HTTP , " called, cert_id={} cert_handle={} " , cert_id , client_certs_counter ) ;
auto * session_data = GetSessionData ( ctx . Session ( ) ) ;
ASSERT ( session_data ) ;
@ -459,8 +644,8 @@ void HTTP_C::OpenDefaultClientCertContext(Kernel::HLERequestContext& ctx) {
const auto & it = std : : find_if ( client_certs . begin ( ) , client_certs . end ( ) ,
[ default_cert_id , & session_data ] ( const auto & i ) {
return default_cert_id = = i . second . cert_id & &
session_data - > session_id = = i . second . session_id ;
return default_cert_id = = i . second - > cert_id & &
session_data - > session_id = = i . second - > session_id ;
} ) ;
if ( it ! = client_certs . end ( ) ) {
@ -472,24 +657,24 @@ void HTTP_C::OpenDefaultClientCertContext(Kernel::HLERequestContext& ctx) {
return ;
}
+ + client_certs_counter ;
client_certs [ client_certs_counter ] . handle = client_certs_counter ;
client_certs [ client_certs_counter ] . certificate = ClCertA . certificate ;
client_certs [ client_certs_counter ] . private_key = ClCertA . private_key ;
client_certs [ client_certs_counter ] . session_id = session_data - > session_id ;
client_certs [ + + client_certs_counter ] = std : : make_shared < ClientCertContext > ( ) ;
client_certs [ client_certs_counter ] - > handle = client_certs_counter ;
client_certs [ client_certs_counter ] - > certificate = ClCertA . certificate ;
client_certs [ client_certs_counter ] - > private_key = ClCertA . private_key ;
client_certs [ client_certs_counter ] - > session_id = session_data - > session_id ;
+ + session_data - > num_client_certs ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 2 , 0 ) ;
rb . Push ( RESULT_SUCCESS ) ;
rb . Push < u32 > ( client_certs_counter ) ;
LOG_DEBUG ( Service_HTTP , " called, cert_id={} " , cert_id ) ;
}
void HTTP_C : : CloseClientCertContext ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx , 0x34 , 1 , 0 ) ;
ClientCertContext : : Handle cert_handle = rp . Pop < u32 > ( ) ;
LOG_DEBUG ( Service_HTTP , " called, cert_handle={} " , cert_handle ) ;
auto * session_data = GetSessionData ( ctx . Session ( ) ) ;
ASSERT ( session_data ) ;
@ -501,7 +686,7 @@ void HTTP_C::CloseClientCertContext(Kernel::HLERequestContext& ctx) {
return ;
}
if ( client_certs [ cert_handle ] . session_id ! = session_data - > session_id ) {
if ( client_certs [ cert_handle ] - > session_id ! = session_data - > session_id ) {
LOG_ERROR ( Service_HTTP , " called from another main session " ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
// This just return success without doing anything
@ -514,8 +699,6 @@ void HTTP_C::CloseClientCertContext(Kernel::HLERequestContext& ctx) {
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( RESULT_SUCCESS ) ;
LOG_DEBUG ( Service_HTTP , " called, cert_handle={} " , cert_handle ) ;
}
void HTTP_C : : Finalize ( Kernel : : HLERequestContext & ctx ) {
@ -614,8 +797,8 @@ HTTP_C::HTTP_C() : ServiceFramework("http:C", 32) {
{ 0x00060040 , nullptr , " GetDownloadSizeState " } ,
{ 0x00070040 , nullptr , " GetRequestError " } ,
{ 0x00080042 , & HTTP_C : : InitializeConnectionSession , " InitializeConnectionSession " } ,
{ 0x00090040 , nullptr , " BeginRequest " } ,
{ 0x000A0040 , nullptr , " BeginRequestAsync " } ,
{ 0x00090040 , & HTTP_C : : BeginRequest , " BeginRequest " } ,
{ 0x000A0040 , & HTTP_C : : BeginRequestAsync , " BeginRequestAsync " } ,
{ 0x000B0082 , nullptr , " ReceiveData " } ,
{ 0x000C0102 , nullptr , " ReceiveDataTimeout " } ,
{ 0x000D0146 , nullptr , " SetProxy " } ,
@ -645,8 +828,8 @@ HTTP_C::HTTP_C() : ServiceFramework("http:C", 32) {
{ 0x00250080 , nullptr , " AddDefaultCert " } ,
{ 0x00260080 , nullptr , " SelectRootCertChain " } ,
{ 0x002700C4 , nullptr , " SetClientCert " } ,
{ 0x00290080 , nullptr , " SetClientCertContext " } ,
{ 0x002A0040 , nullpt r, " GetSSLError " } ,
{ 0x00290080 , & HTTP_C : : SetClientCertContext , " SetClientCertContext " } ,
{ 0x002A0040 , & HTTP_C : : GetSSLErro r, " GetSSLError " } ,
{ 0x002B0080 , nullptr , " SetSSLOpt " } ,
{ 0x002C0080 , nullptr , " SetSSLClearOpt " } ,
{ 0x002D0000 , nullptr , " CreateRootCertChain " } ,