* Added SSL support, Thanks to Fix94

* Updated Nintendont update URL to github
* Updated http.c to use less memory (thanks nintendont)
* Added progressWindows support for downloads
* Disabled Theme Downloader Menu access (not enough memory)
This commit is contained in:
cyan06 2015-07-13 14:26:30 +00:00
parent 26c671bd7b
commit b69bc9b789
9 changed files with 697 additions and 192 deletions

View File

@ -2,8 +2,8 @@
<app version="1"> <app version="1">
<name> USB Loader GX</name> <name> USB Loader GX</name>
<coder>USB Loader GX Team</coder> <coder>USB Loader GX Team</coder>
<version>3.0 r1252</version> <version>3.0 r1253</version>
<release_date>20150712124252</release_date> <release_date>20150713135453</release_date>
<!-- // remove this line to enable arguments <!-- // remove this line to enable arguments
<arguments> <arguments>
<arg>--ios=250</arg> <arg>--ios=250</arg>

View File

@ -215,9 +215,9 @@ int MainMenu(int menu)
case MENU_THEMEMENU: case MENU_THEMEMENU:
currentMenu = ThemeMenu::Execute(); currentMenu = ThemeMenu::Execute();
break; break;
case MENU_THEMEDOWNLOADER: // case MENU_THEMEDOWNLOADER:
currentMenu = ThemeDownloader::Execute(); // currentMenu = ThemeDownloader::Execute();
break; // break;
case MENU_HOMEBREWBROWSE: case MENU_HOMEBREWBROWSE:
currentMenu = HomebrewBrowser::Execute(); currentMenu = HomebrewBrowser::Execute();
break; break;

View File

