SWIGEXPORT jshort JNICALL Java_org_robovm_libimobiledevice_binding_libimobiledeviceJNI_lockdownd_1service_1descriptor_1free(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { jshort jresult = 0 ; lockdownd_service_descriptor_t arg1 = (lockdownd_service_descriptor_t) 0 ; lockdownd_error_t result; (void)jenv; (void)jcls; (void)jarg1_; arg1 = *(lockdownd_service_descriptor_t *)&jarg1; result = (lockdownd_error_t)lockdownd_service_descriptor_free(arg1); jresult = (jshort)result; return jresult; }
/* * Class: com_att_aro_libimobiledevice_Screencapture * Method: stopService * Signature: ()V */ JNIEXPORT void JNICALL Java_com_att_aro_libimobiledevice_ScreencaptureImpl_stopService (JNIEnv * env, jobject obj) { if(shotr) { screenshotr_client_free(shotr); } if (service) { lockdownd_service_descriptor_free(service); } if(device) { idevice_free(device); } }
/** * Starts a new service on the specified device with given name and * connects to it. * * @param device The device to connect to. * @param service_name The name of the service to start. * @param client Pointer that will point to a newly allocated service_client_t * upon successful return. Must be freed using service_client_free() after * use. * @param label The label to use for communication. Usually the program name. * Pass NULL to disable sending the label in requests to lockdownd. * * @return SERVICE_E_SUCCESS on success, or a SERVICE_E_* error code * otherwise. */ service_error_t service_client_factory_start_service(idevice_t device, const char* service_name, void **client, const char* label, int16_t (*constructor_func)(idevice_t, lockdownd_service_descriptor_t, void**), int16_t *error_code) { *client = NULL; lockdownd_client_t lckd = NULL; if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(device, &lckd, label)) { debug_info("Could not create a lockdown client."); return SERVICE_E_START_SERVICE_ERROR; } lockdownd_service_descriptor_t service = NULL; lockdownd_start_service(lckd, service_name, &service); lockdownd_client_free(lckd); if (!service || service->port == 0) { debug_info("Could not start service %s!", service_name); return SERVICE_E_START_SERVICE_ERROR; } int16_t ec; if (constructor_func) { ec = (int16_t)constructor_func(device, service, client); } else { ec = service_client_new(device, service, (service_client_t*)client); } if (error_code) { *error_code = ec; } if (ec != SERVICE_E_SUCCESS) { debug_info("Could not connect to service %s! Port: %i, error: %i", service_name, service->port, ec); } lockdownd_service_descriptor_free(service); service = NULL; return (ec == SERVICE_E_SUCCESS) ? SERVICE_E_SUCCESS : SERVICE_E_START_SERVICE_ERROR; }
static void perform_notification(idevice_t phone, lockdownd_client_t client, const char *notification) { lockdownd_service_descriptor_t service = NULL; np_client_t np; lockdownd_start_service(client, "com.apple.mobile.notification_proxy", &service); if (service && service->port) { printf("::::::::::::::: np was started ::::::::::::\n"); np_client_new(phone, service, &np); if (np) { printf("::::::::: PostNotification %s\n", notification); np_post_notification(np, notification); np_client_free(np); } } else { printf("::::::::::::::: np was NOT started ::::::::::::\n"); } if (service) { lockdownd_service_descriptor_free(service); service = NULL; } }
int main(int argc, char *argv[]) { lockdownd_client_t lockdown = NULL; idevice_t device = NULL; idevice_connection_t connection = NULL; idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; thread_t th; const char* udid = NULL; lockdownd_service_descriptor_t service = NULL; uint16_t local_port = 0; int result = EXIT_SUCCESS; int i; /* bind signals */ signal(SIGINT, clean_exit); signal(SIGTERM, clean_exit); #ifndef WIN32 signal(SIGQUIT, clean_exit); signal(SIGPIPE, SIG_IGN); #endif /* parse cmdline arguments */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { debug_mode = 1; idevice_set_debug_level(1); socket_set_verbose(3); 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], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return EXIT_SUCCESS; } else if (atoi(argv[i]) > 0) { local_port = atoi(argv[i]); continue; } else { print_usage(argc, argv); return EXIT_SUCCESS; } } /* a PORT is mandatory */ if (!local_port) { fprintf(stderr, "Please specify a PORT.\n"); print_usage(argc, argv); goto leave_cleanup; } /* start services and connect to device */ ret = idevice_new(&device, udid); if (ret != IDEVICE_E_SUCCESS) { if (udid) { fprintf(stderr, "No device found with udid %s, is it plugged in?\n", udid); } else { fprintf(stderr, "No device found, is it plugged in?\n"); } result = EXIT_FAILURE; goto leave_cleanup; } if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(device, &lockdown, "idevicedebugserverproxy")) { fprintf(stderr, "Could not connect to lockdownd. Exiting.\n"); result = EXIT_FAILURE; goto leave_cleanup; } if ((lockdownd_start_service(lockdown, "com.apple.debugserver", &service) != LOCKDOWN_E_SUCCESS) || !service || !service->port) { fprintf(stderr, "Could not start com.apple.debugserver!\nPlease make sure to mount the developer disk image first.\n"); result = EXIT_FAILURE; goto leave_cleanup; } if (idevice_connect(device, service->port, &connection) != IDEVICE_E_SUCCESS) { fprintf(stderr, "Connection to debugserver port %d failed!\n", (int)service->port); result = EXIT_FAILURE; goto leave_cleanup; } /* free lockdown connection if running as it is not needed anymore */ if (lockdown) { lockdownd_client_free(lockdown); lockdown = NULL; } /* setup and create socket endpoint */ socket_info_t socket_info; socket_info.device_connection = connection; socket_info.local_port = local_port; socket_info.remote_port = service->port; if (service) { lockdownd_service_descriptor_free(service); service = NULL; } /* create local socket */ socket_info.server_fd = socket_create(socket_info.local_port); if (socket_info.server_fd < 0) { fprintf(stderr, "Could not create socket\n"); result = EXIT_FAILURE; goto leave_cleanup; } while (!quit_flag) { debug("%s: Waiting for connection on local port %d\n", __func__, socket_info.local_port); /* wait for client */ socket_info.client_fd = socket_accept(socket_info.server_fd, socket_info.local_port); if (socket_info.client_fd < 0) { debug("%s: Continuing...\n", __func__); continue; } debug("%s: Handling new client connection...\n", __func__); if (thread_create(&th, connection_handler, (void*)&socket_info) != 0) { fprintf(stderr, "Could not start connection handler.\n"); socket_shutdown(socket_info.server_fd, SHUT_RDWR); socket_close(socket_info.server_fd); } } debug("%s: Shutting down debugserver proxy...\n", __func__); leave_cleanup: if (connection) { idevice_disconnect(connection); } if (lockdown) { lockdownd_client_free(lockdown); } if (device) { idevice_free(device); } return result; }
int main(int argc, char *argv[]) { lockdownd_client_t client = NULL; lockdownd_service_descriptor_t service = NULL; idevice_t device = NULL; idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; int i; int op = -1; 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], "-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; } 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 != lockdownd_client_new_with_handshake(device, &client, "ideviceprovision")) { 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: { FILE* f = fopen(param, "rb"); if (!f) { fprintf(stderr, "Could not open file '%s'\n", param); break; } fseek(f, 0, SEEK_END); long int size = ftell(f); fseek(f, 0, SEEK_SET); if (size >= 0x1000000) { fprintf(stderr, "The file '%s' is too large for processing.\n", param); fclose(f); break; } char* buf = (char *)malloc(size); if (!buf) { fprintf(stderr, "Could not allocate memory...\n"); fclose(f); break; } long int cur = 0; while (cur < size) { ssize_t r = fread(buf+cur, 1, 512, f); if (r <= 0) { break; } cur += r; } fclose(f); if (cur != size) { free(buf); fprintf(stderr, "Could not read in file '%s' (size %ld read %ld)\n", param, size, cur); break; } uint64_t psize = size; plist_t pdata = plist_new_data(buf, psize); 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); } free(buf); } 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, (size_t) 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; 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) { idevice_t device = NULL; lockdownd_client_t lckd = NULL; mobile_image_mounter_client_t mim = NULL; afc_client_t afc = NULL; lockdownd_service_descriptor_t service = NULL; int res = -1; char *image_path = NULL; char *image_sig_path = NULL; parse_opts(argc, argv); argc -= optind; argv += optind; if (!list_mode) { if (argc < 1) { printf("ERROR: No IMAGE_FILE has been given!\n"); return -1; } image_path = strdup(argv[0]); if (argc >= 2) { image_sig_path = strdup(argv[1]); } else { if (asprintf(&image_sig_path, "%s.signature", image_path) < 0) { printf("Out of memory?!\n"); return -1; } } } if (IDEVICE_E_SUCCESS != idevice_new(&device, udid)) { printf("No device found, is it plugged in?\n"); return -1; } if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(device, &lckd, "ideviceimagemounter")) { printf("ERROR: could not connect to lockdown. Exiting.\n"); goto leave; } lockdownd_start_service(lckd, "com.apple.mobile.mobile_image_mounter", &service); if (!service || service->port == 0) { printf("ERROR: Could not start mobile_image_mounter service!\n"); goto leave; } if (mobile_image_mounter_new(device, service, &mim) != MOBILE_IMAGE_MOUNTER_E_SUCCESS) { printf("ERROR: Could not connect to mobile_image_mounter!\n"); goto leave; } if (service) { lockdownd_service_descriptor_free(service); service = NULL; } if (!list_mode) { struct stat fst; if ((lockdownd_start_service(lckd, "com.apple.afc", &service) != LOCKDOWN_E_SUCCESS) || !service || !service->port) { fprintf(stderr, "Could not start com.apple.afc!\n"); goto leave; } if (afc_client_new(device, service, &afc) != AFC_E_SUCCESS) { fprintf(stderr, "Could not connect to AFC!\n"); goto leave; } if (service) { lockdownd_service_descriptor_free(service); service = NULL; } if (stat(image_path, &fst) != 0) { fprintf(stderr, "ERROR: stat: %s: %s\n", image_path, strerror(errno)); goto leave; } if (stat(image_sig_path, &fst) != 0) { fprintf(stderr, "ERROR: stat: %s: %s\n", image_sig_path, strerror(errno)); goto leave; } } lockdownd_client_free(lckd); lckd = NULL; mobile_image_mounter_error_t err; plist_t result = NULL; if (list_mode) { /* list mounts mode */ if (!imagetype) { imagetype = strdup("Developer"); } err = mobile_image_mounter_lookup_image(mim, imagetype, &result); free(imagetype); if (err == MOBILE_IMAGE_MOUNTER_E_SUCCESS) { res = 0; if (xml_mode) { print_xml(result); } else { plist_dict_to_string(result); } } else { printf("Error: lookup_image returned %d\n", err); } } else { char sig[8192]; size_t sig_length = 0; FILE *f = fopen(image_sig_path, "rb"); if (!f) { fprintf(stderr, "Error opening signature file '%s': %s\n", image_sig_path, strerror(errno)); goto leave; } sig_length = fread(sig, 1, sizeof(sig), f); fclose(f); if (sig_length == 0) { fprintf(stderr, "Could not read signature from file '%s'\n", image_sig_path); goto leave; } f = fopen(image_path, "rb"); if (!f) { fprintf(stderr, "Error opening image file '%s': %s\n", image_path, strerror(errno)); goto leave; } char *targetname = NULL; if (asprintf(&targetname, "%s/%s", PKG_PATH, "staging.dimage") < 0) { fprintf(stderr, "Out of memory!?\n"); goto leave; } char *mountname = NULL; if (asprintf(&mountname, "%s/%s", PATH_PREFIX, targetname) < 0) { fprintf(stderr, "Out of memory!?\n"); goto leave; } printf("Copying '%s' --> '%s'\n", image_path, targetname); char **strs = NULL; if (afc_get_file_info(afc, PKG_PATH, &strs) != AFC_E_SUCCESS) { if (afc_make_directory(afc, PKG_PATH) != AFC_E_SUCCESS) { fprintf(stderr, "WARNING: Could not create directory '%s' on device!\n", PKG_PATH); } } if (strs) { int i = 0; while (strs[i]) { free(strs[i]); i++; } free(strs); } uint64_t af = 0; if ((afc_file_open(afc, targetname, AFC_FOPEN_WRONLY, &af) != AFC_E_SUCCESS) || !af) { fclose(f); fprintf(stderr, "afc_file_open on '%s' failed!\n", targetname); goto leave; } char buf[8192]; size_t amount = 0; do { amount = fread(buf, 1, sizeof(buf), f); if (amount > 0) { uint32_t written, total = 0; while (total < amount) { written = 0; if (afc_file_write(afc, af, buf, amount, &written) != AFC_E_SUCCESS) { fprintf(stderr, "AFC Write error!\n"); break; } total += written; } if (total != amount) { fprintf(stderr, "Error: wrote only %d of %d\n", total, (unsigned int)amount); afc_file_close(afc, af); fclose(f); goto leave; } } } while (amount > 0); afc_file_close(afc, af); fclose(f); printf("done.\n"); printf("Mounting...\n"); if (!imagetype) { imagetype = strdup("Developer"); } err = mobile_image_mounter_mount_image(mim, mountname, sig, sig_length, imagetype, &result); free(imagetype); if (err == MOBILE_IMAGE_MOUNTER_E_SUCCESS) { if (result) { plist_t node = plist_dict_get_item(result, "Status"); if (node) { char *status = NULL; plist_get_string_val(node, &status); if (status) { if (!strcmp(status, "Complete")) { printf("Done.\n"); res = 0; } else { printf("unexpected status value:\n"); if (xml_mode) { print_xml(result); } else { plist_dict_to_string(result); } } free(status); } else { printf("unexpected result:\n"); if (xml_mode) { print_xml(result); } else { plist_dict_to_string(result); } } } node = plist_dict_get_item(result, "Error"); if (node) { char *error = NULL; plist_get_string_val(node, &error); if (error) { printf("Error: %s\n", error); free(error); } else { printf("unexpected result:\n"); if (xml_mode) { print_xml(result); } else { plist_dict_to_string(result); } } } else { if (xml_mode) { print_xml(result); } else { plist_dict_to_string(result); } } } } else { printf("Error: mount_image returned %d\n", err); } } if (result) { plist_free(result); } /* perform hangup command */ mobile_image_mounter_hangup(mim); /* free client */ mobile_image_mounter_free(mim); leave: if (afc) { afc_client_free(afc); } if (lckd) { lockdownd_client_free(lckd); } idevice_free(device); if (image_path) free(image_path); if (image_sig_path) free(image_sig_path); return res; }
int main(int argc, char **argv) { idevice_t device = NULL; lockdownd_client_t lckd = NULL; lockdownd_error_t ldret = LOCKDOWN_E_UNKNOWN_ERROR; screenshotr_client_t shotr = NULL; lockdownd_service_descriptor_t service = NULL; int result = -1; int i; const char *udid = NULL; char *filename = 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], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } else if (argv[i][0] != '-' && !filename) { filename = strdup(argv[i]); continue; } else { print_usage(argc, argv); return 0; } } if (IDEVICE_E_SUCCESS != idevice_new(&device, udid)) { 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, &lckd, NULL))) { idevice_free(device); printf("ERROR: Could not connect to lockdownd, error code %d\n", ldret); return -1; } lockdownd_start_service(lckd, "com.apple.mobile.screenshotr", &service); lockdownd_client_free(lckd); if (service && service->port > 0) { if (screenshotr_client_new(device, service, &shotr) != SCREENSHOTR_E_SUCCESS) { printf("Could not connect to screenshotr!\n"); } else { char *imgdata = NULL; uint64_t imgsize = 0; if (screenshotr_take_screenshot(shotr, &imgdata, &imgsize) == SCREENSHOTR_E_SUCCESS) { if (!filename) { const char *fileext = NULL; if (memcmp(imgdata, "\x89PNG", 4) == 0) { fileext = ".png"; } else if (memcmp(imgdata, "MM\x00*", 4) == 0) { fileext = ".tiff"; } else { printf("WARNING: screenshot data has unexpected image format.\n"); fileext = ".dat"; } time_t now = time(NULL); filename = (char*)malloc(36); size_t pos = strftime(filename, 36, "screenshot-%Y-%m-%d-%H-%M-%S", gmtime(&now)); sprintf(filename+pos, "%s", fileext); } FILE *f = fopen(filename, "wb"); if (f) { if (fwrite(imgdata, 1, (size_t)imgsize, f) == (size_t)imgsize) { printf("Screenshot saved to %s\n", filename); result = 0; } else { printf("Could not save screenshot to file %s!\n", filename); } fclose(f); } else { printf("Could not open %s for writing: %s\n", filename, strerror(errno)); } } else { printf("Could not get screenshot!\n"); } screenshotr_client_free(shotr); } } else { printf("Could not start screenshotr service! Remember that you have to mount the Developer disk image on your device if you want to use the screenshotr service.\n"); } if (service) lockdownd_service_descriptor_free(service); idevice_free(device); free(filename); return result; }
int main(int argc, const char **argv) { char *errmsg = ""; idevice_t device = NULL; lockdownd_client_t client = NULL; lockdownd_service_descriptor_t service = NULL; house_arrest_client_t hac = NULL; const char *service_name = "com.apple.afc"; const char *appid = NULL; char *device_name = NULL; int result = 0; char* udid = NULL; int cmd = CMD_INTERACTIVE; const char *cmdstr = NULL; int i; cwd = strdup("/"); /* parse cmdline args */ for (i = 1; i < argc; i++) { if (str_is_equal(argv[i], "-d") || str_is_equal(argv[i], "--debug")) { idevice_set_debug_level(1); continue; } else if (str_is_equal(argv[i], "-u") || str_is_equal(argv[i], "--udid")) { i++; if (!argv[i] || (strlen(argv[i]) != 40)) { print_usage(argc, argv); exit(EXIT_FAILURE); } udid = strdup(argv[i]); continue; } else if (str_is_equal(argv[i], "-2") || str_is_equal(argv[i], "--afc2")) { service_name = "com.apple.afc2"; continue; } else if (str_is_equal(argv[i], "-a") || str_is_equal(argv[i], "--appid")) { if (++i >= argc) { print_usage(argc, argv); exit(EXIT_FAILURE); } appid = argv[i]; } else if (str_is_equal(argv[i], "-h") || str_is_equal(argv[i], "--help")) { print_usage(argc, argv); exit(EXIT_SUCCESS); } else if ((cmd = str_to_cmd(argv[i])) != CMD_UNKNOWN) { cmdstr = argv[i]; i++; break; } } argc -= i; argv += i; /* Connect to device */ if (udid) { result = idevice_new(&device, udid); if (result != IDEVICE_E_SUCCESS) errx(EXIT_FAILURE, "No device found with udid %s, is it plugged in?", udid); } else { result = idevice_new(&device, NULL); if (result != IDEVICE_E_SUCCESS) errx(EXIT_FAILURE, "No device found, is it plugged in?"); idevice_get_udid(device, &udid); } /* Connect to lockdownd */ result = lockdownd_client_new_with_handshake(device, &client, "afccl"); if (result != LOCKDOWN_E_SUCCESS) { asprintf(&errmsg, "ERROR: Connecting to lockdownd service failed!"); goto bail; } result = lockdownd_get_device_name(client, &device_name); if ((result != LOCKDOWN_E_SUCCESS) || !device_name) { asprintf(&errmsg, "ERROR: Could not get device name!"); goto bail; } if (appid) { result = lockdownd_start_service(client, "com.apple.mobile.house_arrest", &service); if (result != LOCKDOWN_E_SUCCESS || !service || !service->port) { asprintf(&errmsg, "error starting house arrest service: (%d) %s", result, afc_strerror(result)); goto bail; } if (client) { lockdownd_client_free(client); client = NULL; } if (house_arrest_client_new(device, service, &hac) != HOUSE_ARREST_E_SUCCESS) { asprintf(&errmsg, "could not connect to house_arrest service!\n"); goto bail; } if (service) { lockdownd_service_descriptor_free(service); service = NULL; } result = house_arrest_send_command(hac, "VendDocuments", appid); if (result != HOUSE_ARREST_E_SUCCESS) { asprintf(&errmsg, "error %d when trying to get VendDocuments\n", result); goto bail; } plist_t dict = NULL; if (house_arrest_get_result(hac, &dict) != HOUSE_ARREST_E_SUCCESS) { if (house_arrest_get_result(hac, &dict) != HOUSE_ARREST_E_SUCCESS) { asprintf(&errmsg, "hmmm....\n"); goto bail; } } plist_t node = plist_dict_get_item(dict, "Error"); if (node) { char *str = NULL; plist_get_string_val(node, &str); asprintf(&errmsg, "Error: %s\n", str); if (str) free(str); plist_free(dict); dict = NULL; goto bail; } node = plist_dict_get_item(dict, "Status"); if (node) { char *str = NULL; plist_get_string_val(node, &str); if (str && (strcmp(str, "Complete") != 0)) { printf("Warning: Status is not 'Complete' but '%s'\n", str); } if (str) free(str); } if (dict) { plist_free(dict); } afc_error_t ae = afc_client_new_from_house_arrest_client(hac, &afc); if (ae != AFC_E_SUCCESS) { printf("afc error %d\n", ae); } } else { result = lockdownd_start_service(client, service_name, &service); if (result != LOCKDOWN_E_SUCCESS || !service || !service->port) { asprintf(&errmsg, "error starting AFC service: (%d) %s", result, afc_strerror(result)); goto bail; } /* Connect to AFC */ result = afc_client_new(device, service, &afc); lockdownd_client_free(client); idevice_free(device); if (result != AFC_E_SUCCESS) { errx(EXIT_FAILURE, "AFC connection failed (%d) %s", result, afc_strerror(result)); } } result = do_cmd(cmd, argc, argv); if (hac) house_arrest_client_free(hac); afc_client_free(afc); exit(result == 0 ? EXIT_SUCCESS : EXIT_FAILURE); bail: if (hac) house_arrest_client_free(hac); if (service) lockdownd_service_descriptor_free(service); if (client) lockdownd_client_free(client); if (device) idevice_free(device); errx(EXIT_FAILURE, "%s", errmsg); }
int main(int argc, char* argv[]) { idevice_t device = NULL; lockdownd_client_t lockdownd = NULL; afc_client_t afc = NULL; idevice_error_t device_error = IDEVICE_E_SUCCESS; lockdownd_error_t lockdownd_error = LOCKDOWN_E_SUCCESS; afc_error_t afc_error = AFC_E_SUCCESS; int i; const char* udid = 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], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } else if (!strcmp(argv[i], "-e") || !strcmp(argv[i], "--extract")) { extract_raw_crash_reports = 1; continue; } else if (!strcmp(argv[i], "-k") || !strcmp(argv[i], "--keep")) { keep_crash_reports = 1; continue; } else if (target_directory == NULL) { target_directory = argv[i]; continue; } else { print_usage(argc, argv); return 0; } } /* ensure a target directory was supplied */ if (!target_directory) { print_usage(argc, argv); return 0; } /* check if target directory exists */ if (!file_exists(target_directory)) { fprintf(stderr, "ERROR: Directory '%s' does not exist.\n", target_directory); print_usage(argc, argv); return 0; } device_error = idevice_new(&device, udid); if (device_error != 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; } lockdownd_error = lockdownd_client_new_with_handshake(device, &lockdownd, "idevicecrashreport"); if (lockdownd_error != LOCKDOWN_E_SUCCESS) { fprintf(stderr, "ERROR: Could not connect to lockdownd, error code %d\n", lockdownd_error); idevice_free(device); return -1; } /* start crash log mover service */ lockdownd_service_descriptor_t service = NULL; lockdownd_error = lockdownd_start_service(lockdownd, "com.apple.crashreportmover", &service); if (lockdownd_error != LOCKDOWN_E_SUCCESS) { lockdownd_client_free(lockdownd); idevice_free(device); return -1; } /* trigger move operation on device */ idevice_connection_t connection = NULL; device_error = idevice_connect(device, service->port, &connection); if(device_error != IDEVICE_E_SUCCESS) { lockdownd_client_free(lockdownd); idevice_free(device); return -1; } /* read "ping" message which indicates the crash logs have been moved to a safe harbor */ char *ping = malloc(4); int attempts = 0; while ((strncmp(ping, "ping", 4) != 0) && (attempts > 10)) { uint32_t bytes = 0; device_error = idevice_connection_receive_timeout(connection, ping, 4, &bytes, 2000); if ((bytes == 0) && (device_error == IDEVICE_E_SUCCESS)) { attempts++; continue; } else if (device_error < 0) { fprintf(stderr, "ERROR: Crash logs could not be moved. Connection interrupted.\n"); break; } } idevice_disconnect(connection); free(ping); if (service) { lockdownd_service_descriptor_free(service); service = NULL; } if (device_error != IDEVICE_E_SUCCESS || attempts > 10) { fprintf(stderr, "ERROR: Failed to receive ping message from crash report mover.\n"); lockdownd_client_free(lockdownd); idevice_free(device); return -1; } lockdownd_error = lockdownd_start_service(lockdownd, "com.apple.crashreportcopymobile", &service); if (lockdownd_error != LOCKDOWN_E_SUCCESS) { lockdownd_client_free(lockdownd); idevice_free(device); return -1; } lockdownd_client_free(lockdownd); afc = NULL; afc_error = afc_client_new(device, service, &afc); if(afc_error != AFC_E_SUCCESS) { lockdownd_client_free(lockdownd); idevice_free(device); return -1; } if (service) { lockdownd_service_descriptor_free(service); service = NULL; } /* recursively copy crash reports from the device to a local directory */ if (afc_client_copy_and_remove_crash_reports(afc, ".", target_directory) < 0) { fprintf(stderr, "ERROR: Failed to get crash reports from device.\n"); afc_client_free(afc); idevice_free(device); return -1; } printf("Done.\n"); afc_client_free(afc); idevice_free(device); return 0; }
int main(int argc, char **argv) { idevice_t device = NULL; lockdownd_client_t lckd = NULL; screenshotr_client_t shotr = NULL; lockdownd_service_descriptor_t service = NULL; int result = -1; int i; const char *udid = 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], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } else { print_usage(argc, argv); return 0; } } if (IDEVICE_E_SUCCESS != idevice_new(&device, udid)) { 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 != lockdownd_client_new_with_handshake(device, &lckd, NULL)) { idevice_free(device); printf("Exiting.\n"); return -1; } lockdownd_start_service(lckd, "com.apple.mobile.screenshotr", &service); lockdownd_client_free(lckd); if (service && service->port > 0) { if (screenshotr_client_new(device, service, &shotr) != SCREENSHOTR_E_SUCCESS) { printf("Could not connect to screenshotr!\n"); } else { char *imgdata = NULL; char filename[36]; uint64_t imgsize = 0; time_t now = time(NULL); strftime(filename, 36, "screenshot-%Y-%m-%d-%H-%M-%S.tiff", gmtime(&now)); if (screenshotr_take_screenshot(shotr, &imgdata, &imgsize) == SCREENSHOTR_E_SUCCESS) { FILE *f = fopen(filename, "wb"); if (f) { if (fwrite(imgdata, 1, (size_t)imgsize, f) == (size_t)imgsize) { printf("Screenshot saved to %s\n", filename); result = 0; } else { printf("Could not save screenshot to file %s!\n", filename); } fclose(f); } else { printf("Could not open %s for writing: %s\n", filename, strerror(errno)); } } else { printf("Could not get screenshot!\n"); } screenshotr_client_free(shotr); } } else { printf("Could not start screenshotr service! Remember that you have to mount the Developer disk image on your device if you want to use the screenshotr service.\n"); } if (service) lockdownd_service_descriptor_free(service); idevice_free(device); return result; }
static void* preflight_worker_handle_device_add(void* userdata) { struct device_info *info = (struct device_info*)userdata; struct idevice_private *_dev = (struct idevice_private*)malloc(sizeof(struct idevice_private)); _dev->udid = strdup(info->serial); _dev->conn_type = CONNECTION_USBMUXD; _dev->conn_data = (void*)(long)info->id; idevice_t dev = (idevice_t)_dev; lockdownd_client_t lockdown = NULL; lockdownd_error_t lerr; plist_t value = NULL; char* version_str = NULL; usbmuxd_log(LL_INFO, "%s: Starting preflight on device %s...", __func__, _dev->udid); retry: lerr = lockdownd_client_new(dev, &lockdown, "usbmuxd"); if (lerr != LOCKDOWN_E_SUCCESS) { usbmuxd_log(LL_ERROR, "%s: ERROR: Could not connect to lockdownd on device %s, lockdown error %d", __func__, _dev->udid, lerr); goto leave; } char *type = NULL; lerr = lockdownd_query_type(lockdown, &type); if (!type) { usbmuxd_log(LL_ERROR, "%s: ERROR: Could not get lockdownd type from device %s, lockdown error %d", __func__, _dev->udid, lerr); goto leave; } if (strcmp(type, "com.apple.mobile.lockdown") != 0) { // make restore mode devices visible free(type); usbmuxd_log(LL_INFO, "%s: Finished preflight on device %s", __func__, _dev->udid); client_device_add(info); goto leave; } free(type); int is_device_paired = 0; char *host_id = NULL; if (config_has_device_record(dev->udid)) { config_device_record_get_host_id(dev->udid, &host_id); lerr = lockdownd_start_session(lockdown, host_id, NULL, NULL); if (host_id) free(host_id); if (lerr == LOCKDOWN_E_SUCCESS) { usbmuxd_log(LL_INFO, "%s: StartSession success for device %s", __func__, _dev->udid); usbmuxd_log(LL_INFO, "%s: Finished preflight on device %s", __func__, _dev->udid); client_device_add(info); goto leave; } usbmuxd_log(LL_INFO, "%s: StartSession failed on device %s, lockdown error %d", __func__, _dev->udid, lerr); } else { lerr = LOCKDOWN_E_INVALID_HOST_ID; } switch (lerr) { case LOCKDOWN_E_INVALID_HOST_ID: usbmuxd_log(LL_INFO, "%s: Device %s is not paired with this host.", __func__, _dev->udid); break; case LOCKDOWN_E_SSL_ERROR: usbmuxd_log(LL_ERROR, "%s: The stored pair record for device %s is invalid. Removing.", __func__, _dev->udid); if (config_remove_device_record(_dev->udid) == 0) { lockdownd_client_free(lockdown); lockdown = NULL; goto retry; } else { usbmuxd_log(LL_ERROR, "%s: Could not remove pair record for device %s", __func__, _dev->udid); } break; default: is_device_paired = 1; break; } lerr = lockdownd_get_value(lockdown, NULL, "ProductVersion", &value); if (lerr != LOCKDOWN_E_SUCCESS) { usbmuxd_log(LL_ERROR, "%s: ERROR: Could not get ProductVersion from device %s, lockdown error %d", __func__, _dev->udid, lerr); goto leave; } if (value && plist_get_node_type(value) == PLIST_STRING) { plist_get_string_val(value, &version_str); } if (!version_str) { usbmuxd_log(LL_ERROR, "%s: Could not get ProductVersion string from device %s handle %d", __func__, _dev->udid, (int)(long)_dev->conn_data); goto leave; } int version_major = strtol(version_str, NULL, 10); if (version_major >= 7) { /* iOS 7.0 and later */ usbmuxd_log(LL_INFO, "%s: Found ProductVersion %s device %s", __func__, version_str, _dev->udid); lockdownd_set_untrusted_host_buid(lockdown); /* if not paired, trigger the trust dialog to make sure it appears */ if (!is_device_paired) { if (lockdownd_pair(lockdown, NULL) == LOCKDOWN_E_SUCCESS) { /* if device is still showing the setup screen it will pair even without trust dialog */ usbmuxd_log(LL_INFO, "%s: Pair success for device %s", __func__, _dev->udid); usbmuxd_log(LL_INFO, "%s: Finished preflight on device %s", __func__, _dev->udid); client_device_add(info); goto leave; } } lockdownd_service_descriptor_t service = NULL; lerr = lockdownd_start_service(lockdown, "com.apple.mobile.insecure_notification_proxy", &service); if (lerr != LOCKDOWN_E_SUCCESS) { usbmuxd_log(LL_ERROR, "%s: ERROR: Could not start insecure_notification_proxy on %s, lockdown error %d", __func__, _dev->udid, lerr); goto leave; } np_client_t np = NULL; np_client_new(dev, service, &np); lockdownd_service_descriptor_free(service); service = NULL; lockdownd_client_free(lockdown); lockdown = NULL; struct cb_data cbdata; cbdata.dev = dev; cbdata.np = np; cbdata.is_device_connected = 1; np_set_notify_callback(np, np_callback, (void*)&cbdata); device_set_preflight_cb_data(info->id, (void*)&cbdata); const char* spec[] = { "com.apple.mobile.lockdown.request_pair", "com.apple.mobile.lockdown.request_host_buid", NULL }; np_observe_notifications(np, spec); /* TODO send notification to user's desktop */ usbmuxd_log(LL_INFO, "%s: Waiting for user to trust this computer on device %s", __func__, _dev->udid); /* make device visible anyways */ client_device_add(info); while (cbdata.np && cbdata.is_device_connected == 1) { sleep(1); } device_set_preflight_cb_data(info->id, NULL); usbmuxd_log(LL_INFO, "%s: Finished waiting for notification from device %s, is_device_connected %d", __func__, _dev->udid, cbdata.is_device_connected); if (cbdata.np) { np_client_free(cbdata.np); } } else { /* iOS 6.x and earlier */ lerr = lockdownd_pair(lockdown, NULL); if (lerr != LOCKDOWN_E_SUCCESS) { if (lerr == LOCKDOWN_E_PASSWORD_PROTECTED) { usbmuxd_log(LL_INFO, "%s: Device %s is locked with a passcode. Cannot pair.", __func__, _dev->udid); /* TODO send notification to user's desktop */ } else { usbmuxd_log(LL_ERROR, "%s: ERROR: Pair failed for device %s, lockdown error %d", __func__, _dev->udid, lerr); } usbmuxd_log(LL_INFO, "%s: Finished preflight on device %s", __func__, _dev->udid); /* make device visible anyways */ client_device_add(info); goto leave; } host_id = NULL; config_device_record_get_host_id(dev->udid, &host_id); lerr = lockdownd_start_session(lockdown, host_id, NULL, NULL); free(host_id); if (lerr != LOCKDOWN_E_SUCCESS) { usbmuxd_log(LL_ERROR, "%s: ERROR StartSession failed on device %s, lockdown error %d", __func__, _dev->udid, lerr); goto leave; } lerr = lockdownd_validate_pair(lockdown, NULL); if (lerr != LOCKDOWN_E_SUCCESS) { usbmuxd_log(LL_ERROR, "%s: ERROR: ValidatePair failed for device %s, lockdown error %d", __func__, _dev->udid, lerr); goto leave; } usbmuxd_log(LL_INFO, "%s: Finished preflight on device %s", __func__, _dev->udid); /* emit device added event and thus make device visible to clients */ client_device_add(info); } leave: if (value) plist_free(value); if (version_str) free(version_str); if (lockdown) lockdownd_client_free(lockdown); if (dev) idevice_free(dev); free(info); return NULL; }
int main(int argc, char **argv) { idevice_t device = NULL; lockdownd_client_t lockdown_client = NULL; diagnostics_relay_client_t diagnostics_client = NULL; lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; lockdownd_service_descriptor_t service = NULL; int result = -1; int i; const char *udid = NULL; int cmd = CMD_NONE; char* cmd_arg = NULL; plist_t node = NULL; plist_t keys = 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); result = 0; goto cleanup; } udid = argv[i]; continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); result = 0; goto cleanup; } else if (!strcmp(argv[i], "sleep")) { cmd = CMD_SLEEP; } else if (!strcmp(argv[i], "restart")) { cmd = CMD_RESTART; } else if (!strcmp(argv[i], "shutdown")) { cmd = CMD_SHUTDOWN; } else if (!strcmp(argv[i], "diagnostics")) { cmd = CMD_DIAGNOSTICS; /* read type */ i++; if (!argv[i] || ((strcmp(argv[i], "All") != 0) && (strcmp(argv[i], "WiFi") != 0) && (strcmp(argv[i], "GasGauge") != 0) && (strcmp(argv[i], "NAND") != 0))) { if (argv[i] == NULL) { cmd_arg = strdup("All"); continue; } if (!strncmp(argv[i], "-", 1)) { cmd_arg = strdup("All"); i--; continue; } printf("Unknown TYPE %s\n", argv[i]); print_usage(argc, argv); goto cleanup; } cmd_arg = strdup(argv[i]); continue; } else if (!strcmp(argv[i], "mobilegestalt")) { cmd = CMD_MOBILEGESTALT; /* read keys */ i++; if (!argv[i] || argv[i] == NULL || (!strncmp(argv[i], "-", 1))) { printf("Please supply the key to query.\n"); print_usage(argc, argv); goto cleanup; } keys = plist_new_array(); while(1) { if (argv[i] && (strlen(argv[i]) >= 2) && (strncmp(argv[i], "-", 1) != 0)) { plist_array_append_item(keys, plist_new_string(argv[i])); i++; } else { i--; break; } } continue; } else if (!strcmp(argv[i], "ioreg")) { cmd = CMD_IOREGISTRY; /* read plane */ i++; if (argv[i]) { cmd_arg = strdup(argv[i]); } continue; } else { print_usage(argc, argv); return 0; } } /* verify options */ if (cmd == CMD_NONE) { print_usage(argc, argv); goto cleanup; } if (IDEVICE_E_SUCCESS != idevice_new(&device, udid)) { 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"); } goto cleanup; } if (LOCKDOWN_E_SUCCESS != (ret = lockdownd_client_new_with_handshake(device, &lockdown_client, "idevicediagnostics"))) { idevice_free(device); printf("ERROR: Could not connect to lockdownd, error code %d\n", ret); goto cleanup; } /* attempt to use newer diagnostics service available on iOS 5 and later */ ret = lockdownd_start_service(lockdown_client, "com.apple.mobile.diagnostics_relay", &service); if (ret != LOCKDOWN_E_SUCCESS) { /* attempt to use older diagnostics service */ ret = lockdownd_start_service(lockdown_client, "com.apple.iosdiagnostics.relay", &service); } lockdownd_client_free(lockdown_client); if ((ret == LOCKDOWN_E_SUCCESS) && service && (service->port > 0)) { if (diagnostics_relay_client_new(device, service, &diagnostics_client) != DIAGNOSTICS_RELAY_E_SUCCESS) { printf("Could not connect to diagnostics_relay!\n"); result = -1; } else { switch (cmd) { case CMD_SLEEP: if (diagnostics_relay_sleep(diagnostics_client) == DIAGNOSTICS_RELAY_E_SUCCESS) { printf("Putting device into deep sleep mode.\n"); result = EXIT_SUCCESS; } else { printf("Failed to put device into deep sleep mode.\n"); } break; case CMD_RESTART: if (diagnostics_relay_restart(diagnostics_client, DIAGNOSTICS_RELAY_ACTION_FLAG_WAIT_FOR_DISCONNECT) == DIAGNOSTICS_RELAY_E_SUCCESS) { printf("Restarting device.\n"); result = EXIT_SUCCESS; } else { printf("Failed to restart device.\n"); } break; case CMD_SHUTDOWN: if (diagnostics_relay_shutdown(diagnostics_client, DIAGNOSTICS_RELAY_ACTION_FLAG_WAIT_FOR_DISCONNECT) == DIAGNOSTICS_RELAY_E_SUCCESS) { printf("Shutting down device.\n"); result = EXIT_SUCCESS; } else { printf("Failed to shutdown device.\n"); } break; case CMD_MOBILEGESTALT: if (diagnostics_relay_query_mobilegestalt(diagnostics_client, keys, &node) == DIAGNOSTICS_RELAY_E_SUCCESS) { if (node) { print_xml(node); result = EXIT_SUCCESS; } } else { printf("Unable to query mobilegestalt keys.\n"); } break; case CMD_IOREGISTRY: if (diagnostics_relay_query_ioregistry_plane(diagnostics_client, cmd_arg == NULL ? "": cmd_arg, &node) == DIAGNOSTICS_RELAY_E_SUCCESS) { if (node) { print_xml(node); result = EXIT_SUCCESS; } } else { printf("Unable to retrieve IORegistry from device.\n"); } break; case CMD_DIAGNOSTICS: default: if (diagnostics_relay_request_diagnostics(diagnostics_client, cmd_arg, &node) == DIAGNOSTICS_RELAY_E_SUCCESS) { if (node) { print_xml(node); result = EXIT_SUCCESS; } } else { printf("Unable to retrieve diagnostics from device.\n"); } break; } diagnostics_relay_goodbye(diagnostics_client); diagnostics_relay_client_free(diagnostics_client); } } else { printf("Could not start diagnostics service!\n"); } if (service) { lockdownd_service_descriptor_free(service); service = NULL; } idevice_free(device); cleanup: if (node) { plist_free(node); } if (keys) { plist_free(keys); } if (cmd_arg) { free(cmd_arg); } return result; }
int main(int argc, char *argv[]) { unsigned int bytes = 0; uint16_t i = 0; lockdownd_service_descriptor_t service = NULL; lockdownd_client_t client = NULL; idevice_t phone = NULL; uint64_t lockfile = 0; np_client_t gnp = NULL; if (argc > 1 && !strcasecmp(argv[1], "--debug")) { idevice_set_debug_level(1); } else { idevice_set_debug_level(0); } 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, "ideviceclient")) { idevice_free(phone); printf("Exiting.\n"); return -1; } char *nnn = NULL; if (LOCKDOWN_E_SUCCESS == lockdownd_get_device_name(client, &nnn)) { printf("DeviceName : %s\n", nnn); free(nnn); } lockdownd_start_service(client, "com.apple.afc", &service); if (service && service->port) { afc_client_t afc = NULL; afc_client_new(phone, service, &afc); if (afc) { service->port = 0; service->ssl_enabled = 0; lockdownd_start_service(client, "com.apple.mobile.notification_proxy", &service); if (service->port) { printf("Notification Proxy started.\n"); np_client_new(phone, service, &gnp); } else { printf("ERROR: Notification proxy could not be started.\n"); } if (gnp) { const char *nspec[5] = { NP_SYNC_CANCEL_REQUEST, NP_SYNC_SUSPEND_REQUEST, NP_SYNC_RESUME_REQUEST, NP_ITDBPREP_DID_END, NULL }; np_observe_notifications(gnp, nspec); np_set_notify_callback(gnp, notifier, NULL); } perform_notification(phone, client, NP_SYNC_WILL_START); afc_file_open(afc, "/com.apple.itunes.lock_sync", AFC_FOPEN_RW, &lockfile); if (lockfile) { printf("locking file\n"); afc_file_lock(afc, lockfile, AFC_LOCK_EX); perform_notification(phone, client, NP_SYNC_DID_START); } char **dirs = NULL; afc_read_directory(afc, "/eafaedf", &dirs); if (!dirs) afc_read_directory(afc, "/", &dirs); printf("Directory time.\n"); for (i = 0; dirs[i]; i++) { printf("/%s\n", dirs[i]); free(dirs[i]); } if (dirs) free(dirs); dirs = NULL; afc_get_device_info(afc, &dirs); if (dirs) { for (i = 0; dirs[i]; i += 2) { printf("%s: %s\n", dirs[i], dirs[i + 1]); free(dirs[i]); } free(dirs); } uint64_t my_file = 0; char **info = NULL; uint64_t fsize = 0; if (AFC_E_SUCCESS == afc_get_file_info(afc, "/readme.libimobiledevice.fx", &info) && info) { for (i = 0; info[i]; i += 2) { printf("%s: %s\n", info[i], info[i+1]); if (!strcmp(info[i], "st_size")) { fsize = atoll(info[i+1]); } } } if (AFC_E_SUCCESS == afc_file_open(afc, "/readme.libimobiledevice.fx", AFC_FOPEN_RDONLY, &my_file) && my_file) { printf("A file size: %llu\n", (long long)fsize); char *file_data = (char *) malloc(sizeof(char) * fsize); afc_file_read(afc, my_file, file_data, fsize, &bytes); if (bytes > 0) { printf("The file's data:\n"); fwrite(file_data, 1, bytes, stdout); } printf("\nClosing my file.\n"); afc_file_close(afc, my_file); free(file_data); } else printf("couldn't open a file\n"); afc_file_open(afc, "/readme.libimobiledevice.fx", AFC_FOPEN_WR, &my_file); if (my_file) { char *outdatafile = strdup("this is a bitchin text file\n"); afc_file_write(afc, my_file, outdatafile, strlen(outdatafile), &bytes); free(outdatafile); if (bytes > 0) printf("Wrote a surprise. ;)\n"); else printf("I wanted to write a surprise, but... :(\n"); afc_file_close(afc, my_file); } printf("Deleting a file...\n"); bytes = afc_remove_path(afc, "/delme"); if (bytes) printf("Success.\n"); else printf("Failure. (expected unless you have a /delme file on your phone)\n"); printf("Renaming a file...\n"); bytes = afc_rename_path(afc, "/renme", "/renme2"); if (bytes > 0) printf("Success.\n"); else printf("Failure. (expected unless you have a /renme file on your phone)\n"); printf("Seek & read\n"); afc_file_open(afc, "/readme.libimobiledevice.fx", AFC_FOPEN_RDONLY, &my_file); if (AFC_E_SUCCESS != afc_file_seek(afc, my_file, 5, SEEK_CUR)) printf("WARN: SEEK DID NOT WORK\n"); char *threeletterword = (char *) malloc(sizeof(char) * 5); afc_file_read(afc, my_file, threeletterword, 3, &bytes); threeletterword[3] = '\0'; if (bytes > 0) printf("Result: %s\n", threeletterword); else printf("Couldn't read!\n"); free(threeletterword); afc_file_close(afc, my_file); } if (gnp && lockfile) { printf("XXX sleeping\n"); sleep(5); printf("XXX unlocking file\n"); afc_file_lock(afc, lockfile, AFC_LOCK_UN); printf("XXX closing file\n"); afc_file_close(afc, lockfile); printf("XXX sleeping\n"); sleep(5); //perform_notification(phone, client, NP_SYNC_DID_FINISH); } if (gnp) { np_client_free(gnp); gnp = NULL; } afc_client_free(afc); lockdownd_service_descriptor_free(service); service = NULL; } else { printf("Start service failure.\n"); } printf("All done.\n"); lockdownd_client_free(client); idevice_free(phone); return 0; }
int main(int argc, char **argv) { idevice_t phone = NULL; lockdownd_client_t client = NULL; instproxy_client_t ipc = NULL; instproxy_error_t err; np_client_t np = NULL; afc_client_t afc = NULL; #ifdef HAVE_LIBIMOBILEDEVICE_1_1_5 lockdownd_service_descriptor_t service = NULL; #else uint16_t service = 0; #endif int res = 0; char *bundleidentifier = NULL; parse_opts(argc, argv); argc -= optind; argv += optind; if (IDEVICE_E_SUCCESS != idevice_new(&phone, udid)) { fprintf(stderr, "No iOS device found, is it plugged in?\n"); return -1; } if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(phone, &client, "ideviceinstaller")) { fprintf(stderr, "Could not connect to lockdownd. Exiting.\n"); goto leave_cleanup; } if ((lockdownd_start_service (client, "com.apple.mobile.notification_proxy", &service) != LOCKDOWN_E_SUCCESS) || !service) { fprintf(stderr, "Could not start com.apple.mobile.notification_proxy!\n"); goto leave_cleanup; } np_error_t nperr = np_client_new(phone, service, &np); #ifdef HAVE_LIBIMOBILEDEVICE_1_1_5 if (service) { lockdownd_service_descriptor_free(service); } service = NULL; #else service = 0; #endif if (nperr != NP_E_SUCCESS) { fprintf(stderr, "Could not connect to notification_proxy!\n"); goto leave_cleanup; } #ifdef HAVE_LIBIMOBILEDEVICE_1_1 np_set_notify_callback(np, notifier, NULL); #else np_set_notify_callback(np, notifier); #endif const char *noties[3] = { NP_APP_INSTALLED, NP_APP_UNINSTALLED, NULL }; np_observe_notifications(np, noties); run_again: #ifdef HAVE_LIBIMOBILEDEVICE_1_1_5 if (service) { lockdownd_service_descriptor_free(service); } service = NULL; #else service = 0; #endif if ((lockdownd_start_service(client, "com.apple.mobile.installation_proxy", &service) != LOCKDOWN_E_SUCCESS) || !service) { fprintf(stderr, "Could not start com.apple.mobile.installation_proxy!\n"); goto leave_cleanup; } err = instproxy_client_new(phone, service, &ipc); #ifdef HAVE_LIBIMOBILEDEVICE_1_1_5 if (service) { lockdownd_service_descriptor_free(service); } service = NULL; #else service = 0; #endif if (err != INSTPROXY_E_SUCCESS) { fprintf(stderr, "Could not connect to installation_proxy!\n"); goto leave_cleanup; } setbuf(stdout, NULL); if (last_status) { free(last_status); last_status = NULL; } notification_expected = 0; if (cmd == CMD_LIST_APPS) { int xml_mode = 0; plist_t client_opts = instproxy_client_options_new(); instproxy_client_options_add(client_opts, "ApplicationType", "User", NULL); plist_t apps = NULL; /* look for options */ if (options) { char *opts = strdup(options); char *elem = strtok(opts, ","); while (elem) { if (!strcmp(elem, "list_system")) { if (!client_opts) { client_opts = instproxy_client_options_new(); } instproxy_client_options_add(client_opts, "ApplicationType", "System", NULL); } else if (!strcmp(elem, "list_all")) { instproxy_client_options_free(client_opts); client_opts = NULL; } else if (!strcmp(elem, "list_user")) { /* do nothing, we're already set */ } else if (!strcmp(elem, "xml")) { xml_mode = 1; } elem = strtok(NULL, ","); } free(opts); } err = instproxy_browse(ipc, client_opts, &apps); instproxy_client_options_free(client_opts); if (err != INSTPROXY_E_SUCCESS) { fprintf(stderr, "ERROR: instproxy_browse returned %d\n", err); goto leave_cleanup; } if (!apps || (plist_get_node_type(apps) != PLIST_ARRAY)) { fprintf(stderr, "ERROR: instproxy_browse returnd an invalid plist!\n"); goto leave_cleanup; } if (xml_mode) { char *xml = NULL; uint32_t len = 0; plist_to_xml(apps, &xml, &len); if (xml) { puts(xml); free(xml); } plist_free(apps); goto leave_cleanup; } printf("Total: %d apps\n", plist_array_get_size(apps)); uint32_t i = 0; for (i = 0; i < plist_array_get_size(apps); i++) { plist_t app = plist_array_get_item(apps, i); plist_t p_appid = plist_dict_get_item(app, "CFBundleIdentifier"); char *s_appid = NULL; char *s_dispName = NULL; char *s_version = NULL; plist_t dispName = plist_dict_get_item(app, "CFBundleDisplayName"); plist_t version = plist_dict_get_item(app, "CFBundleVersion"); if (p_appid) { plist_get_string_val(p_appid, &s_appid); } if (!s_appid) { fprintf(stderr, "ERROR: Failed to get APPID!\n"); break; } if (dispName) { plist_get_string_val(dispName, &s_dispName); } if (version) { plist_get_string_val(version, &s_version); } if (!s_dispName) { s_dispName = strdup(s_appid); } if (s_version) { printf("%s - %s %s\n", s_appid, s_dispName, s_version); free(s_version); } else { printf("%s - %s\n", s_appid, s_dispName); } free(s_dispName); free(s_appid); } plist_free(apps); } else if (cmd == CMD_INSTALL || cmd == CMD_UPGRADE) { plist_t sinf = NULL; plist_t meta = NULL; char *pkgname = NULL; struct stat fst; uint64_t af = 0; char buf[8192]; #ifdef HAVE_LIBIMOBILEDEVICE_1_1_5 if (service) { lockdownd_service_descriptor_free(service); } service = NULL; #else service = 0; #endif if ((lockdownd_start_service(client, "com.apple.afc", &service) != LOCKDOWN_E_SUCCESS) || !service) { fprintf(stderr, "Could not start com.apple.afc!\n"); goto leave_cleanup; } lockdownd_client_free(client); client = NULL; if (afc_client_new(phone, service, &afc) != INSTPROXY_E_SUCCESS) { fprintf(stderr, "Could not connect to AFC!\n"); goto leave_cleanup; } if (stat(appid, &fst) != 0) { fprintf(stderr, "ERROR: stat: %s: %s\n", appid, strerror(errno)); goto leave_cleanup; } char **strs = NULL; if (afc_get_file_info(afc, PKG_PATH, &strs) != AFC_E_SUCCESS) { if (afc_make_directory(afc, PKG_PATH) != AFC_E_SUCCESS) { fprintf(stderr, "WARNING: Could not create directory '%s' on device!\n", PKG_PATH); } } if (strs) { int i = 0; while (strs[i]) { free(strs[i]); i++; } free(strs); } plist_t client_opts = instproxy_client_options_new(); /* open install package */ int errp = 0; struct zip *zf = NULL; if ((strlen(appid) > 5) && (strcmp(&appid[strlen(appid)-5], ".ipcc") == 0)) { zf = zip_open(appid, 0, &errp); if (!zf) { fprintf(stderr, "ERROR: zip_open: %s: %d\n", appid, errp); goto leave_cleanup; } char* ipcc = strdup(appid); if ((asprintf(&pkgname, "%s/%s", PKG_PATH, basename(ipcc)) > 0) && pkgname) { afc_make_directory(afc, pkgname); } printf("Uploading %s package contents... ", basename(ipcc)); /* extract the contents of the .ipcc file to PublicStaging/<name>.ipcc directory */ zip_uint64_t numzf = zip_get_num_entries(zf, 0); zip_uint64_t i = 0; for (i = 0; numzf > 0 && i < numzf; i++) { const char* zname = zip_get_name(zf, i, 0); char* dstpath = NULL; if (!zname) continue; if (zname[strlen(zname)-1] == '/') { // directory if ((asprintf(&dstpath, "%s/%s/%s", PKG_PATH, basename(ipcc), zname) > 0) && dstpath) { afc_make_directory(afc, dstpath); } free(dstpath); dstpath = NULL; } else { // file struct zip_file* zfile = zip_fopen_index(zf, i, 0); if (!zfile) continue; if ((asprintf(&dstpath, "%s/%s/%s", PKG_PATH, basename(ipcc), zname) <= 0) || !dstpath || (afc_file_open(afc, dstpath, AFC_FOPEN_WRONLY, &af) != AFC_E_SUCCESS)) { fprintf(stderr, "ERROR: can't open afc://%s for writing\n", dstpath); free(dstpath); dstpath = NULL; zip_fclose(zfile); continue; } struct zip_stat zs; zip_stat_init(&zs); if (zip_stat_index(zf, i, 0, &zs) != 0) { fprintf(stderr, "ERROR: zip_stat_index %" PRIu64 " failed!\n", i); free(dstpath); dstpath = NULL; zip_fclose(zfile); continue; } free(dstpath); dstpath = NULL; zip_uint64_t zfsize = 0; while (zfsize < zs.size) { zip_int64_t amount = zip_fread(zfile, buf, sizeof(buf)); if (amount == 0) { break; } if (amount > 0) { uint32_t written, total = 0; while (total < amount) { written = 0; if (afc_file_write(afc, af, buf, amount, &written) != AFC_E_SUCCESS) { fprintf(stderr, "AFC Write error!\n"); break; } total += written; } if (total != amount) { fprintf(stderr, "Error: wrote only %d of %" PRIi64 "\n", total, amount); afc_file_close(afc, af); zip_fclose(zfile); free(dstpath); goto leave_cleanup; } } zfsize += amount; } afc_file_close(afc, af); af = 0; zip_fclose(zfile); } } free(ipcc); printf("DONE.\n"); instproxy_client_options_add(client_opts, "PackageType", "CarrierBundle", NULL); } else if (S_ISDIR(fst.st_mode)) { /* upload developer app directory */ instproxy_client_options_add(client_opts, "PackageType", "Developer", NULL); if (asprintf(&pkgname, "%s/%s", PKG_PATH, basename(appid)) < 0) { fprintf(stderr, "ERROR: Out of memory allocating pkgname!?\n"); goto leave_cleanup; } printf("Uploading %s package contents... ", basename(appid)); afc_upload_dir(afc, appid, pkgname); printf("DONE.\n"); } else { zf = zip_open(appid, 0, &errp); if (!zf) { fprintf(stderr, "ERROR: zip_open: %s: %d\n", appid, errp); goto leave_cleanup; } /* extract iTunesMetadata.plist from package */ char *zbuf = NULL; uint32_t len = 0; plist_t meta_dict = NULL; if (zip_get_contents(zf, ITUNES_METADATA_PLIST_FILENAME, 0, &zbuf, &len) == 0) { meta = plist_new_data(zbuf, len); if (memcmp(zbuf, "bplist00", 8) == 0) { plist_from_bin(zbuf, len, &meta_dict); } else { plist_from_xml(zbuf, len, &meta_dict); } } else { fprintf(stderr, "WARNING: could not locate %s in archive!\n", ITUNES_METADATA_PLIST_FILENAME); } if (zbuf) { free(zbuf); } /* determine .app directory in archive */ zbuf = NULL; len = 0; plist_t info = NULL; char* filename = NULL; char* app_directory_name = NULL; if (zip_get_app_directory(zf, &app_directory_name)) { fprintf(stderr, "Unable to locate app directory in archive!\n"); goto leave_cleanup; } /* construct full filename to Info.plist */ filename = (char*)malloc(strlen(app_directory_name)+10+1); strcpy(filename, app_directory_name); free(app_directory_name); app_directory_name = NULL; strcat(filename, "Info.plist"); if (zip_get_contents(zf, filename, 0, &zbuf, &len) < 0) { fprintf(stderr, "WARNING: could not locate %s in archive!\n", filename); free(filename); zip_unchange_all(zf); zip_close(zf); goto leave_cleanup; } free(filename); if (memcmp(zbuf, "bplist00", 8) == 0) { plist_from_bin(zbuf, len, &info); } else { plist_from_xml(zbuf, len, &info); } free(zbuf); if (!info) { fprintf(stderr, "Could not parse Info.plist!\n"); zip_unchange_all(zf); zip_close(zf); goto leave_cleanup; } char *bundleexecutable = NULL; plist_t bname = plist_dict_get_item(info, "CFBundleExecutable"); if (bname) { plist_get_string_val(bname, &bundleexecutable); } bname = plist_dict_get_item(info, "CFBundleIdentifier"); if (bname) { plist_get_string_val(bname, &bundleidentifier); } plist_free(info); info = NULL; if (!bundleexecutable) { fprintf(stderr, "Could not determine value for CFBundleExecutable!\n"); zip_unchange_all(zf); zip_close(zf); goto leave_cleanup; } char *sinfname = NULL; if (asprintf(&sinfname, "Payload/%s.app/SC_Info/%s.sinf", bundleexecutable, bundleexecutable) < 0) { fprintf(stderr, "Out of memory!?\n"); goto leave_cleanup; } free(bundleexecutable); /* extract .sinf from package */ zbuf = NULL; len = 0; if (zip_get_contents(zf, sinfname, 0, &zbuf, &len) == 0) { sinf = plist_new_data(zbuf, len); } else { fprintf(stderr, "WARNING: could not locate %s in archive!\n", sinfname); } free(sinfname); if (zbuf) { free(zbuf); } /* copy archive to device */ pkgname = NULL; if (asprintf(&pkgname, "%s/%s", PKG_PATH, bundleidentifier) < 0) { fprintf(stderr, "Out of memory!?\n"); goto leave_cleanup; } printf("Copying '%s' to device... ", appid); if (afc_upload_file(afc, appid, pkgname) < 0) { free(pkgname); goto leave_cleanup; } printf("DONE.\n"); if (bundleidentifier) { instproxy_client_options_add(client_opts, "CFBundleIdentifier", bundleidentifier, NULL); } if (sinf) { instproxy_client_options_add(client_opts, "ApplicationSINF", sinf, NULL); } if (meta) { instproxy_client_options_add(client_opts, "iTunesMetadata", meta, NULL); } } if (zf) { zip_unchange_all(zf); zip_close(zf); } /* perform installation or upgrade */ if (cmd == CMD_INSTALL) { printf("Installing '%s'\n", bundleidentifier); #ifdef HAVE_LIBIMOBILEDEVICE_1_1 instproxy_install(ipc, pkgname, client_opts, status_cb, NULL); #else instproxy_install(ipc, pkgname, client_opts, status_cb); #endif } else { printf("Upgrading '%s'\n", bundleidentifier); #ifdef HAVE_LIBIMOBILEDEVICE_1_1 instproxy_upgrade(ipc, pkgname, client_opts, status_cb, NULL); #else instproxy_upgrade(ipc, pkgname, client_opts, status_cb); #endif } instproxy_client_options_free(client_opts); free(pkgname); wait_for_op_complete = 1; notification_expected = 1; } else if (cmd == CMD_UNINSTALL) { printf("Uninstalling '%s'\n", appid); #ifdef HAVE_LIBIMOBILEDEVICE_1_1 instproxy_uninstall(ipc, appid, NULL, status_cb, NULL); #else instproxy_uninstall(ipc, appid, NULL, status_cb); #endif wait_for_op_complete = 1; notification_expected = 0; } else if (cmd == CMD_LIST_ARCHIVES) { int xml_mode = 0; plist_t dict = NULL; plist_t lres = NULL; /* look for options */ if (options) { char *opts = strdup(options); char *elem = strtok(opts, ","); while (elem) { if (!strcmp(elem, "xml")) { xml_mode = 1; } elem = strtok(NULL, ","); } } err = instproxy_lookup_archives(ipc, NULL, &dict); if (err != INSTPROXY_E_SUCCESS) { fprintf(stderr, "ERROR: lookup_archives returned %d\n", err); goto leave_cleanup; } if (!dict) { fprintf(stderr, "ERROR: lookup_archives did not return a plist!?\n"); goto leave_cleanup; } lres = plist_dict_get_item(dict, "LookupResult"); if (!lres || (plist_get_node_type(lres) != PLIST_DICT)) { plist_free(dict); fprintf(stderr, "ERROR: Could not get dict 'LookupResult'\n"); goto leave_cleanup; } if (xml_mode) { char *xml = NULL; uint32_t len = 0; plist_to_xml(lres, &xml, &len); if (xml) { puts(xml); free(xml); } plist_free(dict); goto leave_cleanup; } plist_dict_iter iter = NULL; plist_t node = NULL; char *key = NULL; printf("Total: %d archived apps\n", plist_dict_get_size(lres)); plist_dict_new_iter(lres, &iter); if (!iter) { plist_free(dict); fprintf(stderr, "ERROR: Could not create plist_dict_iter!\n"); goto leave_cleanup; } do { key = NULL; node = NULL; plist_dict_next_item(lres, iter, &key, &node); if (key && (plist_get_node_type(node) == PLIST_DICT)) { char *s_dispName = NULL; char *s_version = NULL; plist_t dispName = plist_dict_get_item(node, "CFBundleDisplayName"); plist_t version = plist_dict_get_item(node, "CFBundleVersion"); if (dispName) { plist_get_string_val(dispName, &s_dispName); } if (version) { plist_get_string_val(version, &s_version); } if (!s_dispName) { s_dispName = strdup(key); } if (s_version) { printf("%s - %s %s\n", key, s_dispName, s_version); free(s_version); } else { printf("%s - %s\n", key, s_dispName); } free(s_dispName); free(key); } } while (node); plist_free(dict); } else if (cmd == CMD_ARCHIVE) { char *copy_path = NULL; int remove_after_copy = 0; int skip_uninstall = 1; int app_only = 0; int docs_only = 0; plist_t client_opts = NULL; /* look for options */ if (options) { char *opts = strdup(options); char *elem = strtok(opts, ","); while (elem) { if (!strcmp(elem, "uninstall")) { skip_uninstall = 0; } else if (!strcmp(elem, "app_only")) { app_only = 1; docs_only = 0; } else if (!strcmp(elem, "docs_only")) { docs_only = 1; app_only = 0; } else if ((strlen(elem) > 5) && !strncmp(elem, "copy=", 5)) { copy_path = strdup(elem+5); } else if (!strcmp(elem, "remove")) { remove_after_copy = 1; } elem = strtok(NULL, ","); } } if (skip_uninstall || app_only || docs_only) { client_opts = instproxy_client_options_new(); if (skip_uninstall) { instproxy_client_options_add(client_opts, "SkipUninstall", 1, NULL); } if (app_only) { instproxy_client_options_add(client_opts, "ArchiveType", "ApplicationOnly", NULL); } else if (docs_only) { instproxy_client_options_add(client_opts, "ArchiveType", "DocumentsOnly", NULL); } } if (copy_path) { struct stat fst; if (stat(copy_path, &fst) != 0) { fprintf(stderr, "ERROR: stat: %s: %s\n", copy_path, strerror(errno)); free(copy_path); goto leave_cleanup; } if (!S_ISDIR(fst.st_mode)) { fprintf(stderr, "ERROR: '%s' is not a directory as expected.\n", copy_path); free(copy_path); goto leave_cleanup; } #ifdef HAVE_LIBIMOBILEDEVICE_1_1_5 if (service) { lockdownd_service_descriptor_free(service); } service = NULL; #else service = 0; #endif if ((lockdownd_start_service(client, "com.apple.afc", &service) != LOCKDOWN_E_SUCCESS) || !service) { fprintf(stderr, "Could not start com.apple.afc!\n"); free(copy_path); goto leave_cleanup; } lockdownd_client_free(client); client = NULL; if (afc_client_new(phone, service, &afc) != INSTPROXY_E_SUCCESS) { fprintf(stderr, "Could not connect to AFC!\n"); goto leave_cleanup; } } #ifdef HAVE_LIBIMOBILEDEVICE_1_1 instproxy_archive(ipc, appid, client_opts, status_cb, NULL); #else instproxy_archive(ipc, appid, client_opts, status_cb); #endif instproxy_client_options_free(client_opts); wait_for_op_complete = 1; if (skip_uninstall) { notification_expected = 0; } else { notification_expected = 1; } idevice_wait_for_operation_to_complete(); if (copy_path) { if (err_occured) { afc_client_free(afc); afc = NULL; goto leave_cleanup; } FILE *f = NULL; uint64_t af = 0; /* local filename */ char *localfile = NULL; if (asprintf(&localfile, "%s/%s.ipa", copy_path, appid) < 0) { fprintf(stderr, "Out of memory!?\n"); goto leave_cleanup; } free(copy_path); f = fopen(localfile, "wb"); if (!f) { fprintf(stderr, "ERROR: fopen: %s: %s\n", localfile, strerror(errno)); free(localfile); goto leave_cleanup; } /* remote filename */ char *remotefile = NULL; if (asprintf(&remotefile, "%s/%s.zip", APPARCH_PATH, appid) < 0) { fprintf(stderr, "Out of memory!?\n"); goto leave_cleanup; } uint32_t fsize = 0; char **fileinfo = NULL; if ((afc_get_file_info(afc, remotefile, &fileinfo) != AFC_E_SUCCESS) || !fileinfo) { fprintf(stderr, "ERROR getting AFC file info for '%s' on device!\n", remotefile); fclose(f); free(remotefile); free(localfile); goto leave_cleanup; } int i; for (i = 0; fileinfo[i]; i+=2) { if (!strcmp(fileinfo[i], "st_size")) { fsize = atoi(fileinfo[i+1]); break; } } i = 0; while (fileinfo[i]) { free(fileinfo[i]); i++; } free(fileinfo); if (fsize == 0) { fprintf(stderr, "Hm... remote file length could not be determined. Cannot copy.\n"); fclose(f); free(remotefile); free(localfile); goto leave_cleanup; } if ((afc_file_open(afc, remotefile, AFC_FOPEN_RDONLY, &af) != AFC_E_SUCCESS) || !af) { fclose(f); fprintf(stderr, "ERROR: could not open '%s' on device for reading!\n", remotefile); free(remotefile); free(localfile); goto leave_cleanup; } /* copy file over */ printf("Copying '%s' --> '%s'... ", remotefile, localfile); free(remotefile); free(localfile); uint32_t amount = 0; uint32_t total = 0; char buf[8192]; do { if (afc_file_read(afc, af, buf, sizeof(buf), &amount) != AFC_E_SUCCESS) { fprintf(stderr, "AFC Read error!\n"); break; } if (amount > 0) { size_t written = fwrite(buf, 1, amount, f); if (written != amount) { fprintf(stderr, "Error when writing %d bytes to local file!\n", amount); break; } total += written; } } while (amount > 0); afc_file_close(afc, af); fclose(f); printf("DONE.\n"); if (total != fsize) { fprintf(stderr, "WARNING: remote and local file sizes don't match (%d != %d)\n", fsize, total); if (remove_after_copy) { fprintf(stderr, "NOTE: archive file will NOT be removed from device\n"); remove_after_copy = 0; } } if (remove_after_copy) { /* remove archive if requested */ printf("Removing '%s'\n", appid); cmd = CMD_REMOVE_ARCHIVE; free(options); options = NULL; if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(phone, &client, "ideviceinstaller")) { fprintf(stderr, "Could not connect to lockdownd. Exiting.\n"); goto leave_cleanup; } goto run_again; } } goto leave_cleanup; } else if (cmd == CMD_RESTORE) { #ifdef HAVE_LIBIMOBILEDEVICE_1_1 instproxy_restore(ipc, appid, NULL, status_cb, NULL); #else instproxy_restore(ipc, appid, NULL, status_cb); #endif wait_for_op_complete = 1; notification_expected = 1; } else if (cmd == CMD_REMOVE_ARCHIVE) { #ifdef HAVE_LIBIMOBILEDEVICE_1_1 instproxy_remove_archive(ipc, appid, NULL, status_cb, NULL); #else instproxy_remove_archive(ipc, appid, NULL, status_cb); #endif wait_for_op_complete = 1; } else { printf ("ERROR: no operation selected?! This should not be reached!\n"); res = -2; goto leave_cleanup; } if (client) { /* not needed anymore */ lockdownd_client_free(client); client = NULL; } idevice_wait_for_operation_to_complete(); leave_cleanup: if (bundleidentifier) { free(bundleidentifier); } if (np) { np_client_free(np); } if (ipc) { instproxy_client_free(ipc); } if (afc) { afc_client_free(afc); } if (client) { lockdownd_client_free(client); } idevice_free(phone); if (udid) { free(udid); } if (appid) { free(appid); } if (options) { free(options); } return res; }