Example #1
0
static void * rproxy_thread_proc(void * parameter)
{
    control_thread_context_t * context = (control_thread_context_t *)parameter;
    struct bufferevent * control_event = NULL;

    /* Create a bufferevent for the control socket */
    if (0 != create_control_socket_event(context->ev_base, context, &control_event)) {
        error("ERROR: Failed to configure the reverse proxy control socket\n");
        goto cleanup;
    }

    /* Run the event loop */
    if (0 != event_base_dispatch(context->ev_base)) {
        error("ERROR: Failed to start the reverse proxy's event loop\n");
    }

    /* Cleanup */
cleanup:
    if (control_event) {
        bufferevent_free(control_event);
    }
    idevice_disconnect(context->control_connection);
    free(context);

    return NULL;
}
/**
 * Frees a PropertyList service.
 *
 * @param client The property list service to free.
 *
 * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success,
 *     PROPERTY_LIST_SERVICE_E_INVALID_ARG when client is invalid, or a
 *     PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when another error occured.
 */
property_list_service_error_t property_list_service_client_free(property_list_service_client_t client)
{
	if (!client)
		return PROPERTY_LIST_SERVICE_E_INVALID_ARG;

	property_list_service_error_t err = idevice_to_property_list_service_error(idevice_disconnect(client->connection));
	free(client);
	return err;
}
Example #3
0
void asr_free(asr_client_t asr) {
	if (asr != NULL) {
		if (asr->connection != NULL) {
			idevice_disconnect(asr->connection);
			asr->connection = NULL;
		}
		free(asr);
		asr = NULL;
	}
}
Example #4
0
SWIGEXPORT jshort JNICALL Java_org_robovm_libimobiledevice_binding_libimobiledeviceJNI_idevice_1disconnect(JNIEnv *jenv, jclass jcls, jlong jarg1) {
  jshort jresult = 0 ;
  idevice_connection_t arg1 = (idevice_connection_t) 0 ;
  idevice_error_t result;
  
  (void)jenv;
  (void)jcls;
  arg1 = *(idevice_connection_t *)&jarg1; 
  result = (idevice_error_t)idevice_disconnect(arg1);
  jresult = (jshort)result; 
  return jresult;
}
Example #5
0
/**
 * Frees a service instance.
 *
 * @param client The service instance to free.
 *
 * @return SERVICE_E_SUCCESS on success,
 *     SERVICE_E_INVALID_ARG when client is invalid, or a
 *     SERVICE_E_UNKNOWN_ERROR when another error occured.
 */
service_error_t service_client_free(service_client_t client)
{
	if (!client)
		return SERVICE_E_INVALID_ARG;

	service_error_t err = idevice_to_service_error(idevice_disconnect(client->connection));

	free(client);
	client = NULL;

	return err;
}
Example #6
0
static int handle_connect_msg(control_thread_context_t * context)
{
    idevice_connection_t client_connection = NULL;
    if (IDEVICE_E_SUCCESS != rproxy_create_connection(context->device,
            context->connection_port,
            CLIENT_CONNECTION_START_STRING,
            &client_connection)) {
        error("ERROR: Failed to connect to connection port\n");
        goto cleanup;
    }

    plist_t dict = NULL;
    if (0 != rproxy_recv_dict(client_connection, &dict, RPROXY_RECV_TIMEOUT)) {
        error("ERROR: Failed receive connection protocol's dict\n");
        goto cleanup;
    }

    /* Parse the connection protocol version from the response */
    uint64_t conn_protocol_ver = 0;
    if (get_plist_uint_val(dict, "ConnProtoVersion", &conn_protocol_ver) < 0) {
        error("ERROR: Invalid connection protocol plist\n");
        goto cleanup;
    }
    if (CONNECTION_PROTOCOL_VERSION != conn_protocol_ver) {
        error("WARNING: connection protocol mismatch (received "PRIu64", expected "PRIu64")",
              conn_protocol_ver,
              CONNECTION_PROTOCOL_VERSION);
    }

    /* FIXME: Check\Store the identifier? */

    /* Create a new socks client for the connection (and start handling the new connection) */
    if (0 != socks5_add_client_socket(context->ev_base, client_connection)) {
        error("ERROR: Failed to initialize socks client\n");
        goto cleanup;
    }

    return 0;

cleanup:
    if (client_connection) {
        idevice_disconnect(client_connection);
    }
    return -1;
}
Example #7
0
/**
 * Frees up an AFC client. If the connection was created by the
 * client itself, the connection will be closed.
 * 
 * @param client The client to free.
 */