@ -1,9 +1,41 @@
/* http -- http convenience functions
Copyright (C) 2008 bushing
2008-2014 Dimok
2015 Fix94 ; Cyan
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 2.
This program is distributed in the hope that 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <ogc/lwp_watchdog.h>
#include "http.h" #include "http.h"
#include "ssl.h"
#include "../svnrev.h" #include "../svnrev.h"
#include "prompts/ProgressWindow.h"
#include "language/gettext.h"
#include "gecko.h" #include "gecko.h"
extern char incommingIP[50]; extern char incommingIP[50];
static u8 retryloop = 0; static u8 retryloop = 0;
static bool displayProgressWindow = false;
http_res result;
u16 http_port;
u32 http_status;
u32 content_length;
char content_location[255] = "";
/** /**
* Emptyblock is a statically defined variable for functions to return if they are unable * Emptyblock is a statically defined variable for functions to return if they are unable
@ -11,18 +43,19 @@ static u8 retryloop = 0;
*/ */
const struct block emptyblock = { 0, NULL }; const struct block emptyblock = { 0, NULL };
//The maximum amount of bytes to send per net_write() call
//#define NET_BUFFER_SIZE 1024
#define NET_BUFFER_SIZE 3600
// Write our message to the server // Write our message to the server
static s32 send_message(s32 server, char *msg) static s32 tcp_write(s32 server, char *msg)
{ {
s32 bytes_transferred = 0; s32 bytes_transferred = 0;
s32 remaining = strlen(msg); s32 remaining = strlen(msg);
s32 res = 0;
while (remaining) while (remaining)
{ {
if ((bytes_transferred = net_write(server, msg, remaining > NET_BUFFER_SIZE ? NET_BUFFER_SIZE : remaining)) > 0) if(http_port == 443)
res = (bytes_transferred = ssl_write(server, msg, remaining > NET_BUFFER_SIZE ? NET_BUFFER_SIZE : remaining));
else
res = (bytes_transferred = net_write(server, msg, remaining > NET_BUFFER_SIZE ? NET_BUFFER_SIZE : remaining));
if (res > 0)
{ {
remaining -= bytes_transferred; remaining -= bytes_transferred;
msg += bytes_transferred; msg += bytes_transferred;
@ -47,7 +80,7 @@ static s32 send_message(s32 server, char *msg)
* @param u32 the port to connect to on the server * @param u32 the port to connect to on the server
* @return s32 The connection to the server (negative number if connection could not be established) * @return s32 The connection to the server (negative number if connection could not be established)
*/ */
static s32 server_connect(u32 ipaddress, u16 socket_port) static s32 tcp_connect(u32 ipaddress, u16 socket_port)
{ {
//Initialize socket //Initialize socket
s32 connection = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP); s32 connection = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
@ -61,7 +94,7 @@ static s32 server_connect(u32 ipaddress, u16 socket_port)
sprintf(incommingIP, "%s", inet_ntoa(connect_addr.sin_addr)); sprintf(incommingIP, "%s", inet_ntoa(connect_addr.sin_addr));
//Attemt to open the socket //Attempt to open the socket
if (net_connect(connection, (struct sockaddr*) &connect_addr, sizeof(connect_addr)) == -1) if (net_connect(connection, (struct sockaddr*) &connect_addr, sizeof(connect_addr)) == -1)
{ {
net_close(connection); net_close(connection);
@ -70,82 +103,168 @@ static s32 server_connect(u32 ipaddress, u16 socket_port)
return connection; return connection;
} }
//The amount of memory in bytes reserved initially to store the HTTP response in
//Be careful in increasing this number, reading from a socket on the Wii
//will fail if you request more than 20k or so
#define HTTP_BUFFER_SIZE 1024 * 5
//The amount of memory the buffer should expanded with if the buffer is full
#define HTTP_BUFFER_GROWTH 1024 * 5
/** /**
* This function reads all the data from a connection into a buffer which it returns. * Reads the current connection data line by line
* It will return an empty buffer if something doesn't go as planned
* *
* @param s32 connection The connection identifier to suck the response out of * @return string up to "\r\n" or until max_length is reached.
* @return block A 'block' struct (see http.h) in which the buffer is located
*/ */
struct block read_message(s32 connection) char * tcp_readLine (const s32 s, const u16 max_length, const u64 start_time, const u16 timeout) {
{ char *buf;
//Create a block of memory to put in the response u16 c;
struct block buffer; s32 res;
buffer.data = malloc(HTTP_BUFFER_SIZE); char *ret;
buffer.size = HTTP_BUFFER_SIZE;
if (buffer.data == NULL) buf = malloc(max_length);
{
return emptyblock;
}
//The offset variable always points to the first byte of memory that is free in the buffer c = 0;
u32 offset = 0; ret = NULL;
while (true) {
if (ticks_to_millisecs (diff_ticks (start_time, gettime ())) > timeout)
break;
while (1) if(http_port == 443)
{ res = ssl_read (s, &buf[c], 1);
//Fill the buffer with a new batch of bytes from the connection, else
//starting from where we left of in the buffer till the end of the buffer res = net_read (s, &buf[c], 1);
s32 bytes_read = net_read(connection, buffer.data + offset, buffer.size - offset);
//Anything below 0 is an error in the connection if ((res == 0) || (res == -EAGAIN)) {
if (bytes_read < 0) usleep (20 * 1000);
{
//printf("Connection error from net_read() Errorcode: %i\n", bytes_read); continue;
return emptyblock;
} }
//No more bytes were read into the buffer, if (res < 0) break;
//we assume this means the HTTP response is done
if (bytes_read == 0) if ((c > 0) && (buf[c - 1] == '\r') && (buf[c] == '\n')) {
{ if (c == 1) {
ret = strdup ("");
break;
}
ret = strndup (buf, c - 1);
break; break;
} }
offset += bytes_read; c++;
//Check if we have enough buffer left over, if (c == max_length)
//if not expand it with an additional HTTP_BUFFER_GROWTH worth of bytes break;
if (offset >= buffer.size)
{
buffer.size += HTTP_BUFFER_GROWTH;
u8 * tmp = realloc(buffer.data, buffer.size);
if (tmp == NULL)
{
free(buffer.data);
return emptyblock;
}
else
buffer.data = tmp;
}
} }
//At the end of above loop offset should be precisely the amount of bytes that were read from the connection free (buf);
buffer.size = offset; return ret;
}
//Shrink the size of the buffer so the data fits exactly in it /**
buffer.data = realloc(buffer.data, buffer.size); * This function reads all the data from a connection into a buffer.
*
* @param s32 connection The connection identifier to suck the response out of
* @return bool True if data downloaded succesfully.
*/
bool tcp_readData(const s32 connection, u8 **buffer, const u32 length)
{
u8 *p;
u32 left, block, received;
s64 t;
s32 res;
return buffer; p = *buffer;
left = length;
received = 0;
t = gettime ();
while (left)
{
if (ticks_to_millisecs (diff_ticks (t, gettime ())) > TCP_BLOCK_RECV_TIMEOUT)
break;
// Update the progress bar
if(displayProgressWindow)
{
ShowProgress(received, length);
if(ProgressCanceled())
{
ProgressStop();
break;
}
}
// Get next block size
block = left;
if (block > TCP_BLOCK_SIZE)
block = TCP_BLOCK_SIZE;
if(http_port == 443)
res = ssl_read (connection, p, block);
else
res = net_read (connection, p, block);
if ((res == 0) || (res == -EAGAIN))
{
usleep (20 * 1000);
continue;
}
if (res < 0) break;
received += res;
left -= res;
p += res;
// update timing after each downloaded block
t = gettime ();
}
return left == 0;
}
/**
* Parse the HTTP replied header
*
* @param s32 connection identification
* @return bool true if max header lines not reached. Stores HTTP answers into global variables.
*/
u8 read_header(s32 connection)
{
int linecount = 0;
result = HTTPR_OK;
for (linecount = 0; linecount < 32; linecount++)
{
char *line = tcp_readLine (connection, 0xff, gettime(), (u16)HTTP_TIMEOUT);
if (!line)
{
http_status = 404;
result = HTTPR_ERR_REQUEST;
break;
}
if (strlen (line) < 1)
{
free (line);
line = NULL;
break;
}
sscanf (line, "HTTP/1.%*u %u", &http_status);
sscanf (line, "Content-Length: %u", &content_length);
sscanf (line, "Location: %s", content_location);
//gprintf(line);
//gprintf("\n");
free (line);
line = NULL;
}
if (linecount == 32)
{
http_status = 404;
result = HTTPR_ERR_REQUEST;
}
return result;
} }
/** /**
@ -154,15 +273,27 @@ struct block read_message(s32 connection)
*/ */
struct block downloadfile(const char *url) struct block downloadfile(const char *url)
{ {
int sslcontext = -1;
//Check if the url starts with "http://", if not it is not considered a valid url //Check if the url starts with "http://", if not it is not considered a valid url
if (strncmp(url, "http://", strlen("http://")) != 0) if (strncmp(url, "http://", strlen("http://")) == 0)
http_port = 80;
else if(strncmp(url, "https://", strlen("https://")) == 0)
{ {
//printf("URL '%s' doesn't start with 'http://'\n", url); http_port = 443;
return emptyblock; gprintf("Initializing ssl...\n");
if(ssl_init() < 0)
return emptyblock;
} }
else
return emptyblock;
//Locate the path part of the url by searching for '/' past "http://" //Locate the path part of the url by searching for '/' past "http://"
char *path = strchr(url + strlen("http://"), '/'); char *path = 0;
if(http_port == 443)
path = strchr(url + strlen("https://"), '/');
else
path = strchr(url + strlen("http://"), '/');
//At the very least the url has to end with '/', ending with just a domain is invalid //At the very least the url has to end with '/', ending with just a domain is invalid
if (path == NULL) if (path == NULL)
@ -172,7 +303,7 @@ struct block downloadfile(const char *url)
} }
//Extract the domain part out of the url //Extract the domain part out of the url
int domainlength = path - url - strlen("http://"); int domainlength = path - url - strlen("http://") - (http_port == 443 ? 1 : 0);
if (domainlength == 0) if (domainlength == 0)
{ {
@ -181,7 +312,7 @@ struct block downloadfile(const char *url)
} }
char domain[domainlength + 1]; char domain[domainlength + 1];
strlcpy(domain, url + strlen("http://"), domainlength + 1); strlcpy(domain, url + strlen("http://") + (http_port == 443 ? 1 : 0), domainlength + 1);
//Parsing of the URL is done, start making an actual connection //Parsing of the URL is done, start making an actual connection
u32 ipaddress = getipbynamecached(domain); u32 ipaddress = getipbynamecached(domain);
@ -192,7 +323,7 @@ struct block downloadfile(const char *url)
return emptyblock; return emptyblock;
} }
s32 connection = server_connect(ipaddress, 80); s32 connection = tcp_connect(ipaddress, http_port);
if (connection < 0) if (connection < 0)
{ {
@ -200,6 +331,39 @@ struct block downloadfile(const char *url)
return emptyblock; return emptyblock;
} }
if(http_port == 443)
{
//patched out anyways so just to set something
sslcontext = ssl_new((u8*)domain,0);
if(sslcontext < 0)
{
//gprintf("ssl_new\n");
result = HTTPR_ERR_CONNECT;
net_close (connection);
return emptyblock;
}
//patched out anyways so just to set something
ssl_setbuiltinclientcert(sslcontext,0);
if(ssl_connect(sslcontext,connection) < 0)
{
//gprintf("ssl_connect\n");
result = HTTPR_ERR_CONNECT;
ssl_shutdown(sslcontext);
net_close (connection);
return emptyblock;
}
int ret = ssl_handshake(sslcontext);
if(ret < 0)
{
//gprintf("ssl_handshake %i\n", ret);
result = HTTPR_ERR_STATUS;
ssl_shutdown(sslcontext);
net_close (connection);
return emptyblock;
}
}
// Remove Referer from the request header for incompatible websites (ex. Cloudflare proxy) // Remove Referer from the request header for incompatible websites (ex. Cloudflare proxy)
char referer[domainlength + 12]; char referer[domainlength + 12];
snprintf(referer, sizeof(referer), "Referer: %s\r\n", domain); snprintf(referer, sizeof(referer), "Referer: %s\r\n", domain);
@ -216,131 +380,96 @@ struct block downloadfile(const char *url)
//gprintf("%s\n",header); //gprintf("%s\n",header);
//Do the request and get the response //Do the request and get the response
send_message(connection, header); tcp_write(http_port == 443 ? sslcontext : connection, header);
struct block response = read_message(connection); read_header( http_port == 443 ? sslcontext : connection);
net_close(connection);
// dump response if (http_status >= 400) // Not found
// hexdump(response.data, response.size);
//Search for the 4-character sequence \r\n\r\n in the response which signals the start of the http payload (file)
unsigned char *filestart = NULL;
u32 filesize = 0;
u32 i;
char newURL[512];
bool redirect = false;
for (i = 3; i < response.size; i++)
{ {
if (response.data[i] == '\n' && response.data[i - 1] == '\r' && response.data[i - 2] == '\n' && response.data[i - 3] == '\r') //gprintf("HTTP ERROR: %d\n", http_status);
{ return emptyblock;
filestart = response.data + i + 1;
filesize = response.size - i - 1;
// Check the HTTP response code
if (response.size > 10 && strncmp((char*)response.data, "HTTP/", 5)==0)
{
char htstat[i];
strncpy(htstat, (char*)response.data, i);
htstat[i] = 0;
char *codep;
codep = strchr(htstat, ' ');
if (codep)
{
int code;
if (sscanf(codep+1, "%d", &code) == 1)
{
//gprintf("HTTP response code: %d\n", code);
if (code == 302) // 302 FOUND (redirected link)
{
char *ptr = strcasestr((char*)response.data, "Location: ");
if(ptr)
{
ptr += strlen("Location: ");
strncpy(newURL, ptr, sizeof(newURL));
*(strchr(newURL, '\r'))=0;
redirect = true;
//gprintf("New URL to download = %s \n", newURL);
}
else
{
//gprintf("HTTP ERROR: %s\n", htstat);
free(response.data);
return emptyblock;
}
}
if (code >=400) // Not found
{
//gprintf("HTTP ERROR: %s\n", htstat);
free(response.data);
return emptyblock;
}
}
}
}
break;
}
} }
if(redirect) if(!content_length)
content_length = 0;
// create data buffer to return
struct block response;
response.data = malloc(content_length);
response.size = content_length;
if (response.data == NULL)
{ {
// Prevent endless loop return emptyblock;
}
if (http_status == 200)
{
if(displayProgressWindow)
{
ProgressCancelEnable(true);
StartProgress(tr("Downloading file..."), tr("Please wait"), 0, false, false);
}
int ret = tcp_readData(http_port == 443 ? sslcontext : connection, &response.data, content_length);
if(!ret)
{
free(response.data);
result = HTTPR_ERR_RECEIVE;
if(http_port == 443)
ssl_shutdown(sslcontext);
net_close (connection);
return emptyblock;
}
}
else if (http_status == 302) // 302 FOUND (redirected link)
{
// close current connection
if(http_port == 443)
ssl_shutdown(sslcontext);
net_close (connection);
// prevent infinite loops
retryloop++; retryloop++;
if(retryloop > 3) if(retryloop > 3)
{ {
retryloop = 0; retryloop = 0;
free(response.data);
return emptyblock; return emptyblock;
} }
struct block redirected = downloadfile(newURL); struct block redirected = downloadfile(content_location);
if(redirected.size == 0)
return emptyblock;
// copy the newURL data into the original data // copy the newURL data into the original data
u8 * tmp = realloc(response.data, redirected.size); u8 * tmp = realloc(response.data, redirected.size);
if (tmp == NULL) if (tmp == NULL)
{ {
//gprintf("Could not allocate enough memory for new URL. Download canceled.\n"); gprintf("Could not allocate enough memory for new URL. Download canceled.\n");
free(response.data); free(response.data);
response.size = 0;
free(redirected.data); free(redirected.data);
result = HTTPR_ERR_RECEIVE;
if(http_port == 443)
ssl_shutdown(sslcontext);
net_close (connection);
return emptyblock; return emptyblock;
} }
response.data = tmp; response.data = tmp;
memcpy(response.data, redirected.data, redirected.size); memcpy(response.data, redirected.data, redirected.size);
// Set filestart's new size based on redirected file
filestart = response.data;
filesize = redirected.size;
free(redirected.data); free(redirected.data);
response.size = redirected.size;
} }
retryloop = 0; retryloop = 0;
if (filestart == NULL) // reset progress window if used
if(displayProgressWindow)
{ {
//printf("HTTP Response was without a file\n"); ProgressStop();
free(response.data); ProgressCancelEnable(false);
return emptyblock; displayProgressWindow = false;
} }
//Copy the file part of the response into a new memoryblock to return return response;
struct block file;
file.data = malloc(filesize);
file.size = filesize;
if (file.data == NULL)
{
//printf("No more memory to copy file from HTTP response\n");
free(response.data);
return emptyblock;
}
memcpy(file.data, filestart, filesize);
//Dispose of the original response
free(response.data);
return file;
} }
s32 GetConnection(char * domain) s32 GetConnection(char * domain)
@ -351,7 +480,12 @@ s32 GetConnection(char * domain)
{ {
return -1; return -1;
} }
s32 connection = server_connect(ipaddress, 80); s32 connection = tcp_connect(ipaddress, 80);
return connection; return connection;
} }
void displayDownloadProgress(bool display)
{
displayProgressWindow = display;
}

