Ctrl Request

This commit is contained in:
Florian Märkl 2018-11-17 20:08:51 +01:00
commit 7333044a19
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
6 changed files with 190 additions and 14 deletions

View file

@ -29,6 +29,7 @@ typedef struct chiaki_ctrl_t
{
struct chiaki_session_t *session;
ChiakiThread thread;
int sock;
} ChiakiCtrl;
CHIAKI_EXPORT ChiakiErrorCode chiaki_ctrl_start(ChiakiCtrl *ctrl, struct chiaki_session_t *session);

View file

@ -33,7 +33,6 @@ typedef struct chiaki_rpcrypt_t
{
uint8_t bright[CHIAKI_KEY_BYTES];
uint8_t ambassador[CHIAKI_KEY_BYTES];
struct hmac_ctx_st *hmac_ctx;
} ChiakiRPCrypt;
CHIAKI_EXPORT void chiaki_rpcrypt_bright_ambassador(uint8_t *bright, uint8_t *ambassador, const uint8_t *nonce, const uint8_t *morning);

View file

@ -31,13 +31,17 @@
extern "C" {
#endif
#define CHIAKI_RP_DID_SIZE 32
typedef struct chiaki_connect_info_t
{
const char *host;
const char *regist_key;
const char *ostype;
char auth[0x10];
const char *host; // null terminated
const char *regist_key; // null terminated
const char *ostype; // null terminated
char auth[0x10]; // must be completely filled (pad with \0)
uint8_t morning[0x10];
uint8_t did[CHIAKI_RP_DID_SIZE];
} ChiakiConnectInfo;
@ -72,6 +76,7 @@ typedef void (*ChiakiEventCallback)(ChiakiEvent *event, void *user);
typedef struct chiaki_session_t
{
struct
@ -83,9 +88,11 @@ typedef struct chiaki_session_t
char *ostype;
char auth[CHIAKI_KEY_BYTES];
uint8_t morning[CHIAKI_KEY_BYTES];
uint8_t did[CHIAKI_RP_DID_SIZE];
} connect_info;
uint8_t nonce[CHIAKI_KEY_BYTES];
ChiakiRPCrypt rpcrypt;
ChiakiQuitReason quit_reason;
@ -109,6 +116,13 @@ static inline void chiaki_session_set_event_cb(ChiakiSession *session, ChiakiEve
session->event_cb_user = user;
}
static inline void chiaki_session_set_quit_reason(ChiakiSession *session, ChiakiQuitReason reason)
{
if(session->quit_reason != CHIAKI_QUIT_REASON_NONE)
return;
session->quit_reason = reason;
}
#ifdef __cplusplus
}
#endif

View file

