// // If plist_from_bin will fail, xmlBuff_ will remain unchanged, pointing to PREVIOUS-SAVED xml buffer. // const CharVt& PlistEntry::GetXML(CharVt&& BplistBuff) { GuardedPlist plist; try { plist_from_bin(BplistBuff.data(), BplistBuff.size(), plist.get_ptr()); } catch (...) { // catch SEH exceptions (/withSEH) throw std::system_error(std::error_code(EFAULT, std::generic_category()), "Invalid bplist file! Cant parse it"); } uint32_t cbXML = 0; char* pXML_{}; plist_to_xml( plist, &pXML_, &cbXML ); if ( cbXML > 0 ) { xmlBuff_.assign( pXML_, pXML_ + cbXML ); // free mem allocated by plist_to_xml free( pXML_ ); } if ( xmlBuff_.empty() ) { contentType_ = ContentType::corrupted; throw std::runtime_error( "error converting bplist to xml" ); } contentType_ = ContentType::xml; return xmlBuff_; }
/** Polls the iPhone for MobileSync data. * * @param client The MobileSync client * @param plist A pointer to the location where the plist should be stored * * @return an error code */ mobilesync_error_t mobilesync_recv(mobilesync_client_t client, plist_t * plist) { if (!client || !plist || (plist && *plist)) return MOBILESYNC_E_INVALID_ARG; mobilesync_error_t ret = MOBILESYNC_E_UNKNOWN_ERROR; char *receive = NULL; uint32_t datalen = 0, bytes = 0, received_bytes = 0; ret = iphone_device_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes); datalen = ntohl(datalen); receive = (char *) malloc(sizeof(char) * datalen); /* fill buffer and request more packets if needed */ while ((received_bytes < datalen) && (ret == MOBILESYNC_E_SUCCESS)) { ret = iphone_device_recv(client->connection, receive + received_bytes, datalen - received_bytes, &bytes); received_bytes += bytes; } if (ret != MOBILESYNC_E_SUCCESS) { free(receive); return MOBILESYNC_E_MUX_ERROR; } plist_from_bin(receive, received_bytes, plist); free(receive); char *XMLContent = NULL; uint32_t length = 0; plist_to_xml(*plist, &XMLContent, &length); log_dbg_msg(DBGMASK_MOBILESYNC, "%s: plist size: %i\nbuffer :\n%s\n", __func__, length, XMLContent); free(XMLContent); return ret; }
/** Sends MobileSync data to the iPhone * * @note This function is low-level and should only be used if you need to send * a new type of message. * * @param client The MobileSync client * @param plist The location of the plist to send * * @return an error code */ mobilesync_error_t mobilesync_send(mobilesync_client_t client, plist_t plist) { if (!client || !plist) return MOBILESYNC_E_INVALID_ARG; char *XMLContent = NULL; uint32_t length = 0; plist_to_xml(plist, &XMLContent, &length); log_dbg_msg(DBGMASK_MOBILESYNC, "%s: plist size: %i\nbuffer :\n%s\n", __func__, length, XMLContent); free(XMLContent); char *content = NULL; length = 0; plist_to_bin(plist, &content, &length); char *real_query; int bytes; mobilesync_error_t ret = MOBILESYNC_E_UNKNOWN_ERROR; real_query = (char *) malloc(sizeof(char) * (length + 4)); length = htonl(length); memcpy(real_query, &length, sizeof(length)); memcpy(real_query + 4, content, ntohl(length)); ret = iphone_device_send(client->connection, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes); free(real_query); return (ret == 0 ? MOBILESYNC_E_SUCCESS: MOBILESYNC_E_MUX_ERROR); }
FB::variant ibrowserAPI::getAppList(F_ADD) { THREAD(&ibrowserAPI::getAppList); char *xml_doc=NULL; uint32_t xml_length=0; plist_t node = NULL; plist_t client_opts = instproxy_client_options_new(); instproxy_client_options_add(client_opts, "ApplicationType", "User", NULL); if(INSTPROXY_E_SUCCESS != instproxy_browse(instproxy_client,client_opts,&node)) { ERRO("instproxy_browse"); } instproxy_client_options_free(client_opts); plist_to_xml(node, &xml_doc, &xml_length); plist_free(node); SUCC(xml_doc); return xml_doc; }
FB::variant ibrowserAPI::getDeviceInfo(const std::vector<std::string>& domains,F_ADD) { THREAD(&ibrowserAPI::getDeviceInfo, domains); std::vector<std::string> result; for(int i=0;i<domains.size();i++) { std::string domain = domains[i]; plist_t node = NULL; int ret = 0; if(LOCKDOWN_E_SUCCESS != (ret = lockdownd_get_value(lockdownd_client, domain.empty()?NULL:domain.c_str(), NULL, &node)) ) { ERRO("lockdownd_get_value"); } char *xml_doc=NULL; uint32_t xml_length; plist_to_xml(node, &xml_doc, &xml_length); plist_free(node); result.insert(result.end(),std::string(xml_doc)); free(xml_doc); } SUCC(result); return result; }
void debug_plist(plist_t plist) { int size = 0; char* data = NULL; plist_to_xml(plist, &data, &size); info("%s", data); free(data); }
dl_status dl_start(dl_t self) { // Assume usbmuxd supports proto_version 1. If not then we'd need to // send a binary listen request, check for failure, then retry this: plist_t dict = plist_new_dict(); plist_dict_insert_item(dict, "ClientVersionString", plist_new_string( "device_listener")); plist_dict_insert_item(dict, "MessageType", plist_new_string("Listen")); plist_dict_insert_item(dict, "ProgName", plist_new_string("libusbmuxd")); char *xml = NULL; uint32_t xml_length = 0; plist_to_xml(dict, &xml, &xml_length); plist_free(dict); size_t length = 16 + xml_length; char *packet = (char *)calloc(length, sizeof(char)); if (!packet) { return DL_ERROR; } char *tail = packet; tail = dl_sprintf_uint32(tail, length); tail = dl_sprintf_uint32(tail, 1); // version: 1 tail = dl_sprintf_uint32(tail, TYPE_PLIST); // type: plist tail = dl_sprintf_uint32(tail, 1); // tag: 1 tail = stpncpy(tail, xml, xml_length); free(xml); dl_status ret = self->send_packet(self, packet, length); free(packet); return ret; }
wi_status recv_plist(wi_t wi, const plist_t rpc_dict) { char *xml = NULL; uint32_t length = 0; plist_to_xml(rpc_dict, &xml, &length); puts(xml); free(xml); return WI_SUCCESS; }
static void print_xml(plist_t node) { char *xml = NULL; uint32_t len = 0; plist_to_xml(node, &xml, &len); if (xml) puts(xml); }
void debug_plist(plist_t plist) { uint32_t size = 0; char* data = NULL; plist_to_xml(plist, &data, &size); if (size <= MAX_PRINT_LEN) info("%s:printing %i bytes plist:\n%s", __FILE__, size, data); else info("%s:supressed printing %i bytes plist...\n", __FILE__, size); free(data); }
static plist_t plist_data_from_plist(plist_t plist) { if (plist && plist_get_node_type(plist) == PLIST_DATA) { return plist_copy(plist); } plist_t result = NULL; char *xml = NULL; uint32_t xml_len = 0; plist_to_xml(plist, &xml, &xml_len); result = plist_new_data(xml, xml_len); free(xml); return result; }
static int send_plist_pkt(struct mux_client *client, uint32_t tag, plist_t plist) { int res = -1; char *xml = NULL; uint32_t xmlsize = 0; plist_to_xml(plist, &xml, &xmlsize); if (xml) { res = send_pkt(client, tag, MESSAGE_PLIST, xml, xmlsize); free(xml); } else { usbmuxd_log(LL_ERROR, "%s: Could not convert plist to xml", __func__); } return res; }
void ibrowserAPI::installCallback(const char *operation, plist_t status, void *user_data) { char *xml_doc=NULL; uint32_t xml_length; Callback *cb = (Callback *)user_data; FB::JSObjectPtr pcb = cb->get("pcb"); FB::JSObjectPtr scb = cb->get("scb"); FB::JSObjectPtr ecb = cb->get("ecb"); if(pcb) { plist_to_xml(status, &xml_doc, &xml_length); pcb->InvokeAsync("", FB::variant_list_of(xml_doc)); free(xml_doc); } plist_dict_iter it = NULL; char* key = NULL; char* s = NULL; plist_t subnode = NULL; plist_dict_new_iter(status, &it); plist_dict_next_item(status, it, &key, &subnode); while (subnode) { if(strcmp(key, "Error") == 0) { plist_get_string_val(subnode, &s); if(ecb) ecb->InvokeAsync("", FB::variant_list_of(s)); }else if(strcmp(key, "Status") == 0){ plist_get_string_val(subnode, &s); if(strcmp(s, "Complete") == 0){ if(scb) scb->InvokeAsync("", FB::variant_list_of(NULL)); } } plist_dict_next_item(status, it, &key, &subnode); } if(key) free(key); if(s) free(s); free(it); return; }
int asr_send(asr_client_t asr, plist_t data) { uint32_t size = 0; char* buffer = NULL; plist_to_xml(data, &buffer, &size); if (asr_send_buffer(asr, buffer, size) < 0) { error("ERROR: Unable to send plist to ASR\n"); free(buffer); return -1; } if (buffer) free(buffer); return 0; }
int asr_send(idevice_connection_t asr, plist_t* data) { uint32_t size = 0; char* buffer = NULL; plist_to_xml(data, &buffer, &size); if (asr_send_buffer(asr, buffer, size) < 0) { error("ERROR: Unable to send plist to ASR\n"); free(buffer); return -1; } debug("Sent %d bytes:\n", size); debug_plist(data); free(buffer); return 0; }
int cache_plist(const char *fname, plist_t plist) { if (backup_to_cache==1) { uint32_t len=0; char *xml=NULL; plist_to_xml(plist, &xml, &len); return cache(fname, (const char *)xml); } else { return -1; } }
/** * Sends a plist using the given property list service client. * Internally used generic plist send function. * * @param client The property list service client to use for sending. * @param plist plist to send * @param binary 1 = send binary plist, 0 = send xml plist * * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success, * PROPERTY_LIST_SERVICE_E_INVALID_ARG when one or more parameters are * invalid, PROPERTY_LIST_SERVICE_E_PLIST_ERROR when dict is not a valid * plist, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when an unspecified * error occurs. */ static property_list_service_error_t internal_plist_send(property_list_service_client_t client, plist_t plist, int binary) { property_list_service_error_t res = PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR; char *content = NULL; uint32_t length = 0; uint32_t nlen = 0; int bytes = 0; if (!client || (client && !client->parent) || !plist) { return PROPERTY_LIST_SERVICE_E_INVALID_ARG; } if (binary) { plist_to_bin(plist, &content, &length); } else { plist_to_xml(plist, &content, &length); } if (!content || length == 0) { return PROPERTY_LIST_SERVICE_E_PLIST_ERROR; } nlen = htobe32(length); debug_info("sending %d bytes", length); service_send(client->parent, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); if (bytes == sizeof(nlen)) { service_send(client->parent, content, length, (uint32_t*)&bytes); if (bytes > 0) { debug_info("sent %d bytes", bytes); debug_plist(plist); if ((uint32_t)bytes == length) { res = PROPERTY_LIST_SERVICE_E_SUCCESS; } else { debug_info("ERROR: Could not send all data (%d of %d)!", bytes, length); } } } if (bytes <= 0) { debug_info("ERROR: sending to device failed."); } free(content); return res; }
inline void debug_plist_real(const char *func, const char *file, int line, plist_t plist) { #ifndef STRIP_DEBUG_CODE if (!plist) return; char *buffer = NULL; uint32_t length = 0; plist_to_xml(plist, &buffer, &length); /* get rid of ending newline as one is already added in the debug line */ if (buffer[length-1] == '\n') buffer[length-1] = '\0'; debug_info_real(func, file, line, "printing %i bytes plist:\n%s", length, buffer); free(buffer); #endif }
int asr_send(idevice_connection_t asr, plist_t* data) { uint32_t size = 0; char* buffer = NULL; plist_to_xml(data, &buffer, &size); if (asr_send_buffer(asr, buffer, size) < 0) { error("ERROR: Unable to send plist to ASR\n"); free(buffer); return -1; } debug("Sent %d bytes:\n", size); // TODO: Actually figure out the problem with the commented out code below, instead of just ditching it... /*if (idevicerestore_debug) debug_plist(*data); free(buffer);*/ return 0; }
int plist_write_to_filename(plist_t plist, const char *filename, enum plist_format_t format) { char *buffer = NULL; uint32_t length; if (!plist || !filename) return 0; if (format == PLIST_FORMAT_XML) plist_to_xml(plist, &buffer, &length); else if (format == PLIST_FORMAT_BINARY) plist_to_bin(plist, &buffer, &length); else return 0; buffer_write_to_filename(filename, buffer, length); free(buffer); return 1; }
/** * Sends an xml plist to the device using the connection specified in client. * This function is only used internally. * * @param client NP to send data to * @param dict plist to send * * @return NP_E_SUCCESS or an error code. */ static np_error_t np_plist_send(np_client_t client, plist_t dict) { char *XML_content = NULL; uint32_t length = 0; uint32_t nlen = 0; int bytes = 0; np_error_t res = NP_E_UNKNOWN_ERROR; if (!client || !dict) { return NP_E_INVALID_ARG; } plist_to_xml(dict, &XML_content, &length); if (!XML_content || length == 0) { return NP_E_PLIST_ERROR; } nlen = htonl(length); iphone_device_send(client->connection, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); if (bytes == sizeof(nlen)) { iphone_device_send(client->connection, XML_content, length, (uint32_t*)&bytes); if (bytes > 0) { if ((uint32_t)bytes == length) { res = NP_E_SUCCESS; } else { log_debug_msg("%s: ERROR: Could not send all data (%d of %d)!\n", __func__, bytes, length); } } } if (bytes <= 0) { log_debug_msg("%s: ERROR: sending to device failed.\n", __func__); } free(XML_content); return res; }
plist_t tss_send_request(plist_t tss_request) { curl_global_init(CURL_GLOBAL_ALL); int status_code = -1; char* request = NULL; int retry = 0; int max_retries = 15; unsigned int size = 0; plist_to_xml(tss_request, &request, &size); tss_response* response = NULL; while (retry++ < max_retries) { response = NULL; CURL* handle = curl_easy_init(); if (handle == NULL) { break; } struct curl_slist* header = NULL; header = curl_slist_append(header, "Cache-Control: no-cache"); header = curl_slist_append(header, "Content-type: text/xml; charset=\"utf-8\""); header = curl_slist_append(header, "Expect:"); response = malloc(sizeof(tss_response)); if (response == NULL) { fprintf(stderr, "Unable to allocate sufficent memory\n"); return NULL; } response->length = 0; response->content = malloc(1); response->content[0] = '\0'; curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, (curl_write_callback)&tss_write_callback); curl_easy_setopt(handle, CURLOPT_WRITEDATA, response); curl_easy_setopt(handle, CURLOPT_HTTPHEADER, header); curl_easy_setopt(handle, CURLOPT_POSTFIELDS, request); curl_easy_setopt(handle, CURLOPT_USERAGENT, "InetURL/1.0"); curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, strlen(request)); if (use_apple_server==0) { curl_easy_setopt(handle, CURLOPT_URL, "http://cydia.saurik.com/TSS/controller?action=2"); } else { curl_easy_setopt(handle, CURLOPT_URL, "http://gs.apple.com/TSS/controller?action=2"); } curl_easy_perform(handle); curl_slist_free_all(header); curl_easy_cleanup(handle); if (strstr(response->content, "MESSAGE=SUCCESS")) { status_code = 0; break; } if (response->length > 0) { error("TSS server returned: %s\n", response->content); } char* status = strstr(response->content, "STATUS="); if (status) { sscanf(status+7, "%d&%*s", &status_code); } if (status_code == -1) { // no status code in response. retry free(response->content); free(response); sleep(2); continue; } else if (status_code == 94) { // This device isn't eligible for the requested build. break; } else if (status_code == 100) { // server error, most likely the request was malformed break; } else { error("ERROR: tss_send_request: Unhandled status code %d\n", status_code); } } if (status_code != 0) { error("ERROR: TSS request failed (status=%d)\n", status_code); free(response->content); free(response); free(request); return NULL; } char* tss_data = strstr(response->content, "<?xml"); if (tss_data == NULL) { error("ERROR: Incorrectly formatted TSS response\n"); free(response->content); free(response); free(request); return NULL; } uint32_t tss_size = 0; plist_t tss_response = NULL; tss_size = response->length - (tss_data - response->content); plist_from_xml(tss_data, tss_size, &tss_response); free(response->content); free(response); if (idevicerestore_debug) { debug_plist(tss_response); } free(request); curl_global_cleanup(); return tss_response; }
int main(int argc, char *argv[]) { lockdownd_client_t client = NULL; idevice_t phone = NULL; idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; int i; int simple = 0; int format = FORMAT_KEY_VALUE; char uuid[41]; char *domain = NULL; char *key = NULL; char *xml_doc = NULL; uint32_t xml_length; plist_t node = NULL; plist_type node_type; uuid[0] = 0; /* parse cmdline args */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--uuid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); return 0; } strcpy(uuid, argv[i]); continue; } else if (!strcmp(argv[i], "-q") || !strcmp(argv[i], "--domain")) { i++; if (!argv[i] || (strlen(argv[i]) < 4)) { print_usage(argc, argv); return 0; } if (!is_domain_known(argv[i])) { fprintf(stderr, "WARNING: Sending query with unknown domain \"%s\".\n", argv[i]); } domain = strdup(argv[i]); continue; } else if (!strcmp(argv[i], "-k") || !strcmp(argv[i], "--key")) { i++; if (!argv[i] || (strlen(argv[i]) <= 1)) { print_usage(argc, argv); return 0; } key = strdup(argv[i]); continue; } else if (!strcmp(argv[i], "-x") || !strcmp(argv[i], "--xml")) { format = FORMAT_XML; continue; } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--simple")) { simple = 1; continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } else { print_usage(argc, argv); return 0; } } if (uuid[0] != 0) { ret = idevice_new(&phone, uuid); if (ret != IDEVICE_E_SUCCESS) { printf("No device found with uuid %s, is it plugged in?\n", uuid); return -1; } } else { ret = idevice_new(&phone, NULL); if (ret != IDEVICE_E_SUCCESS) { printf("No device found, is it plugged in?\n"); return -1; } } if (LOCKDOWN_E_SUCCESS != (simple ? lockdownd_client_new(phone, &client, "ideviceinfo"): lockdownd_client_new_with_handshake(phone, &client, "ideviceinfo"))) { idevice_free(phone); return -1; } /* run query and output information */ if(lockdownd_get_value(client, domain, key, &node) == LOCKDOWN_E_SUCCESS) { if (node) { switch (format) { case FORMAT_XML: plist_to_xml(node, &xml_doc, &xml_length); printf("%s", xml_doc); free(xml_doc); break; case FORMAT_KEY_VALUE: node_type = plist_get_node_type(node); if (node_type == PLIST_DICT) { plist_dict_to_string(node); } else if (node_type == PLIST_ARRAY) { plist_array_to_string(node); break; } default: if (key != NULL) plist_node_to_string(node); break; } plist_free(node); node = NULL; } } if (domain != NULL) free(domain); lockdownd_client_free(client); idevice_free(phone); return 0; }
G_GNUC_INTERNAL char * read_sysinfo_extended_by_uuid (const char *uuid) { lockdownd_client_t client = NULL; idevice_t device = NULL; idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; char *xml = NULL; char *str = NULL; char *gxml; uint32_t xml_length = 0; plist_t value = NULL; plist_t global = NULL; plist_t ptr = NULL; int cnt = 0; /* usbmuxd needs some time to start up so we try several times * to open the device before finally returning with an error */ while (cnt++ < 20) { ret = idevice_new(&device, uuid); if (ret == IDEVICE_E_SUCCESS) { break; } if (ret != IDEVICE_E_NO_DEVICE) { break; } g_usleep (G_USEC_PER_SEC / 2); } if (ret != IDEVICE_E_SUCCESS) { printf("No device found with uuid %s, is it plugged in?\n", uuid); return NULL; } if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(device, &client, "libgpod")) { idevice_free(device); return NULL; } /* run query and get format plist */ lockdownd_get_value(client, NULL, NULL, &global); lockdownd_get_value(client, "com.apple.mobile.iTunes", NULL, &value); /* add some required values manually to emulate old plist format */ ptr = plist_dict_get_item(global, "SerialNumber"); plist_get_string_val(ptr, &str); if (str != NULL) { ptr = plist_new_string(str); plist_dict_insert_item(value, "SerialNumber", ptr); free(str); } ptr = plist_dict_get_item(global, "ProductVersion"); plist_get_string_val(ptr, &str); if (str != NULL) { ptr = plist_new_string(str); plist_dict_insert_item(value, "VisibleBuildID", ptr); free(str); } ptr = plist_new_string(uuid); plist_dict_insert_item(value, "FireWireGUID", ptr); ptr = plist_new_string(uuid); plist_dict_insert_item(value, "UniqueDeviceID", ptr); plist_to_xml(value, &xml, &xml_length); ptr = NULL; if (value) plist_free(value); value = NULL; if (global) plist_free(global); global = NULL; lockdownd_client_free(client); idevice_free(device); /* Jump through hoops since libxml will say to free mem it allocated * with xmlFree while memory freed with g_free has to be allocated * by glib. */ if (xml != NULL) { gxml = g_strdup(xml); xmlFree(xml); } else { gxml = NULL; } return gxml; }
void print_lckd_request_result(iphone_lckd_client_t control, const char *domain, const char *request, const char *key, int format) { char *xml_doc = NULL; char *s = NULL; uint32_t xml_length = 0; iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; plist_t node = plist_new_dict(); if (domain) { plist_add_sub_key_el(node, "Domain"); plist_add_sub_string_el(node, domain); } if (key) { plist_add_sub_key_el(node, "Key"); plist_add_sub_string_el(node, key); } plist_add_sub_key_el(node, "Request"); plist_add_sub_string_el(node, request); ret = iphone_lckd_send(control, node); if (ret == IPHONE_E_SUCCESS) { plist_free(node); node = NULL; ret = iphone_lckd_recv(control, &node); if (ret == IPHONE_E_SUCCESS) { /* seek to value node */ for ( node = plist_get_first_child(node); node != NULL; node = plist_get_next_sibling(node) ) { if(plist_get_node_type(node) == PLIST_KEY) { plist_get_key_val(node, &s); if (strcmp("Value", s)) continue; node = plist_get_next_sibling(node); if (plist_get_node_type(node) == PLIST_DICT) { if (plist_get_first_child(node)) { switch (format) { case FORMAT_XML: plist_to_xml(node, &xml_doc, &xml_length); printf(xml_doc); free(xml_doc); break; case FORMAT_KEY_VALUE: default: plist_children_to_string(node); break; } } } else if(node && (key != NULL)) plist_node_to_string(node); } } } } if (node) plist_free(node); node = NULL; }
int main(int argc, char *argv[]) { lockdownd_client_t client = NULL; lockdownd_error_t ldret = LOCKDOWN_E_UNKNOWN_ERROR; lockdownd_service_descriptor_t service = NULL; idevice_t device = NULL; idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; int i; int op = -1; int output_xml = 0; const char* udid = NULL; const char* param = NULL; /* parse cmdline args */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); return 0; } udid = argv[i]; continue; } else if (!strcmp(argv[i], "install")) { i++; if (!argv[i] || (strlen(argv[i]) < 1)) { print_usage(argc, argv); return 0; } param = argv[i]; op = OP_INSTALL; continue; } else if (!strcmp(argv[i], "list")) { op = OP_LIST; } else if (!strcmp(argv[i], "copy")) { i++; if (!argv[i] || (strlen(argv[i]) < 1)) { print_usage(argc, argv); return 0; } param = argv[i]; op = OP_COPY; continue; } else if (!strcmp(argv[i], "remove")) { i++; if (!argv[i] || (strlen(argv[i]) < 1)) { print_usage(argc, argv); return 0; } param = argv[i]; op = OP_REMOVE; continue; } else if (!strcmp(argv[i], "dump")) { i++; if (!argv[i] || (strlen(argv[i]) < 1)) { print_usage(argc, argv); return 0; } param = argv[i]; op = OP_DUMP; continue; } else if (!strcmp(argv[i], "-x") || !strcmp(argv[i], "--xml")) { output_xml = 1; continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } else { print_usage(argc, argv); return 0; } } if ((op == -1) || (op >= NUM_OPS)) { print_usage(argc, argv); return 0; } if (op == OP_DUMP) { int res = 0; unsigned char* profile_data = NULL; unsigned int profile_size = 0; if (profile_read_from_file(param, &profile_data, &profile_size) != 0) { return -1; } plist_t pdata = plist_new_data((char*)profile_data, profile_size); plist_t pl = profile_get_embedded_plist(pdata); plist_free(pdata); free(profile_data); if (pl) { if (output_xml) { char* xml = NULL; uint32_t xlen = 0; plist_to_xml(pl, &xml, &xlen); if (xml) { printf("%s\n", xml); free(xml); } } else { if (pl && (plist_get_node_type(pl) == PLIST_DICT)) { plist_print_to_stream(pl, stdout); } else { fprintf(stderr, "ERROR: unexpected node type in profile plist (not PLIST_DICT)\n"); res = -1; } } } else { fprintf(stderr, "ERROR: could not extract embedded plist from profile!\n"); } plist_free(pl); return res; } ret = idevice_new(&device, udid); if (ret != IDEVICE_E_SUCCESS) { if (udid) { printf("No device found with udid %s, is it plugged in?\n", udid); } else { printf("No device found, is it plugged in?\n"); } return -1; } if (LOCKDOWN_E_SUCCESS != (ldret = lockdownd_client_new_with_handshake(device, &client, "ideviceprovision"))) { fprintf(stderr, "ERROR: Could not connect to lockdownd, error code %d\n", ldret); idevice_free(device); return -1; } if (LOCKDOWN_E_SUCCESS != lockdownd_start_service(client, "com.apple.misagent", &service)) { fprintf(stderr, "Could not start service \"com.apple.misagent\"\n"); lockdownd_client_free(client); idevice_free(device); return -1; } lockdownd_client_free(client); client = NULL; misagent_client_t mis = NULL; if (misagent_client_new(device, service, &mis) != MISAGENT_E_SUCCESS) { fprintf(stderr, "Could not connect to \"com.apple.misagent\" on device\n"); if (service) lockdownd_service_descriptor_free(service); lockdownd_client_free(client); idevice_free(device); return -1; } if (service) lockdownd_service_descriptor_free(service); switch (op) { case OP_INSTALL: { unsigned char* profile_data = NULL; unsigned int profile_size = 0; if (profile_read_from_file(param, &profile_data, &profile_size) != 0) { break; } uint64_t psize = profile_size; plist_t pdata = plist_new_data((const char*)profile_data, psize); free(profile_data); if (misagent_install(mis, pdata) == MISAGENT_E_SUCCESS) { printf("Profile '%s' installed successfully.\n", param); } else { int sc = misagent_get_status_code(mis); fprintf(stderr, "Could not install profile '%s', status code: 0x%x\n", param, sc); } } break; case OP_LIST: case OP_COPY: { plist_t profiles = NULL; if (misagent_copy(mis, &profiles) == MISAGENT_E_SUCCESS) { uint32_t num_profiles = plist_array_get_size(profiles); printf("Device has %d provisioning %s installed:\n", num_profiles, (num_profiles == 1) ? "profile" : "profiles"); uint32_t j; for (j = 0; j < num_profiles; j++) { char* p_name = NULL; char* p_uuid = NULL; plist_t profile = plist_array_get_item(profiles, j); plist_t pl = profile_get_embedded_plist(profile); if (pl && (plist_get_node_type(pl) == PLIST_DICT)) { plist_t node; node = plist_dict_get_item(pl, "Name"); if (node && (plist_get_node_type(node) == PLIST_STRING)) { plist_get_string_val(node, &p_name); } node = plist_dict_get_item(pl, "UUID"); if (node && (plist_get_node_type(node) == PLIST_STRING)) { plist_get_string_val(node, &p_uuid); } } printf("%s - %s\n", (p_uuid) ? p_uuid : "(unknown id)", (p_name) ? p_name : "(no name)"); if (op == OP_COPY) { char pfname[512]; if (p_uuid) { sprintf(pfname, "%s/%s.mobileprovision", param, p_uuid); } else { sprintf(pfname, "%s/profile%d.mobileprovision", param, j); } FILE* f = fopen(pfname, "wb"); if (f) { char* dt = NULL; uint64_t ds = 0; plist_get_data_val(profile, &dt, &ds); fwrite(dt, 1, ds, f); fclose(f); printf(" => %s\n", pfname); } else { fprintf(stderr, "Could not open '%s' for writing\n", pfname); } } if (p_uuid) { free(p_uuid); } if (p_name) { free(p_name); } } } else { int sc = misagent_get_status_code(mis); fprintf(stderr, "Could not get installed profiles from device, status code: 0x%x\n", sc); } } break; case OP_REMOVE: if (misagent_remove(mis, param) == MISAGENT_E_SUCCESS) { printf("Profile '%s' removed.\n", param); } else { int sc = misagent_get_status_code(mis); fprintf(stderr, "Could not remove profile '%s', status code 0x%x\n", param, sc); } break; default: break; } misagent_client_free(mis); idevice_free(device); return 0; }
int main(int argc, char *argv[]) { lockdownd_client_t client = NULL; idevice_t phone = NULL; idevice_set_debug_level(1); if (IDEVICE_E_SUCCESS != idevice_new(&phone, NULL)) { printf("No device found, is it plugged in?\n"); return -1; } char *udid = NULL; if (IDEVICE_E_SUCCESS == idevice_get_udid(phone, &udid)) { printf("DeviceUniqueID : %s\n", udid); } if (udid) free(udid); if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(phone, &client, "lckdclient")) { idevice_free(phone); return -1; } using_history(); int loop = 1; while (loop) { char *cmd = readline("> "); if (cmd) { char **args = get_tokens(cmd); int len = 0; while (args && args[len]) { len++; } if (len > 0) { add_history(cmd); if (!strcmp(*args, "quit")) loop = 0; if (!strcmp(*args, "get") && len >= 2) { plist_t value = NULL; if (LOCKDOWN_E_SUCCESS == lockdownd_get_value(client, len == 3 ? *(args + 1):NULL, len == 3 ? *(args + 2):*(args + 1), &value)) { char *xml = NULL; uint32_t length; plist_to_xml(value, &xml, &length); printf("Success : value = %s\n", xml); free(xml); } else printf("Error\n"); if (value) plist_free(value); } if (!strcmp(*args, "start") && len == 2) { uint16_t port = 0; if(LOCKDOWN_E_SUCCESS == lockdownd_start_service(client, *(args + 1), &port)) { printf("started service %s on port %i\n", *(args + 1), port); } else { printf("failed to start service %s on device.\n", *(args + 1)); } } } strfreev(args); } free(cmd); cmd = NULL; } clear_history(); lockdownd_client_free(client); idevice_free(phone); return 0; }
int main(int argc, char *argv[]) { FILE *iplist = NULL; plist_t root_node1 = NULL; plist_t root_node2 = NULL; char *plist_xml = NULL; char *plist_xml2 = NULL; char *plist_bin = NULL; int size_in = 0; uint32_t size_out = 0; uint32_t size_out2 = 0; char *file_in = NULL; char *file_out = NULL; struct stat *filestats = (struct stat *) malloc(sizeof(struct stat)); if (argc != 3) { printf("Wrong input\n"); return 1; } file_in = argv[1]; file_out = argv[2]; //read input file iplist = fopen(file_in, "rb"); if (!iplist) { printf("File does not exists\n"); return 2; } printf("File %s is open\n", file_in); stat(file_in, filestats); size_in = filestats->st_size; plist_xml = (char *) malloc(sizeof(char) * (size_in + 1)); fread(plist_xml, sizeof(char), size_in, iplist); fclose(iplist); //convert one format to another plist_from_xml(plist_xml, size_in, &root_node1); if (!root_node1) { printf("PList XML parsing failed\n"); return 3; } else printf("PList XML parsing succeeded\n"); plist_to_bin(root_node1, &plist_bin, &size_out); if (!plist_bin) { printf("PList BIN writing failed\n"); return 4; } else printf("PList BIN writing succeeded\n"); plist_from_bin(plist_bin, size_out, &root_node2); if (!root_node2) { printf("PList BIN parsing failed\n"); return 5; } else printf("PList BIN parsing succeeded\n"); plist_to_xml(root_node2, &plist_xml2, &size_out2); if (!plist_xml2) { printf("PList XML writing failed\n"); return 8; } else printf("PList XML writing succeeded\n"); if (plist_xml2) { FILE *oplist = NULL; oplist = fopen(file_out, "wb"); fwrite(plist_xml2, size_out2, sizeof(char), oplist); fclose(oplist); } plist_free(root_node1); plist_free(root_node2); free(plist_bin); free(plist_xml); free(plist_xml2); free(filestats); if ((uint32_t)size_in != size_out2) { printf("Size of input and output is different\n"); printf("Input size : %i\n", size_in); printf("Output size : %i\n", size_out2); } //success return 0; }
plist_t tss_request_send(plist_t tss_request, const char* server_url_string) { if (idevicerestore_debug) { debug_plist(tss_request); } char* request = NULL; int status_code = -1; int retry = 0; int max_retries = 15; unsigned int size = 0; char curl_error_message[CURL_ERROR_SIZE]; const char* urls[6] = { "https://gs.apple.com/TSS/controller?action=2", "https://17.171.36.30/TSS/controller?action=2", "https://17.151.36.30/TSS/controller?action=2", "http://gs.apple.com/TSS/controller?action=2", "http://17.171.36.30/TSS/controller?action=2", "http://17.151.36.30/TSS/controller?action=2" }; plist_to_xml(tss_request, &request, &size); tss_response* response = NULL; memset(curl_error_message, '\0', CURL_ERROR_SIZE); while (retry++ < max_retries) { response = NULL; CURL* handle = curl_easy_init(); if (handle == NULL) { break; } struct curl_slist* header = NULL; header = curl_slist_append(header, "Cache-Control: no-cache"); header = curl_slist_append(header, "Content-type: text/xml; charset=\"utf-8\""); header = curl_slist_append(header, "Expect:"); response = malloc(sizeof(tss_response)); if (response == NULL) { fprintf(stderr, "Unable to allocate sufficent memory\n"); return NULL; } response->length = 0; response->content = malloc(1); response->content[0] = '\0'; /* disable SSL verification to allow download from untrusted https locations */ curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, curl_error_message); curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, (curl_write_callback)&tss_write_callback); curl_easy_setopt(handle, CURLOPT_WRITEDATA, response); curl_easy_setopt(handle, CURLOPT_HTTPHEADER, header); curl_easy_setopt(handle, CURLOPT_POSTFIELDS, request); curl_easy_setopt(handle, CURLOPT_USERAGENT, "InetURL/1.0"); curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, strlen(request)); if (server_url_string) { curl_easy_setopt(handle, CURLOPT_URL, server_url_string); } else { int url_index = (retry - 1) % 6; curl_easy_setopt(handle, CURLOPT_URL, urls[url_index]); info("Request URL set to %s\n", urls[url_index]); } info("Sending TSS request attempt %d... ", retry); curl_easy_perform(handle); curl_slist_free_all(header); curl_easy_cleanup(handle); if (strstr(response->content, "MESSAGE=SUCCESS")) { status_code = 0; info("response successfully received\n"); break; } if (response->length > 0) { error("TSS server returned: %s\n", response->content); } char* status = strstr(response->content, "STATUS="); if (status) { sscanf(status+7, "%d&%*s", &status_code); } if (status_code == -1) { error("%s\n", curl_error_message); // no status code in response. retry free(response->content); free(response); sleep(2); continue; } else if (status_code == 8) { // server error (invalid bb request?) break; } else if (status_code == 49) { // server error (invalid bb data, e.g. BbSNUM?) break; } else if (status_code == 69 || status_code == 94) { // This device isn't eligible for the requested build. break; } else if (status_code == 100) { // server error, most likely the request was malformed break; } else if (status_code == 126) { // An internal error occured, most likely the request was malformed break; } else { error("ERROR: tss_send_request: Unhandled status code %d\n", status_code); } } if (status_code != 0) { if (strstr(response->content, "MESSAGE=") != NULL) { char* message = strstr(response->content, "MESSAGE=") + strlen("MESSAGE="); error("ERROR: TSS request failed (status=%d, message=%s)\n", status_code, message); } else { error("ERROR: TSS request failed: %s (status=%d)\n", curl_error_message, status_code); } free(request); free(response->content); free(response); return NULL; } char* tss_data = strstr(response->content, "<?xml"); if (tss_data == NULL) { error("ERROR: Incorrectly formatted TSS response\n"); free(request); free(response->content); free(response); return NULL; } uint32_t tss_size = 0; plist_t tss_response = NULL; tss_size = response->length - (tss_data - response->content); plist_from_xml(tss_data, tss_size, &tss_response); free(response->content); free(response); if (idevicerestore_debug) { debug_plist(tss_response); } free(request); return tss_response; }
int activate_fetch_record(lockdownd_client_t client, plist_t* record) { int size = 0; char* request = NULL; struct curl_httppost* post = NULL; struct curl_httppost* last = NULL; activate_response* response = NULL; char* imei = NULL; char* imsi = NULL; char* iccid = NULL; char* serial_number = NULL; char* activation_info = NULL; plist_t imei_node = NULL; plist_t imsi_node = NULL; plist_t iccid_node = NULL; plist_t serial_number_node = NULL; plist_t activation_info_node = NULL; char* device_class = NULL; plist_t device_class_node = NULL; lockdownd_get_value(client, NULL, "DeviceClass", &device_class_node); if (!device_class_node || plist_get_node_type(device_class_node) != PLIST_STRING) { fprintf(stderr, "Unable to get DeviceClass from lockdownd\n"); return -1; } plist_get_string_val(device_class_node, &device_class); plist_free(device_class_node); if (!strcmp(device_class, "iPhone")) { lockdownd_get_value(client, NULL, "IntegratedCircuitCardIdentity", &iccid_node); if (!iccid_node || plist_get_node_type(iccid_node) != PLIST_STRING) { fprintf(stderr, "Unable to get ICCID from lockdownd\n"); return -1; } plist_get_string_val(iccid_node, &iccid); plist_free(iccid_node); lockdownd_get_value(client, NULL, "InternationalMobileEquipmentIdentity", &imei_node); if (!imei_node || plist_get_node_type(imei_node) != PLIST_STRING) { fprintf(stderr, "Unable to get IMEI from lockdownd\n"); return -1; } plist_get_string_val(imei_node, &imei); plist_free(imei_node); lockdownd_get_value(client, NULL, "InternationalMobileSubscriberIdentity", &imsi_node); if (!imsi_node || plist_get_node_type(imsi_node) != PLIST_STRING) { fprintf(stderr, "Unable to get IMSI from lockdownd\n"); return -1; } plist_get_string_val(imsi_node, &imsi); plist_free(imsi_node); } lockdownd_get_value(client, NULL, "SerialNumber", &serial_number_node); if (!serial_number_node || plist_get_node_type(serial_number_node) != PLIST_STRING) { fprintf(stderr, "Unable to get SerialNumber from lockdownd\n"); return -1; } plist_get_string_val(serial_number_node, &serial_number); plist_free(serial_number_node); lockdownd_get_value(client, NULL, "ActivationInfo", &activation_info_node); int type = plist_get_node_type(activation_info_node); if (!activation_info_node || plist_get_node_type(activation_info_node) != PLIST_DICT) { fprintf(stderr, "Unable to get ActivationInfo from lockdownd\n"); return -1; } //plist_get_string_val(activation_info_node, &activation_info); uint32_t activation_info_size = 0; char* activation_info_data = NULL; plist_to_xml(activation_info_node, &activation_info_data, &activation_info_size); plist_free(activation_info_node); printf("%s\n\n", activation_info_data); char* activation_info_start = strstr(activation_info_data, "<dict>"); if (activation_info_start == NULL) { fprintf(stderr, "Unable to locate beginning of ActivationInfo\n"); return -1; } char* activation_info_stop = strstr(activation_info_data, "</dict>"); if (activation_info_stop == NULL) { fprintf(stderr, "Unable to locate end of ActivationInfo\n"); return -1; } activation_info_stop += strlen("</dict>"); activation_info_size = activation_info_stop - activation_info_start; activation_info = malloc(activation_info_size + 1); memset(activation_info, '\0', activation_info_size + 1); memcpy(activation_info, activation_info_start, activation_info_size); free(activation_info_data); curl_global_init(CURL_GLOBAL_ALL); CURL* handle = curl_easy_init(); if (handle == NULL) { fprintf(stderr, "Unable to initialize libcurl\n"); curl_global_cleanup(); return -1; } curl_formadd(&post, &last, CURLFORM_COPYNAME, "machineName", CURLFORM_COPYCONTENTS, "linux", CURLFORM_END); curl_formadd(&post, &last, CURLFORM_COPYNAME, "InStoreActivation", CURLFORM_COPYCONTENTS, "false", CURLFORM_END); if (imei != NULL) { curl_formadd(&post, &last, CURLFORM_COPYNAME, "IMEI", CURLFORM_COPYCONTENTS, imei, CURLFORM_END); free(imei); } if (imsi != NULL) { curl_formadd(&post, &last, CURLFORM_COPYNAME, "IMSI", CURLFORM_COPYCONTENTS, imsi, CURLFORM_END); free(imsi); } if (iccid != NULL) { curl_formadd(&post, &last, CURLFORM_COPYNAME, "ICCID", CURLFORM_COPYCONTENTS, iccid, CURLFORM_END); free(iccid); } if (serial_number != NULL) { curl_formadd(&post, &last, CURLFORM_COPYNAME, "AppleSerialNumber", CURLFORM_COPYCONTENTS, serial_number, CURLFORM_END); free(serial_number); } if (activation_info != NULL) { curl_formadd(&post, &last, CURLFORM_COPYNAME, "activation-info", CURLFORM_COPYCONTENTS, activation_info, CURLFORM_END); free(activation_info); } struct curl_slist* header = NULL; header = curl_slist_append(header, "X-Apple-Tz: -14400"); header = curl_slist_append(header, "X-Apple-Store-Front: 143441-1"); response = malloc(sizeof(activate_response)); if (response == NULL) { fprintf(stderr, "Unable to allocate sufficent memory\n"); return -1; } response->length = 0; response->content = malloc(1); curl_easy_setopt(handle, CURLOPT_HTTPPOST, post); curl_easy_setopt(handle, CURLOPT_HTTPHEADER, header); curl_easy_setopt(handle, CURLOPT_WRITEDATA, response); curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, &activate_write_callback); curl_easy_setopt(handle, CURLOPT_USERAGENT, "iTunes/9.1 (Macintosh; U; Intel Mac OS X 10.5.6)"); curl_easy_setopt(handle, CURLOPT_URL, "https://albert.apple.com/WebObjects/ALUnbrick.woa/wa/deviceActivation"); curl_easy_perform(handle); curl_slist_free_all(header); curl_easy_cleanup(handle); curl_global_cleanup(); uint32_t ticket_size = response->length; char* ticket_data = response->content; char* ticket_start = strstr(ticket_data, "<plist"); if (ticket_start == NULL) { fprintf(stderr, "Unable to locate beginning of ActivationInfo\n"); return -1; } char* ticket_stop = strstr(ticket_data, "</plist>"); if (ticket_stop == NULL) { fprintf(stderr, "Unable to locate end of ActivationInfo\n"); return -1; } ticket_stop += strlen("</plist>"); ticket_size = ticket_stop - ticket_start; char* ticket = malloc(ticket_size + 1); memset(ticket, '\0', ticket_size + 1); memcpy(ticket, ticket_start, ticket_size); //free(ticket_data); printf("%s\n\n", ticket); plist_t ticket_dict = NULL; plist_from_xml(ticket, ticket_size, &ticket_dict); if (ticket_dict == NULL) { printf("Unable to convert activation ticket into plist\n"); return -1; } plist_t iphone_activation_node = plist_dict_get_item(ticket_dict, "iphone-activation"); if (!iphone_activation_node) { iphone_activation_node = plist_dict_get_item(ticket_dict, "device-activation"); if (!iphone_activation_node) { printf("Unable to find device activation node\n"); return -1; } } plist_t activation_record = plist_dict_get_item(iphone_activation_node, "activation-record"); if (!activation_record) { printf("Unable to find activation record node"); return -1; } *record = plist_copy(activation_record); //free(response->content); //free(response); //free(request); return 0; }