View File

@ -6,6 +6,27 @@
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#define TCP_CONNECT_TIMEOUT 5000
#define TCP_BLOCK_SIZE (16 * 1024)
#define TCP_BLOCK_RECV_TIMEOUT 4000
#define TCP_BLOCK_SEND_TIMEOUT 4000
#define HTTP_TIMEOUT 300000
//The maximum amount of bytes to send per net_write() call
#define NET_BUFFER_SIZE 3600
typedef enum {
HTTPR_OK,
HTTPR_ERR_CONNECT,
HTTPR_ERR_REQUEST,
HTTPR_ERR_STATUS,
HTTPR_ERR_TOOBIG,
HTTPR_ERR_RECEIVE
} http_res;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
{ {
@ -18,14 +39,15 @@ extern "C"
*/ */
struct block struct block
{ {
u32 size; u32 size;
unsigned char *data; unsigned char *data;
}; };
extern const struct block emptyblock; extern const struct block emptyblock;
struct block downloadfile(const char *url); struct block downloadfile(const char *url);
s32 GetConnection(char * domain); s32 GetConnection(char * domain);
void displayDownloadProgress(bool display);
#ifdef __cplusplus #ifdef __cplusplus
} }

284
source/network/ssl.c Normal file
View File

@ -0,0 +1,284 @@
/* Code taken from http://wiibrew.org/wiki//dev/net/ssl/code */
#include <gccore.h>
#include <string.h>
#include "ssl.h"
#include "system/runtimeiospatch.h"
#define ISALIGNED(x) ((((u32)x)&0x1F)==0)
static char __ssl_fs[] ATTRIBUTE_ALIGN(32) = "/dev/net/ssl";
static s32 __ssl_fd = -1;
static s32 __ssl_hid = -1;
s32 ssl_init(void){
if(__ssl_hid < 0 ) {
__ssl_hid = iosCreateHeap(SSL_HEAP_SIZE);
if(__ssl_hid < 0){
return __ssl_hid;
}
if(IosPatch_SSL(false) < 4)
return -1;
}
return 0;
}
u32 ssl_open(void){
s32 ret;
if (__ssl_fd < 0) {
ret = IOS_Open(__ssl_fs,0);
if(ret<0){
return ret;
}
__ssl_fd = ret;
}
return 0;
}
u32 ssl_close(void){
s32 ret;
if(__ssl_fd < 0){
return 0;
}
ret = IOS_Close(__ssl_fd);
__ssl_fd = -1;
if(ret<0){
return ret;
}
return 0;
}
s32 ssl_new(u8 * CN, u32 ssl_verify_options){
s32 ret;
s32 aContext[8] ATTRIBUTE_ALIGN(32);
u32 aVerify_options[8] ATTRIBUTE_ALIGN(32);
ret = ssl_open();
if(ret){
return ret;
}
aVerify_options[0] = ssl_verify_options;
if(ISALIGNED(CN)){ //Avoid alignment if the input is aligned
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_NEW, "d:dd", aContext, 0x20, aVerify_options, 0x20, CN, 0x100);
}else{
u8 *aCN = NULL;
aCN = iosAlloc(__ssl_hid, 0x100);
if (!aCN) {
return IPC_ENOMEM;
}
memcpy(aCN, CN, 0x100);
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_NEW, "d:dd", aContext, 0x20, aVerify_options, 0x20, aCN, 0x100);
if(aCN){
iosFree(__ssl_hid, aCN);
}
}
ssl_close();
return (ret ? ret : aContext[0]);
}
s32 ssl_setbuiltinclientcert(s32 ssl_context, s32 index){
s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
s32 aIndex[8] ATTRIBUTE_ALIGN(32);
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
s32 ret;
ret = ssl_open();
if(ret){
return ret;
}
aSsl_context[0] = ssl_context;
aIndex[0] = index;
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_SETBUILTINCLIENTCERT, "d:dd", aResponse, 32, aSsl_context, 32, aIndex, 32);
ssl_close();
return (ret ? ret : aResponse[0]);
}
s32 ssl_setrootca(s32 ssl_context, const void *root, u32 length){
s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
s32 ret;
ret = ssl_open();
if(ret){
return ret;
}
aSsl_context[0] = ssl_context;
if(ISALIGNED(root)){ //Avoid alignment if the input is aligned
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_SETROOTCA, "d:dd", aResponse, 0x20, aSsl_context, 0x20, root, length);
}else{
u8 *aRoot = NULL;
aRoot = iosAlloc(__ssl_hid, length);
if (!aRoot) {
return IPC_ENOMEM;
}
memcpy(aRoot, root, length);
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_SETROOTCA, "d:dd", aResponse, 0x20, aSsl_context, 0x20, aRoot, length);
if(aRoot){
iosFree(__ssl_hid, aRoot);
}
}
ssl_close();
return (ret ? ret : aResponse[0]);
}
s32 ssl_connect(s32 ssl_context, s32 socket){
s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
s32 aSocket[8] ATTRIBUTE_ALIGN(32);
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
s32 ret;
ret = ssl_open();
if(ret){
return ret;
}
aSsl_context[0] = ssl_context;
aSocket[0] = socket;
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_CONNECT, "d:dd", aResponse, 0x20, aSsl_context, 0x20, aSocket, 0x20);
ssl_close();
return (ret ? ret : aResponse[0]);
}
s32 ssl_handshake( s32 ssl_context ){
s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
s32 ret;
ret = ssl_open();
if(ret){
return ret;
}
aSsl_context[0] = ssl_context;
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_HANDSHAKE, "d:d", aResponse, 0x20, aSsl_context, 0x20);
ssl_close();
return (ret ? ret : aResponse[0]);
}
s32 ssl_read(s32 ssl_context, void* buffer, u32 length){
s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
s32 ret;
ret = ssl_open();
if(ret){
return ret;
}
if(!buffer){
return IPC_EINVAL;
}
u8 *aBuffer = NULL;
aBuffer = iosAlloc(__ssl_hid, length);
if (!aBuffer) {
return IPC_ENOMEM;
}
aSsl_context[0] = ssl_context;
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_READ, "dd:d", aResponse, 0x20, aBuffer, length, aSsl_context, 0x20);
ssl_close();
if(ret == IPC_OK){
memcpy(buffer, aBuffer, aResponse[0]);
}
if(aBuffer){
iosFree(__ssl_hid, aBuffer);
}
return (ret ? ret : aResponse[0]);
}
s32 ssl_write(s32 ssl_context, const void *buffer, u32 length){
s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
s32 ret;
ret = ssl_open();
if(ret){
return ret;
}
if(!buffer){
return IPC_EINVAL;
}
aSsl_context[0] = ssl_context;
if(ISALIGNED(buffer)){ //Avoid alignment if the input is aligned
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_WRITE, "d:dd", aResponse, 0x20, aSsl_context, 0x20, buffer, length);
}else{
u8 *aBuffer = NULL;
aBuffer = iosAlloc(__ssl_hid, length);
if (!aBuffer) {
return IPC_ENOMEM;
}
memcpy(aBuffer, buffer, length);
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_WRITE, "d:dd", aResponse, 0x20, aSsl_context, 0x20, aBuffer, length);
}
ssl_close();
return (ret ? ret : aResponse[0]);
}
s32 ssl_shutdown( s32 ssl_context){
s32 aSsl_context[8] ATTRIBUTE_ALIGN(32);
s32 aResponse[8] ATTRIBUTE_ALIGN(32);
s32 ret;
ret = ssl_open();
if(ret){
return ret;
}
aSsl_context[0] = ssl_context;
ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_SHUTDOWN, "d:d", aResponse, 0x20, aSsl_context, 0x20);
ssl_close();
return (ret ? ret : aResponse[0]);
}