@ -17,11 +17,14 @@
#include <chiaki/ctrl.h>
#include <chiaki/session.h>
#include <chiaki/base64.h>
#include <chiaki/http.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#define SESSION_CTRL_PORT 9295
@ -47,11 +50,49 @@ static void *ctrl_thread_func(void *user)
{
ChiakiCtrl *ctrl = user;
ChiakiErrorCode err = ctrl_thread_connect(ctrl);
if(err != CHIAKI_ERR_SUCCESS)
{
chiaki_session_set_quit_reason(ctrl->session, CHIAKI_QUIT_REASON_CTRL_UNKNOWN);
return NULL;
}
// ...
return NULL;
}
typedef struct ctrl_response_t {
bool server_type_valid;
uint8_t rp_server_type[0x10];
bool success;
} CtrlResponse;
static void parse_ctrl_response(CtrlResponse *response, ChiakiHttpResponse *http_response)
{
memset(response, 0, sizeof(CtrlResponse));
if(http_response->code != 200)
{
response->success = false;
return;
}
response->success = true;
response->server_type_valid = false;
for(ChiakiHttpHeader *header=http_response->headers; header; header=header->next)
{
if(strcmp(header->key, "RP-Server-Type") == 0)
{
size_t server_type_size = sizeof(response->rp_server_type);
chiaki_base64_decode(header->value, strlen(header->value) + 1, response->rp_server_type, &server_type_size);
response->server_type_valid = server_type_size == sizeof(response->rp_server_type);
}
}
}
static ChiakiErrorCode ctrl_thread_connect(ChiakiCtrl *ctrl)
{
ChiakiSession *session = ctrl->session;
@ -72,21 +113,65 @@ static ChiakiErrorCode ctrl_thread_connect(ChiakiCtrl *ctrl)
if(sock < 0)
{
CHIAKI_LOGE(&session->log, "Session ctrl socket creation failed.\n");
if(session->quit_reason == CHIAKI_QUIT_REASON_NONE)
session->quit_reason = CHIAKI_QUIT_REASON_CTRL_UNKNOWN;
chiaki_session_set_quit_reason(session, CHIAKI_QUIT_REASON_CTRL_UNKNOWN);
return CHIAKI_ERR_NETWORK;
}
int r = connect(sock, sa, addr->ai_addrlen);
free(sa);
if(r < 0)
{
int errsv = errno;
CHIAKI_LOGE(&session->log, "Ctrl connect failed: %s\n", strerror(errsv));
if(errsv == ECONNREFUSED)
session->quit_reason = CHIAKI_QUIT_REASON_SESSION_REQUEST_CONNECTION_REFUSED;
else
session->quit_reason = CHIAKI_QUIT_REASON_NONE;
close(sock);
return CHIAKI_ERR_NETWORK;
}
CHIAKI_LOGI(&session->log, "Connected to %s:%d\n", session->connect_info.hostname, SESSION_CTRL_PORT);
char request[512];
uint8_t auth_enc[CHIAKI_KEY_BYTES];
ChiakiErrorCode err = chiaki_rpcrypt_encrypt(&session->rpcrypt, 0, (uint8_t *)session->connect_info.auth, auth_enc, CHIAKI_KEY_BYTES);
if(err != CHIAKI_ERR_SUCCESS)
goto error;
char auth_b64[CHIAKI_KEY_BYTES*2];
err = chiaki_base64_encode(auth_enc, sizeof(auth_enc), auth_b64, sizeof(auth_b64));
if(err != CHIAKI_ERR_SUCCESS)
goto error;
uint8_t did_enc[CHIAKI_RP_DID_SIZE];
err = chiaki_rpcrypt_encrypt(&session->rpcrypt, 1, (uint8_t *)session->connect_info.did, did_enc, CHIAKI_RP_DID_SIZE);
if(err != CHIAKI_ERR_SUCCESS)
goto error;
char did_b64[CHIAKI_RP_DID_SIZE*2];
err = chiaki_base64_encode(did_enc, sizeof(did_enc), did_b64, sizeof(did_b64));
if(err != CHIAKI_ERR_SUCCESS)
goto error;
uint8_t ostype_enc[128];
size_t ostype_len = strlen(session->connect_info.ostype) + 1;
if(ostype_len > sizeof(ostype_enc))
goto error;
err = chiaki_rpcrypt_encrypt(&session->rpcrypt, 2, (uint8_t *)session->connect_info.ostype, ostype_enc, ostype_len);
if(err != CHIAKI_ERR_SUCCESS)
goto error;
char ostype_b64[256];
err = chiaki_base64_encode(ostype_enc, ostype_len, ostype_b64, sizeof(ostype_b64));
if(err != CHIAKI_ERR_SUCCESS)
goto error;
static const char request_fmt[] =
"GET /sce/rp/session/ctrl HTTP/1.1\r\n"
"Host: %s:%d\r\n"
"User-Agent: remoteplay Windows\r\n"
"Connection: keep-alive\r\n"
"Content-Length: 0\r\n"
"RP-Auth: %s\r\n"
"RP-Auth: %s\r\n"
"RP-Version: 8.0\r\n"
"RP-Did: %s\r\n"
"RP-ControllerType: 3\r\n"
@ -94,10 +179,64 @@ static ChiakiErrorCode ctrl_thread_connect(ChiakiCtrl *ctrl)
"RP-OSType: %s\r\n"
"RP-ConPath: 1\r\n\r\n";
uint8_t auth_enc[CHIAKI_KEY_BYTES];
char buf[512];
int request_len = snprintf(buf, sizeof(buf), request_fmt,
session->connect_info.hostname, SESSION_CTRL_PORT, auth_b64, did_b64, ostype_b64);
if(request_len < 0 || request_len >= sizeof(buf))
goto error;
CHIAKI_LOGI(&session->log, "Sending ctrl request\n");
ssize_t sent = send(sock, buf, (size_t)request_len, 0);
if(sent < 0)
{
CHIAKI_LOGE(&session->log, "Failed to send ctrl request\n");
goto error;
}
close(sock);
size_t header_size;
size_t received_size;
err = chiaki_recv_http_header(sock, buf, sizeof(buf)-1, &header_size, &received_size);
if(err != CHIAKI_ERR_SUCCESS)
{
CHIAKI_LOGE(&session->log, "Failed to receive ctrl request response\n");
goto error;
}
buf[received_size] = '\0';
ChiakiHttpResponse http_response;
err = chiaki_http_response_parse(&http_response, buf, header_size);
if(err != CHIAKI_ERR_SUCCESS)
{
CHIAKI_LOGE(&session->log, "Failed to parse ctrl request response\n");
goto error;
}
CtrlResponse response;
parse_ctrl_response(&response, &http_response);
chiaki_http_response_fini(&http_response);
if(!response.success)
{
err = CHIAKI_ERR_UNKNOWN;
goto error;
}
if(response.server_type_valid)
{
ChiakiErrorCode err2 = chiaki_rpcrypt_decrypt(&session->rpcrypt, 0, response.rp_server_type, response.rp_server_type, sizeof(response.rp_server_type));
response.server_type_valid = err2 == CHIAKI_ERR_SUCCESS;
}
if(!response.server_type_valid)
CHIAKI_LOGE(&session->log, "No valid Server Type in ctrl response\n");
ctrl->sock = sock;
close(sock); // TODO: remove
return CHIAKI_ERR_SUCCESS;
error:
close(sock);
return err;
}

