added option to automatically load latest sep/baseband (untested)

This commit is contained in:
tihmstar 2016-09-21 19:56:44 +02:00
parent 8c08fb0a29
commit 20851cc697
3 changed files with 193 additions and 30 deletions

View file

@ -21,10 +21,20 @@
#include "ipsw.h" #include "ipsw.h"
#include "locking.h" #include "locking.h"
#include "restore.h" #include "restore.h"
#include "tsschecker.h"
#define NONCESIZE 20 #define NONCESIZE 20
#define USEC_PER_SEC 1000000 #define USEC_PER_SEC 1000000
#define TMP_PATH "/tmp"
#define FUTURERESTORE_TMP_PATH TMP_PATH"/futurerestore"
#define BASEBAND_TMP_PATH FUTURERESTORE_TMP_PATH"/baseband.bbfw"
#define BASEBAND_MANIFEST_TMP_PATH FUTURERESTORE_TMP_PATH"/basebandManifest.plist"
#define SEP_TMP_PATH FUTURERESTORE_TMP_PATH"/sep.im4p"
#define SEP_MANIFEST_TMP_PATH FUTURERESTORE_TMP_PATH"/sepManifest.plist"
#define reterror(code,msg ...) error(msg),throw int(code) #define reterror(code,msg ...) error(msg),throw int(code)
#define safeFree(buf) if (buf) free(buf), buf = NULL #define safeFree(buf) if (buf) free(buf), buf = NULL
#define safePlistFree(buf) if (buf) plist_free(buf), buf = NULL #define safePlistFree(buf) if (buf) plist_free(buf), buf = NULL
@ -32,9 +42,12 @@
futurerestore::futurerestore(){ futurerestore::futurerestore(){
_client = idevicerestore_client_new(); _client = idevicerestore_client_new();
if (_client == NULL) throw std::string("could not create idevicerestore client\n"); if (_client == NULL) throw std::string("could not create idevicerestore client\n");
_didInit = false;
_apticket = NULL; struct stat st{0};
_im4m = NULL; if (stat(FUTURERESTORE_TMP_PATH, &st) == -1) mkdir(FUTURERESTORE_TMP_PATH, 0755);
//tsschecker nocache
nocache = 1;
} }
bool futurerestore::init(){ bool futurerestore::init(){
@ -441,11 +454,102 @@ error:
futurerestore::~futurerestore(){ futurerestore::~futurerestore(){
idevicerestore_client_free(_client); idevicerestore_client_free(_client);
safeFree(_im4m); safeFree(_im4m);
safeFree(_firmwareJson);
safeFree(_firmwareTokens);
safeFree(__latestManifest);
safeFree(__latestFirmwareUrl);
safePlistFree(_apticket); safePlistFree(_apticket);
} }
void futurerestore::loadFirmwareTokens(){
if (_firmwareTokens){
if (!_firmwareJson) _firmwareJson = getFirmwareJson();
if (!_firmwareJson) reterror(-6,"[TSSC] could not get firmware.json\n");
int cnt = parseTokens(_firmwareJson, &_firmwareTokens);
if (cnt < 1) reterror(-2,"[TSSC] parsing %s.json failed\n",(0) ? "ota" : "firmware");
}
}
const char *futurerestore::getConnectedDeviceModel(){
if (!_client->device->hardware_model){
int mode = getDeviceMode(true);
if (mode != MODE_NORMAL && mode != MODE_RECOVERY)
reterror(-20, "unexpected device mode=%d\n",mode);
if (check_hardware_model(_client) == NULL || _client->device == NULL)
reterror(-2,"ERROR: Unable to discover device model\n");
}
return _client->device->hardware_model;
}
char *futurerestore::getLatestManifest(){
if (!__latestManifest){
loadFirmwareTokens();
const char *device = getConnectedDeviceModel();
t_iosVersion versVals;
memset(&versVals, 0, sizeof(versVals));
int versionCnt = 0;
int i = 0;
char **versions = getListOfiOSForDevice(_firmwareJson, _firmwareTokens, device, 0, &versionCnt);
if (!versionCnt) reterror(-8, "[TSSC] failed finding latest iOS\n");
char *bpos = NULL;
while((bpos = strstr(versVals.version = strdup(versions[i++]),"[B]")) != 0){
free((char*)versVals.version);
if (--versionCnt == 0) reterror(-9, "[TSSC] automatic iOS selection couldn't find non-beta iOS\n");
}
info("[TSSC] selecting latest iOS: %s\n",versVals.version);
if (bpos) *bpos= '\0';
if (versions) free(versions[versionCnt-1]),free(versions);
__latestFirmwareUrl = getFirmwareUrl(device, versVals, _firmwareJson, _firmwareTokens);
if (!__latestFirmwareUrl) reterror(-21, "could not find url of latest firmware\n");
__latestManifest = getBuildManifest(__latestFirmwareUrl, device, versVals.version, 0);
if (!__latestManifest) reterror(-22, "could not get buildmanifest of latest firmware\n");
free((char*)versVals.version);
}
return __latestManifest;
}
char *futurerestore::getLatestFirmwareUrl(){
return getLatestManifest(),__latestFirmwareUrl;
}
void futurerestore::loadLatestBaseband(){
char * manifeststr = getLatestManifest();
char *pathStr = getPathOfElementInManifest("BasebandFirmware", manifeststr);
if (!downloadPartialzip(getLatestFirmwareUrl(), pathStr, _basebandPath = BASEBAND_TMP_PATH))
reterror(-32, "could not download baseband\n");
saveStringToFile(manifeststr, _basebandManifestPath = BASEBAND_MANIFEST_TMP_PATH);
}
void futurerestore::loadLatestSep(){
char * manifeststr = getLatestManifest();
char *pathStr = getPathOfElementInManifest("SEP", manifeststr);
if (!downloadPartialzip(getLatestFirmwareUrl(), pathStr, _sepPath = SEP_TMP_PATH))
reterror(-33, "could not download SEP\n");
saveStringToFile(manifeststr, _sepManifestPath = SEP_MANIFEST_TMP_PATH);
}
#pragma mark static methods #pragma mark static methods
inline void futurerestore::saveStringToFile(const char *str, const char *path){
FILE *f = fopen(path, "w");
if (!f) reterror(-41,"can't save file at %s\n",path);
else{
size_t len = strlen(str);
size_t wlen = fwrite(str, len, 1, f);
fclose(f);
if (len != wlen) reterror(-42, "saving file failed, wrote=%zu actual=%zu\n",wlen,len);
}
}
char *futurerestore::getNonceFromIM4M(const char* im4m){ char *futurerestore::getNonceFromIM4M(const char* im4m){
char *ret = NULL; char *ret = NULL;
t_asn1Tag *mainSet = NULL; t_asn1Tag *mainSet = NULL;
@ -536,3 +640,22 @@ plist_t futurerestore::loadPlistFromFile(const char *path){
return ret; return ret;
} }
char *futurerestore::getPathOfElementInManifest(const char *element, const char *manifeststr){
char *pathStr = NULL;
plist_t buildmanifest;
plist_from_xml(manifeststr, (uint)strlen(manifeststr), &buildmanifest);
if (plist_t buildidentities = plist_dict_get_item(buildmanifest, "BuildIdentities"))
if (plist_t firstIdentitie = plist_array_get_item(buildidentities, 0))
if (plist_t manifest = plist_dict_get_item(firstIdentitie, element))
if (plist_t info = plist_dict_get_item(manifest, "Info"))
if (plist_t path = plist_dict_get_item(info, "Path"))
if (plist_get_string_val(path, &pathStr), pathStr)
goto noerror;
reterror(-31, "could not get %s path\n",element);
noerror:
plist_free(buildmanifest);
return pathStr;
}

View file

@ -12,19 +12,26 @@
#include "config.h" #include "config.h"
#include <stdio.h> #include <stdio.h>
#include "idevicerestore.h" #include "idevicerestore.h"
#include "jsmn.h"
using namespace std; using namespace std;
class futurerestore { class futurerestore {
struct idevicerestore_client_t* _client; struct idevicerestore_client_t* _client;
bool _didInit; bool _didInit = false;
plist_t _apticket; plist_t _apticket = NULL;
char *_im4m; char *_im4m = NULL;
char *_firmwareJson = NULL;
jsmntok_t *_firmwareTokens = NULL;;
char *__latestManifest = NULL;
char *__latestFirmwareUrl = NULL;
const char *_sepManifestPath = NULL;
const char *_basebandManifestPath = NULL;
const char *_sepPath = NULL;
const char *_basebandPath = NULL;
const char *_sepManifestPath;
const char *_basebandManifestPath;
const char *_sepPath;
const char *_basebandPath;
public: public:
futurerestore(); futurerestore();
@ -40,12 +47,25 @@ public:
bool nonceMatchesApTicket(); bool nonceMatchesApTicket();
void loadFirmwareTokens();
const char *getConnectedDeviceModel();
char *getLatestManifest();
char *getLatestFirmwareUrl();
void loadLatestBaseband();
void loadLatestSep();
void setSepManifestPath(const char *sepManifestPath){_sepManifestPath = sepManifestPath;}; void setSepManifestPath(const char *sepManifestPath){_sepManifestPath = sepManifestPath;};
void setBasebandManifestPath(const char *basebandManifestPath){_basebandManifestPath = basebandManifestPath;}; void setBasebandManifestPath(const char *basebandManifestPath){_basebandManifestPath = basebandManifestPath;};
void setSepPath(const char *sepPath){_sepPath = sepPath;}; void setSepPath(const char *sepPath){_sepPath = sepPath;};
void setBasebandPath(const char *basebandPath){_basebandPath = basebandPath;}; void setBasebandPath(const char *basebandPath){_basebandPath = basebandPath;};
const char *sepManifestPath(){return _sepManifestPath;};
const char *basebandManifestPath(){return _basebandManifestPath;};
const char *sepPath(){return _sepPath;};
const char *basebandPath(){return _basebandPath;};
int doRestore(const char *ipsw, bool noerase); int doRestore(const char *ipsw, bool noerase);
~futurerestore(); ~futurerestore();
@ -53,6 +73,8 @@ public:
static char *getNonceFromIM4M(const char* im4m); static char *getNonceFromIM4M(const char* im4m);
static char *getNonceFromAPTicket(const char* apticketPath); static char *getNonceFromAPTicket(const char* apticketPath);
static plist_t loadPlistFromFile(const char *path); static plist_t loadPlistFromFile(const char *path);
static void saveStringToFile(const char *str, const char *path);
static char *getPathOfElementInManifest(const char *element, const char *manifeststr);
}; };

View file

@ -16,19 +16,23 @@
#define safePlistFree(buf) if (buf) plist_free(buf), buf = NULL #define safePlistFree(buf) if (buf) plist_free(buf), buf = NULL
static struct option longopts[] = { static struct option longopts[] = {
{ "apticket", required_argument, NULL, 't' }, { "apticket", required_argument, NULL, 't' },
{ "baseband", required_argument, NULL, 'b' }, { "baseband", required_argument, NULL, 'b' },
{ "baseband-plist", required_argument, NULL, 'p' }, { "baseband-plist", required_argument, NULL, 'p' },
{ "sep", required_argument, NULL, 's' }, { "sep", required_argument, NULL, 's' },
{ "sep-manifest", required_argument, NULL, 'm' }, { "sep-manifest", required_argument, NULL, 'm' },
{ "wait", no_argument, NULL, 'w' }, { "wait", no_argument, NULL, 'w' },
{ "update", no_argument, NULL, 'u' }, { "update", no_argument, NULL, 'u' },
{ "debug", no_argument, NULL, 'd' }, { "debug", no_argument, NULL, 'd' },
{ "latest-sep", no_argument, NULL, '0' },
{ "latest-baseband", no_argument, NULL, '1' },
{ NULL, 0, NULL, 0 } { NULL, 0, NULL, 0 }
}; };
#define FLAG_WAIT 1 << 0 #define FLAG_WAIT 1 << 0
#define FLAG_UPDATE 1 << 1 #define FLAG_UPDATE 1 << 1
#define FLAG_LATEST_SEP 1 << 2
#define FLAG_LATEST_BASEBAND 1 << 3
void cmd_help(){ void cmd_help(){
printf("Usage: futurerestore [OPTIONS] IPSW\n"); printf("Usage: futurerestore [OPTIONS] IPSW\n");
@ -75,7 +79,7 @@ int main(int argc, const char * argv[]) {
return -1; return -1;
} }
while ((opt = getopt_long(argc, (char* const *)argv, "ht:b:p:s:m:wud", longopts, &optindex)) > 0) { while ((opt = getopt_long(argc, (char* const *)argv, "ht:b:p:s:m:wud01", longopts, &optindex)) > 0) {
switch (opt) { switch (opt) {
case 't': // long option: "apticket"; can be called as short option case 't': // long option: "apticket"; can be called as short option
apticketPath = optarg; apticketPath = optarg;
@ -98,6 +102,12 @@ int main(int argc, const char * argv[]) {
case 'u': // long option: "update"; can be called as short option case 'u': // long option: "update"; can be called as short option
flags |= FLAG_UPDATE; flags |= FLAG_UPDATE;
break; break;
case '0': // long option: "latest-sep";
flags |= FLAG_LATEST_SEP;
break;
case '1': // long option: "latest-baseband";
flags |= FLAG_LATEST_BASEBAND;
break;
case 'd': // long option: "debug"; can be called as short option case 'd': // long option: "debug"; can be called as short option
idevicerestore_debug = 1; idevicerestore_debug = 1;
break; break;
@ -122,7 +132,9 @@ int main(int argc, const char * argv[]) {
client.putDeviceIntoRecovery(); client.putDeviceIntoRecovery();
client.waitForNonce(); client.waitForNonce();
} }
if (!(apticketPath && basebandPath && basebandManifestPath && sepPath && sepManifestPath && ipsw)) { if (!(apticketPath && ipsw)
&& ((basebandPath && basebandManifestPath) || (flags & FLAG_LATEST_BASEBAND))
&& ((sepPath && sepManifestPath) || (flags & FLAG_LATEST_SEP)) ) {
if (!(flags & FLAG_WAIT) || ipsw){ if (!(flags & FLAG_WAIT) || ipsw){
error("missing argument\n"); error("missing argument\n");
cmd_help(); cmd_help();
@ -134,22 +146,28 @@ int main(int argc, const char * argv[]) {
} }
if (flags & FLAG_LATEST_SEP) client.loadLatestSep();
else{
client.setSepPath(sepPath);
client.setSepManifestPath(sepManifestPath);
}
if (flags & FLAG_LATEST_BASEBAND) client.loadLatestBaseband();
else{
client.setBasebandPath(basebandPath);
client.setBasebandManifestPath(basebandManifestPath);
}
versVals.basebandMode = kBasebandModeWithoutBaseband; versVals.basebandMode = kBasebandModeWithoutBaseband;
if (!(isSepManifestSigned = isManifestSignedForDevice(sepManifestPath, NULL, devVals, versVals))){ if (!(isSepManifestSigned = isManifestSignedForDevice(client.sepManifestPath(), NULL, devVals, versVals))){
reterror(-3,"sep firmware isn't signed\n"); reterror(-3,"sep firmware isn't signed\n");
} }
versVals.basebandMode = kBasebandModeOnlyBaseband; versVals.basebandMode = kBasebandModeOnlyBaseband;
if (!(isBasebandSigned = isManifestSignedForDevice(basebandManifestPath, NULL, devVals, versVals))){ if (!(isBasebandSigned = isManifestSignedForDevice(client.basebandManifestPath(), NULL, devVals, versVals))){
reterror(-3,"baseband firmware isn't signed\n"); reterror(-3,"baseband firmware isn't signed\n");
} }
client.setSepPath(sepPath);
client.setSepManifestPath(sepManifestPath);
client.setBasebandPath(basebandPath);
client.setBasebandManifestPath(basebandManifestPath);
client.putDeviceIntoRecovery(); client.putDeviceIntoRecovery();
try { try {