afc_error_t afc_client_free(afc_client_t client)
{
	if (!client || !client->afc_packet)
		return AFC_E_INVALID_ARG;

	if (client->own_connection && client->connection) {
		idevice_disconnect(client->connection);
		client->connection = NULL;
	}
	free(client->afc_packet);
#ifdef WIN32
	DeleteCriticalSection(&client->mutex);
#else
	pthread_mutex_destroy(&client->mutex);
#endif
	free(client);
	return AFC_E_SUCCESS;
}
Example #8
0
/**
 * Makes a connection to the AFC service on the device.
 * This function calls afc_client_new_from_connection() after creating
 * a connection to the specified device and port.
 *
 * @see afc_client_new_from_connection
 * 
 * @param device The device to connect to.
 * @param port The destination port.
 * @param client Pointer that will be set to a newly allocated afc_client_t
 *     upon successful return.
 * 
 * @return AFC_E_SUCCESS on success, AFC_E_INVALID_ARG if device or port is
 *  invalid, AFC_E_MUX_ERROR if the connection cannot be established,
 *  or AFC_E_NO_MEM if there is a memory allocation problem.
 */
afc_error_t afc_client_new(idevice_t device, uint16_t port, afc_client_t * client)
{
	if (!device || port==0)
		return AFC_E_INVALID_ARG;

	/* attempt connection */
	idevice_connection_t connection = NULL;
	if (idevice_connect(device, port, &connection) != IDEVICE_E_SUCCESS) {
		return AFC_E_MUX_ERROR;
	}

	afc_error_t err = afc_client_new_from_connection(connection, client);
	if (err != AFC_E_SUCCESS) {
		idevice_disconnect(connection);
	} else {
		(*client)->own_connection = 1;
	}
	return err;
}
Example #9
0
static int rproxy_create_connection(idevice_t device, uint16_t port, const char * start_msg, idevice_connection_t * connection)
{
    idevice_connection_t new_connection = NULL;

    /* Connect to the proxt port on the device */
    if (IDEVICE_E_SUCCESS != idevice_connect(device, port, &new_connection)) {
        goto cleanup;
    }

    /* Send the start string, including the null terminator */
    uint32_t msg_size = strlen(start_msg) + 1;
    if (IDEVICE_E_SUCCESS != idevice_connection_send_all(new_connection, start_msg, msg_size)) {
        goto cleanup;
    }

    *connection = new_connection;
    return 0;

cleanup:
    if (new_connection) {
        idevice_disconnect(new_connection);
    }
    return -1;
}
Example #10
0
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[]) {
	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;
}
Example #12
0
int rproxy_start(idevice_t device, rproxy_client_t * client)
{
    struct rproxy_client_private * new_client = NULL;
    idevice_connection_t control_connection = NULL;
    control_thread_context_t * thread_ctx = NULL;
    struct event_base * ev_base = NULL;

#ifdef WIN32
    /* Initialize Winsock */
    WSADATA wsaData = { 0 };
    if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData)) {
        error("ERROR: Failed to initialize Winsock\n");
        return -1;
    }
#endif

    /* Initialize libevent */
    event_set_fatal_callback(libevent_fatal_cb);
    event_set_log_callback(libevent_log_cb);
#ifdef WIN32
    if (0 != evthread_use_windows_threads()) {
        error("ERROR: Failed to initialize libevent's threading support\n");
        goto cleanup;
    }
#else
    if (0 != evthread_use_pthreads()) {
        error("ERROR: Failed to initialize libevent's threading support\n");
        goto cleanup;
    }
#endif
#ifdef _DEBUG
    event_enable_debug_mode();