36
source/network/ssl.h Normal file
View File

@ -0,0 +1,36 @@
/* Code taken from http://wiibrew.org/wiki//dev/net/ssl/code */
#ifndef _SSL_H_
#define _SSL_H_
#define IOCTLV_SSL_NEW 1
#define IOCTLV_SSL_CONNECT 2
#define IOCTLV_SSL_HANDSHAKE 3
#define IOCTLV_SSL_READ 4
#define IOCTLV_SSL_WRITE 5
#define IOCTLV_SSL_SHUTDOWN 6
#define IOCTLV_SSL_SETROOTCA 10
#define IOCTLV_SSL_SETBUILTINCLIENTCERT 14
#define SSL_HEAP_SIZE 0xB000
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
s32 ssl_init(void);
u32 ssl_open(void);
u32 ssl_close(void);
s32 ssl_new(u8 * CN, u32 verify_options);
s32 ssl_setbuiltinclientcert(s32 ssl_context, s32 index);
s32 ssl_setrootca(s32 ssl_context, const void *root, u32 length);
s32 ssl_connect(s32 ssl_context, s32 socket);
s32 ssl_handshake( s32 ssl_context );
s32 ssl_read(s32 ssl_context, void* buffer, u32 length);
s32 ssl_write(s32 ssl_context, const void * buffer, u32 length);
s32 ssl_shutdown( s32 ssl_context);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