View file

@ -68,6 +68,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_session_init(ChiakiSession *session, Chiaki
memcpy(session->connect_info.auth, connect_info->auth, sizeof(session->connect_info.auth));
memcpy(session->connect_info.morning, connect_info->morning, sizeof(session->connect_info.morning));
memcpy(session->connect_info.did, connect_info->did, sizeof(session->connect_info.did));
return CHIAKI_ERR_SUCCESS;
}
@ -114,6 +115,20 @@ static void *session_thread_func(void *arg)
CHIAKI_LOGI(&session->log, "Session request successful\n");
chiaki_rpcrypt_init(&session->rpcrypt, session->nonce, session->connect_info.morning);
usleep(10000);
CHIAKI_LOGI(&session->log, "Starting ctrl\n");
ChiakiErrorCode err = chiaki_ctrl_start(&session->ctrl, session);
if(err != CHIAKI_ERR_SUCCESS)
goto quit;
chiaki_ctrl_join(&session->ctrl);
CHIAKI_LOGI(&session->log, "Ctrl stopped\n");
ChiakiEvent quit_event;
quit:
quit_event.type = CHIAKI_EVENT_QUIT;
@ -258,7 +273,7 @@ static bool session_thread_request_session(ChiakiSession *session)
size_t header_size;
size_t received_size;
ChiakiErrorCode err = chiaki_recv_http_header(session_sock, buf, sizeof(buf), &header_size, &received_size);
ChiakiErrorCode err = chiaki_recv_http_header(session_sock, buf, sizeof(buf)-1, &header_size, &received_size);
if(err != CHIAKI_ERR_SUCCESS)
{
CHIAKI_LOGE(&session->log, "Failed to receive session request response\n");