#endif

    /* Create a new client struct  */
    new_client = (rproxy_client_private *)calloc(1, sizeof(rproxy_client_private));
    if (NULL == new_client) {
        error("ERROR: Out of memory\n");
        goto cleanup;
    }

    /* Create an event base */
    new_client->ev_base = event_base_new();
    if (NULL == new_client->ev_base) {
        error("ERROR: Failed to initialize libevent\n");
        goto cleanup;
    }

    /* Connect to the proxy service */
    uint16_t conn_port = 0;
    int i = 0;
    for (i = 1; i <= CONTROL_CONNTECTION_ATTEMPTS; i++) {
        if (0 == rproxy_connect_control_service(device, &control_connection, &conn_port)) {
            break;
        }

        if (CONTROL_CONNTECTION_ATTEMPTS == i) {
            error("ERROR: Failed to initialize reverse proxy connection\n");
            goto cleanup;
        }

        sleep(CONTROL_CONNTECTION_ATTEMPTS_INTERVAL);
        debug("Failed to connect to the proxy, retrying...\n");
    }

    /* Start a new thread for the reverse proxy event loop */
    thread_ctx = (control_thread_context_t *)calloc(1, sizeof(control_thread_context_t));
    if (NULL == thread_ctx) {
        error("ERROR: Out of memory\n");
        goto cleanup;
    }
    thread_ctx->device = device;
    thread_ctx->control_connection = control_connection;
    thread_ctx->connection_port = (uint16_t)conn_port;
    thread_ctx->ev_base = new_client->ev_base;

    if (0 != thread_create(&(new_client->thread), rproxy_thread_proc, thread_ctx)) {
        error("ERROR: Failed to start the reverse proxy thread\n");
        goto cleanup;
    }

    info("Reverse proxy is running\n");
    *client = new_client;
    return 0;

cleanup:
    if (control_connection) {
        idevice_disconnect(control_connection);
    }
    if (new_client) {
        if (new_client->ev_base) {
            event_base_free(new_client->ev_base);
        }
        free(new_client);
    }
    if (thread_ctx) {
        free(thread_ctx);
    }
#ifdef WIN32
    WSACleanup();
#endif

    return -1;
}
Example #13
0
static int rproxy_connect_control_service(idevice_t device, idevice_connection_t * control_connection, uint16_t * connection_port)
{
    plist_t dict = NULL;

    /* Connect to the proxy service */
    idevice_connection_t new_connection = NULL;
    if (IDEVICE_E_SUCCESS != rproxy_create_connection(device, REVERSE_PROXY_MUX_PORT, CONTROL_CONNECTION_START_STRING, &new_connection)) {
        error("ERROR: Failed to connect to the proxy service\n");
        goto cleanup;
    }

    /* Send the BeginCtrl command */
    dict = plist_new_dict();
    plist_dict_set_item(dict, "Command", plist_new_string("BeginCtrl"));
    plist_dict_set_item(dict, "CtrlProtoVersion", plist_new_uint(CONTROL_PROTOCOL_VERSION));

    if (0 != rproxy_send_dict(new_connection, dict)) {
        error("ERROR: Failed send BeginCtrl command to the service\n");
        goto cleanup;
    }
    plist_free(dict);
    dict = NULL;

    /* Get the BeginCtrl's response */
    if (0 != rproxy_recv_dict(new_connection, &dict, RPROXY_RECV_TIMEOUT)) {
        error("ERROR: Failed receive a response for BeginCtrl\n");
        goto cleanup;
    }

    /* Parse the recieved protocol version */
    uint64_t device_ctrl_proto_ver = 0;
    if (get_plist_uint_val(dict, "CtrlProtoVersion", &device_ctrl_proto_ver) < 0) {
        error("ERROR: Device response to BeginCtrl doesn't contain a protocol version\n");
        goto cleanup;
    }
    if (CONTROL_PROTOCOL_VERSION != device_ctrl_proto_ver) {
        error("ERROR: Proxy protocol version mismatch: expected "PRIu64", device reported "PRIu64"\n",
              CONTROL_PROTOCOL_VERSION,
              device_ctrl_proto_ver);
        goto cleanup;
    }

    /* Parse the connection port from the response */
    uint64_t received_conn_port = 0;
    if (get_plist_uint_val(dict, "ConnPort", &received_conn_port) < 0) {
        error("ERROR: Device response to BeginCtrl is missing a connection port\n");
        goto cleanup;
    }
    debug("Reverse proxy connection port: %us", (uint16_t)received_conn_port);

    plist_free(dict);
    dict = NULL;

    *control_connection = new_connection;
    *connection_port = (uint16_t)received_conn_port;
    return 0;

cleanup:
    if (dict) {
        plist_free(dict);
    }
    if (new_connection) {
        idevice_disconnect(new_connection);
    }

    return -1;
}
Example #14
0
void asr_close(idevice_connection_t asr) {
	if (asr != NULL) {
		idevice_disconnect(asr);
		asr = NULL;
	}
}