Parse Regist Response

This commit is contained in:
Florian Märkl 2019-08-15 22:02:04 +02:00
commit 875e8b413e
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
11 changed files with 292 additions and 13 deletions

View file

@ -23,6 +23,7 @@
#include "thread.h"
#include "stoppipe.h"
#include "rpcrypt.h"
#include "session.h"
#ifdef __cplusplus
extern "C" {
@ -35,6 +36,19 @@ typedef struct chiaki_regist_info_t
uint32_t pin;
} ChiakiRegistInfo;
typedef struct chiaki_registered_host_t
{
char ap_ssid[0x30];
char ap_bssid[0x20];
char ap_key[0x50];
char ap_name[0x20];
uint8_t ps4_mac[6];
char ps4_nickname[0x20];
char rp_regist_key[CHIAKI_SESSION_AUTH_SIZE]; // must be completely filled (pad with \0)
uint32_t rp_key_type;
uint8_t rp_key[0x10];
} ChiakiRegisteredHost;
typedef enum chiaki_regist_event_type_t {
CHIAKI_REGIST_EVENT_TYPE_CONNECTED,
CHIAKI_REGIST_EVENT_TYPE_FINISHED_CANCELED,
@ -45,6 +59,7 @@ typedef enum chiaki_regist_event_type_t {
typedef struct chiaki_regist_event_t
{
ChiakiRegistEventType type;
ChiakiRegisteredHost *registered_host;
} ChiakiRegistEvent;
typedef void (*ChiakiRegistCb)(ChiakiRegistEvent *event, void *user);

View file

@ -65,12 +65,14 @@ typedef enum {
CHIAKI_EXPORT void chiaki_connect_video_profile_preset(ChiakiConnectVideoProfile *profile, ChiakiVideoResolutionPreset resolution, ChiakiVideoFPSPreset fps);
#define CHIAKI_SESSION_AUTH_SIZE 0x10
typedef struct chiaki_connect_info_t
{
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)
char auth[CHIAKI_SESSION_AUTH_SIZE]; // must be completely filled (pad with \0)
uint8_t morning[0x10];
uint8_t did[CHIAKI_RP_DID_SIZE];
ChiakiConnectVideoProfile video_profile;

View file

@ -258,7 +258,7 @@ static void *discovery_thread_func(void *user)
buf[n] = '\00';
CHIAKI_LOGV(discovery->log, "Discovery received:\n%s", buf);
//CHIAKI_LOGV(discovery->log, "Discovery received:\n%s", buf);
//chiaki_log_hexdump_raw(discovery->log, CHIAKI_LOG_VERBOSE, (const uint8_t *)buf, n);
char addr_buf[64];

View file

@ -36,7 +36,8 @@
static void *regist_thread_func(void *user);
static ChiakiErrorCode regist_search(ChiakiRegist *regist, struct addrinfo *addrinfos);
static int regist_connect(ChiakiRegist *regist, struct addrinfo *addrinfos, int protocol);
static ChiakiErrorCode regist_recv_response(ChiakiRegist *regist, int sock, ChiakiRPCrypt *rpcrypt);
static ChiakiErrorCode regist_recv_response(ChiakiRegist *regist, ChiakiRegisteredHost *host, int sock, ChiakiRPCrypt *rpcrypt);
static ChiakiErrorCode regist_parse_response_payload(ChiakiRegist *regist, ChiakiRegisteredHost *host, char *buf, size_t buf_size);
CHIAKI_EXPORT ChiakiErrorCode chiaki_regist_start(ChiakiRegist *regist, ChiakiLog *log, const ChiakiRegistInfo *info, ChiakiRegistCb cb, void *cb_user)
{
@ -200,7 +201,8 @@ static void *regist_thread_func(void *user)
CHIAKI_LOGI(regist->log, "Regist waiting for response");
err = regist_recv_response(regist, sock, &crypt);
ChiakiRegisteredHost host;
err = regist_recv_response(regist, &host, sock, &crypt);
if(err != CHIAKI_ERR_SUCCESS)
{
CHIAKI_LOGE(regist->log, "Regist eventually failed");
@ -210,7 +212,6 @@ static void *regist_thread_func(void *user)
CHIAKI_LOGI(regist->log, "Regist successfully received response");
success = true;
// TODO: params
fail_socket:
close(sock);
@ -220,7 +221,12 @@ fail:
if(canceled)
regist_event_simple(regist, CHIAKI_REGIST_EVENT_TYPE_FINISHED_CANCELED);
else if(success)
regist_event_simple(regist, CHIAKI_REGIST_EVENT_TYPE_FINISHED_SUCCESS);
{
ChiakiRegistEvent event = { 0 };
event.type = CHIAKI_REGIST_EVENT_TYPE_FINISHED_SUCCESS;
event.registered_host = &host;
regist->cb(&event, regist->cb_user);
}
else
regist_event_simple(regist, CHIAKI_REGIST_EVENT_TYPE_FINISHED_FAILED);
return NULL;
@ -320,7 +326,7 @@ static int regist_connect(ChiakiRegist *regist, struct addrinfo *addrinfos, int
return sock;
}
static ChiakiErrorCode regist_recv_response(ChiakiRegist *regist, int sock, ChiakiRPCrypt *rpcrypt)
static ChiakiErrorCode regist_recv_response(ChiakiRegist *regist, ChiakiRegisteredHost *host, int sock, ChiakiRPCrypt *rpcrypt)
{
uint8_t buf[0x200];
size_t buf_filled_size;
@ -394,7 +400,126 @@ static ChiakiErrorCode regist_recv_response(ChiakiRegist *regist, int sock, Chia
CHIAKI_LOGI(regist->log, "Regist response payload (decrypted):");
chiaki_log_hexdump(regist->log, CHIAKI_LOG_VERBOSE, payload, payload_size);
// TODO: parse content
err = regist_parse_response_payload(regist, host, (char *)payload, payload_size);
if(err != CHIAKI_ERR_SUCCESS)
{
CHIAKI_LOGE(regist->log, "Regist failed to parse response payload");
return err;
}
return CHIAKI_ERR_SUCCESS;
}
static ChiakiErrorCode regist_parse_response_payload(ChiakiRegist *regist, ChiakiRegisteredHost *host, char *buf, size_t buf_size)
{
ChiakiHttpHeader *headers;
ChiakiErrorCode err = chiaki_http_header_parse(&headers, buf, buf_size);
if(err != CHIAKI_ERR_SUCCESS)
{
CHIAKI_LOGE(regist->log, "Regist failed to parse response payload HTTP header");
return err;
}
memset(host, 0, sizeof(*host));
bool mac_found = false;
bool regist_key_found = false;
bool key_found = false;
for(ChiakiHttpHeader *header=headers; header; header=header->next)
{
#define COPY_STRING(name, key_str) \
if(strcmp(header->key, key_str) == 0) \
{ \
size_t len = strlen(header->value); \
if(len >= sizeof(host->name)) \
{ \
CHIAKI_LOGE(regist->log, "Regist value for " key_str " in response is too long"); \
continue; \
} \
memcpy(host->name, header->value, len); \
host->name[len] = 0; \
continue; \
}
COPY_STRING(ap_ssid, "AP-Ssid")
COPY_STRING(ap_bssid, "AP-Bssid")
COPY_STRING(ap_key, "AP-Key")
COPY_STRING(ap_name, "AP-Name")
COPY_STRING(ps4_nickname, "PS4-Nickname")
#undef COPY_STRING
if(strcmp(header->key, "PS4-RegistKey") == 0)
{
memset(host->rp_regist_key, 0, sizeof(host->rp_regist_key));
size_t buf_size = sizeof(host->rp_regist_key);
err = parse_hex((uint8_t *)host->rp_regist_key, &buf_size, header->value, strlen(header->value));
if(err != CHIAKI_ERR_SUCCESS)
{
CHIAKI_LOGE(regist->log, "Regist received invalid RegistKey in response");
memset(host->rp_regist_key, 0, sizeof(host->rp_regist_key));
}
else
{
regist_key_found = true;
}
}
else if(strcmp(header->key, "RP-KeyType") == 0)
{
host->rp_key_type = (uint32_t)strtoul(header->value, NULL, 0);
}
else if(strcmp(header->key, "RP-Key") == 0)
{
size_t buf_size = sizeof(host->rp_key);
err = parse_hex((uint8_t *)host->rp_key, &buf_size, header->value, strlen(header->value));
if(err != CHIAKI_ERR_SUCCESS || buf_size != sizeof(host->rp_key))
{
CHIAKI_LOGE(regist->log, "Regist received invalid key in response");
memset(host->rp_key, 0, sizeof(host->rp_key));
}
else
{
key_found = true;
}
}
else if(strcmp(header->key, "PS4-Mac") == 0)
{
size_t buf_size = sizeof(host->ps4_mac);
err = parse_hex((uint8_t *)host->ps4_mac, &buf_size, header->value, strlen(header->value));
if(err != CHIAKI_ERR_SUCCESS || buf_size != sizeof(host->ps4_mac))
{
CHIAKI_LOGE(regist->log, "Regist received invalid MAC Address in response");
memset(host->ps4_mac, 0, sizeof(host->ps4_mac));
}
else
{
mac_found = true;
}
}
else
{
CHIAKI_LOGI(regist->log, "Regist received unknown key %s in response payload", header->key);
}
}
chiaki_http_header_free(headers);
if(!regist_key_found)
{
CHIAKI_LOGE(regist->log, "Regist response is missing RegistKey (or it was invalid)");
return CHIAKI_ERR_INVALID_RESPONSE;
}
if(!key_found)
{
CHIAKI_LOGE(regist->log, "Regist response is missing key (or it was invalid)");
return CHIAKI_ERR_INVALID_RESPONSE;
}
if(!mac_found)
{
CHIAKI_LOGE(regist->log, "Regist response is missing MAC Adress (or it was invalid)");
return CHIAKI_ERR_INVALID_RESPONSE;
}
return CHIAKI_ERR_SUCCESS;
}

View file

@ -43,4 +43,37 @@ static inline void xor_bytes(uint8_t *dst, uint8_t *src, size_t sz)
}
}
static inline int8_t nibble_value(char c)
{
if(c >= '0' && c <= '9')
return c - '0';
if(c >= 'a' && c <= 'f')
return c - 'a' + 0xa;
if(c >= 'A' && c <= 'F')
return c - 'A' + 0xa;
return -1;
}
static inline ChiakiErrorCode parse_hex(uint8_t *buf, size_t *buf_size, const char *hex, size_t hex_size)
{
if(hex_size % 2 != 0)
return CHIAKI_ERR_INVALID_DATA;
if(hex_size / 2 > *buf_size)
return CHIAKI_ERR_BUF_TOO_SMALL;
for(size_t i=0; i<hex_size; i+=2)
{
int8_t h = nibble_value(hex[i+0]);
if(h < 0)
return CHIAKI_ERR_INVALID_DATA;
int8_t l = nibble_value(hex[i+1]);
if(l < 0)
return CHIAKI_ERR_INVALID_DATA;
buf[i/2] = (h << 4) | l;
}
*buf_size = hex_size / 2;
return CHIAKI_ERR_SUCCESS;
}
#endif // CHIAKI_UTILS_H