View File

@ -32,7 +32,7 @@
#include "settings/SettingsPrompts.h" #include "settings/SettingsPrompts.h"
#include "network/Wiinnertag.h" #include "network/Wiinnertag.h"
#include "network/networkops.h" #include "network/networkops.h"
#include "network/FileDownloader.h" #include "network/http.h"
#include "FileOperations/fileops.h" #include "FileOperations/fileops.h"
#include "prompts/PromptWindows.h" #include "prompts/PromptWindows.h"
#include "prompts/ProgressWindow.h" #include "prompts/ProgressWindow.h"
@ -541,23 +541,39 @@ int FeatureSettingsMenu::GetMenuInternal()
RenameFile(NINUpdatePath, NINUpdatePathBak); RenameFile(NINUpdatePath, NINUpdatePathBak);
// Download latest loader.dol as boot.dol // Download latest loader.dol as boot.dol
int filesize = DownloadFileToPath("http://nintendon-t.googlecode.com/svn/trunk/loader/loader.dol", NINUpdatePath, false); bool success = false;
displayDownloadProgress(true); // enable progress window for next download
if(filesize <= 0) struct block file = downloadfile("https://raw.githubusercontent.com/FIX94/Nintendont/master/loader/loader.dol");
if (file.data != NULL)
{ {
RemoveFile(NINUpdatePath); FILE * pfile = fopen(NINUpdatePath, "wb");
if(CheckFile(NINUpdatePathBak)) if(pfile)
RenameFile(NINUpdatePathBak, NINUpdatePath); {
WindowPrompt(tr( "Update failed" ), 0, tr( "OK" )); fwrite(file.data, 1, file.size, pfile);
fclose(pfile);
WindowPrompt(tr( "Successfully Updated" ), 0, tr( "OK" ));
success = true;
}
else
WindowPrompt(tr( "Update failed" ), 0, tr( "OK" ));
free(file.data);
} }
else
if(success)
{ {
//remove existing loader.dol file if found as it has priority over boot.dol, and boot.bak //remove existing loader.dol file if found as it has priority over boot.dol, and boot.bak
snprintf(NINUpdatePath, sizeof(NINUpdatePath), "%s/loader.dol", Settings.NINLoaderPath); snprintf(NINUpdatePath, sizeof(NINUpdatePath), "%s/loader.dol", Settings.NINLoaderPath);
RemoveFile(NINUpdatePath); RemoveFile(NINUpdatePath);
RemoveFile(NINUpdatePathBak); RemoveFile(NINUpdatePathBak);
}
WindowPrompt(tr( "Successfully Updated" ), 0, tr( "OK" )); else
{
// Restore backup file if found
RemoveFile(NINUpdatePath);
if(CheckFile(NINUpdatePathBak))
RenameFile(NINUpdatePathBak, NINUpdatePath);
WindowPrompt(tr( "Update failed" ), 0, tr( "OK" ));
} }
} }
} }

View File

@ -224,7 +224,10 @@ void GlobalSettings::CreateSettingsMenu(int menuNr)
return; return;
} }
returnMenu = MENU_THEMEDOWNLOADER; WindowPrompt(tr( "Warning:" ), tr( "Sorry, the theme downloader menu is not working anymore because http://wii.spiffy360.com now requires user registration." ), tr( "OK" ));
return;
// returnMenu = MENU_THEMEDOWNLOADER;
} }
//! Update //! Update
else if(menuNr == Idx++) else if(menuNr == Idx++)

View File

@ -134,6 +134,16 @@ s32 IosPatch_RUNTIME(bool wii, bool sciifii, bool vwii, bool verbose);
*/ */
s32 IosPatch_FULL(bool wii, bool sciifii, bool vwii, bool verbose, int IOS); s32 IosPatch_FULL(bool wii, bool sciifii, bool vwii, bool verbose, int IOS);
/**
* This function patches only SSL certificate check
* @param verbose Flag determing whether or not to print messages on-screen.
* @example if(AHBPROT_DISABLED) IosPatch_SSL(true);
* @return Signed 32bit integer representing code
* > 0 : Success - return equals to number of applied patches
* ERROR_AHBPROT : Error - No HW_AHBPROT access
*/
s32 IosPatch_SSL(bool verbose);
//============================================================================== //==============================================================================
// C++ footer // C++ footer
//============================================================================== //==============================================================================