diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/InstallationProxy.c | 138 | ||||
| -rw-r--r-- | src/MobileSync.c | 69 | ||||
| -rw-r--r-- | src/NotificationProxy.c | 162 | ||||
| -rw-r--r-- | src/SBServices.c | 155 | ||||
| -rw-r--r-- | src/iphone.c | 281 | ||||
| -rw-r--r-- | src/iphone.h | 13 | ||||
| -rw-r--r-- | src/lockdown.c | 98 | 
7 files changed, 452 insertions, 464 deletions
| diff --git a/src/InstallationProxy.c b/src/InstallationProxy.c index 917886d..387f9ca 100644 --- a/src/InstallationProxy.c +++ b/src/InstallationProxy.c @@ -56,112 +56,28 @@ static void instproxy_unlock(instproxy_client_t client)  }  /** - * Sends an xml plist to the device using the connection specified in client. - * This function is only used internally. + * Convert an iphone_error_t value to an instproxy_error_t value. + * Used internally to get correct error codes when using plist helper + * functions.   * - * @param client The installation_proxy to send data to - * @param plist plist to send + * @param err An iphone_error_t error code   * - * @return INSTPROXY_E_SUCCESS on success, INSTPROXY_E_INVALID_ARG when client - *      or plist are NULL, INSTPROXY_E_PLIST_ERROR when dict is not a valid - *      plist, or INSTPROXY_E_UNKNOWN_ERROR when an unspecified error occurs. + * @return A matching instproxy_error_t error code, + *     INSTPROXY_E_UNKNOWN_ERROR otherwise.   */ -static instproxy_error_t instproxy_plist_send(instproxy_client_t client, plist_t plist) +static instproxy_error_t iphone_to_instproxy_error(iphone_error_t err)  { -	instproxy_error_t res = INSTPROXY_E_UNKNOWN_ERROR; -	char *XML_content = NULL; -	uint32_t length = 0; -	uint32_t nlen = 0; -	int bytes = 0; - -	if (!client || !plist) { -		return INSTPROXY_E_INVALID_ARG; -	} - -	plist_to_xml(plist, &XML_content, &length); - -	if (!XML_content || length == 0) { -		return INSTPROXY_E_PLIST_ERROR; -	} - -	nlen = htonl(length); -	log_debug_msg("%s: sending %d bytes\n", __func__, length); -	iphone_device_send(client->connection, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); -	if (bytes == sizeof(nlen)) { -		iphone_device_send(client->connection, XML_content, length, (uint32_t*)&bytes); -		if (bytes > 0) { -			log_debug_msg("%s: received %d bytes\n", __func__, bytes); -			log_debug_buffer(XML_content, bytes); -			if ((uint32_t)bytes == length) { -				res = INSTPROXY_E_SUCCESS; -			} else { -				log_debug_msg("%s: ERROR: Could not send all data (%d of %d)!\n", __func__, bytes, length); -			} -		} -	} -	if (bytes <= 0) { -		log_dbg_msg(DBGMASK_INSTPROXY, "%s: ERROR: sending to device failed.\n", __func__); -	} - -	free(XML_content); - -	return res; -} - -/** - * Receives an xml plist from the device using the connection specified in - *  client. - * This function is only used internally. - * - * @param client The installation_proxy to receive data from - * @param plist pointer to a plist_t that will point to the received plist - *              upon successful return - * - * @return INSTPROXY_E_SUCCESS on success, INSTPROXY_E_INVALID_ARG when client - *      or *plist are NULL, INSTPROXY_E_PLIST_ERROR when dict is not a valid - *      plist, or INSTPROXY_E_UNKNOWN_ERROR when an unspecified error occurs. - */ -static instproxy_error_t instproxy_plist_recv(instproxy_client_t client, plist_t *plist) -{ -	instproxy_error_t res = INSTPROXY_E_UNKNOWN_ERROR; -	char *XML_content = NULL; -	uint32_t pktlen = 0; -	uint32_t bytes = 0; - -	if (!client || !plist) { -		return INSTPROXY_E_INVALID_ARG; -	} - -	iphone_device_recv_timeout(client->connection, (char*)&pktlen, sizeof(pktlen), &bytes, 300000); /* 5 minute timeout should be enough */ -	log_debug_msg("%s: initial read=%i\n", __func__, bytes); -	if (bytes < 4) { -		log_dbg_msg(DBGMASK_INSTPROXY, "%s: initial read failed!\n"); -	} else { -		if ((char)pktlen == 0) { -			uint32_t curlen = 0; -			pktlen = ntohl(pktlen); -			log_debug_msg("%s: %d bytes following\n", __func__, pktlen); -			XML_content = (char*)malloc(pktlen); - -			while (curlen < pktlen) { -				iphone_device_recv(client->connection, XML_content+curlen, pktlen-curlen, &bytes); -				if (bytes <= 0) { -					res = INSTPROXY_E_UNKNOWN_ERROR; -					break; -				} -				log_debug_msg("%s: received %d bytes\n", __func__, bytes); -				curlen += bytes; -			} -			log_debug_buffer(XML_content, pktlen); -			plist_from_xml(XML_content, pktlen, plist); -			res = INSTPROXY_E_SUCCESS; -			free(XML_content); -			XML_content = NULL; -		} else { -			res = INSTPROXY_E_UNKNOWN_ERROR; -		} +	switch (err) { +		case IPHONE_E_SUCCESS: +			return INSTPROXY_E_SUCCESS; +		case IPHONE_E_INVALID_ARG: +			return INSTPROXY_E_INVALID_ARG; +		case IPHONE_E_PLIST_ERROR: +			return INSTPROXY_E_PLIST_ERROR; +		default: +			break;  	} -	return res; +	return INSTPROXY_E_UNKNOWN_ERROR;  }  /** @@ -268,7 +184,7 @@ instproxy_error_t instproxy_browse(instproxy_client_t client, instproxy_apptype_  	plist_dict_insert_item(dict, "Command", plist_new_string("Browse"));  	instproxy_lock(client); -	res = instproxy_plist_send(client, dict); +	res = iphone_to_instproxy_error(iphone_device_send_xml_plist(client->connection, dict));  	plist_free(dict);  	if (res != INSTPROXY_E_SUCCESS) {  		log_dbg_msg(DBGMASK_INSTPROXY, "%s: could not send plist\n", __func__); @@ -280,7 +196,7 @@ instproxy_error_t instproxy_browse(instproxy_client_t client, instproxy_apptype_  	do {  		browsing = 0;  		dict = NULL; -		res = instproxy_plist_recv(client, &dict); +		res = iphone_to_instproxy_error(iphone_device_receive_plist(client->connection, &dict));  		if (res != INSTPROXY_E_SUCCESS) {  			break;  		} @@ -345,7 +261,7 @@ static instproxy_error_t instproxy_perform_operation(instproxy_client_t client,  	do {  		instproxy_lock(client); -		res = instproxy_plist_recv(client, &dict); +		res = iphone_to_instproxy_error(iphone_device_receive_plist_with_timeout(client->connection, &dict, 30000));  		instproxy_unlock(client);  		if (res != INSTPROXY_E_SUCCESS) {  			log_dbg_msg(DBGMASK_INSTPROXY, "%s: could not receive plist, error %d\n", __func__, res); @@ -517,7 +433,7 @@ static instproxy_error_t instproxy_install_or_upgrade(instproxy_client_t client,  	plist_dict_insert_item(dict, "PackagePath", plist_new_string(pkg_path));  	instproxy_lock(client); -	res = instproxy_plist_send(client, dict); +	res = iphone_to_instproxy_error(iphone_device_send_xml_plist(client->connection, dict));  	instproxy_unlock(client);  	plist_free(dict); @@ -610,7 +526,7 @@ instproxy_error_t instproxy_uninstall(instproxy_client_t client, const char *app  	plist_dict_insert_item(dict, "Command", plist_new_string("Uninstall"));  	instproxy_lock(client); -	res = instproxy_plist_send(client, dict); +	res = iphone_to_instproxy_error(iphone_device_send_xml_plist(client->connection, dict));  	instproxy_unlock(client);  	plist_free(dict); @@ -647,7 +563,7 @@ instproxy_error_t instproxy_lookup_archives(instproxy_client_t client, plist_t *  	instproxy_lock(client); -	res = instproxy_plist_send(client, dict); +	res = iphone_to_instproxy_error(iphone_device_send_xml_plist(client->connection, dict));  	plist_free(dict);  	if (res != INSTPROXY_E_SUCCESS) { @@ -655,7 +571,7 @@ instproxy_error_t instproxy_lookup_archives(instproxy_client_t client, plist_t *  		goto leave_unlock;  	} -	res = instproxy_plist_recv(client, result); +	res = iphone_to_instproxy_error(iphone_device_receive_plist(client->connection, result));  	if (res != INSTPROXY_E_SUCCESS) {  		log_dbg_msg(DBGMASK_INSTPROXY, "%s: could not receive plist, error %d\n", __func__, res);  		goto leave_unlock; @@ -718,7 +634,7 @@ instproxy_error_t instproxy_archive(instproxy_client_t client, const char *appid  	plist_dict_insert_item(dict, "Command", plist_new_string("Archive"));  	instproxy_lock(client); -	res = instproxy_plist_send(client, dict); +	res = iphone_to_instproxy_error(iphone_device_send_xml_plist(client->connection, dict));  	instproxy_unlock(client);  	plist_free(dict); @@ -764,7 +680,7 @@ instproxy_error_t instproxy_restore(instproxy_client_t client, const char *appid  	plist_dict_insert_item(dict, "Command", plist_new_string("Restore"));  	instproxy_lock(client); -	res = instproxy_plist_send(client, dict); +	res = iphone_to_instproxy_error(iphone_device_send_xml_plist(client->connection, dict));  	instproxy_unlock(client);  	plist_free(dict); @@ -810,7 +726,7 @@ instproxy_error_t instproxy_remove_archive(instproxy_client_t client, const char  	plist_dict_insert_item(dict, "Command", plist_new_string("RemoveArchive"));  	instproxy_lock(client); -	res = instproxy_plist_send(client, dict); +	res = iphone_to_instproxy_error(iphone_device_send_xml_plist(client->connection, dict));  	instproxy_unlock(client);  	plist_free(dict); diff --git a/src/MobileSync.c b/src/MobileSync.c index 77d2710..76aefa0 100644 --- a/src/MobileSync.c +++ b/src/MobileSync.c @@ -31,6 +31,31 @@  #define MSYNC_VERSION_INT1 100  #define MSYNC_VERSION_INT2 100 +/** + * Convert an iphone_error_t value to an mobilesync_error_t value. + * Used internally to get correct error codes when using plist helper + * functions. + * + * @param err An iphone_error_t error code + * + * @return A matching mobilesync_error_t error code, + *     MOBILESYNC_E_UNKNOWN_ERROR otherwise. + */ +static mobilesync_error_t iphone_to_mobilesync_error(iphone_error_t err) +{ +	switch (err) { +		case IPHONE_E_SUCCESS: +			return MOBILESYNC_E_SUCCESS; +		case IPHONE_E_INVALID_ARG: +			return MOBILESYNC_E_INVALID_ARG; +		case IPHONE_E_PLIST_ERROR: +			return MOBILESYNC_E_PLIST_ERROR; +		default: +			break; +	} +	return MOBILESYNC_E_UNKNOWN_ERROR; +} +  mobilesync_error_t mobilesync_client_new(iphone_device_t device, int dst_port,  						   mobilesync_client_t * client)  { @@ -160,35 +185,19 @@ mobilesync_error_t mobilesync_recv(mobilesync_client_t client, plist_t * plist)  {  	if (!client || !plist || (plist && *plist))  		return MOBILESYNC_E_INVALID_ARG; -	mobilesync_error_t ret = MOBILESYNC_E_UNKNOWN_ERROR; -	char *receive = NULL; -	uint32_t datalen = 0, bytes = 0, received_bytes = 0; - -	ret = iphone_device_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes); -	datalen = ntohl(datalen); - -	receive = (char *) malloc(sizeof(char) * datalen); - -	/* fill buffer and request more packets if needed */ -	while ((received_bytes < datalen) && (ret == MOBILESYNC_E_SUCCESS)) { -		ret = iphone_device_recv(client->connection, receive + received_bytes, datalen - received_bytes, &bytes); -		received_bytes += bytes; -	} +	mobilesync_error_t ret = iphone_to_mobilesync_error(iphone_device_receive_plist(client->connection, plist));  	if (ret != MOBILESYNC_E_SUCCESS) { -		free(receive);  		return MOBILESYNC_E_MUX_ERROR;  	} -	plist_from_bin(receive, received_bytes, plist); -	free(receive); - +#ifndef STRIP_DEBUG_CODE  	char *XMLContent = NULL;  	uint32_t length = 0;  	plist_to_xml(*plist, &XMLContent, &length);  	log_dbg_msg(DBGMASK_MOBILESYNC, "%s: plist size: %i\nbuffer :\n%s\n", __func__, length, XMLContent);  	free(XMLContent); - +#endif  	return ret;  } @@ -207,28 +216,12 @@ mobilesync_error_t mobilesync_send(mobilesync_client_t client, plist_t plist)  	if (!client || !plist)  		return MOBILESYNC_E_INVALID_ARG; +#ifndef STRIP_DEBUG_CODE  	char *XMLContent = NULL;  	uint32_t length = 0;  	plist_to_xml(plist, &XMLContent, &length);  	log_dbg_msg(DBGMASK_MOBILESYNC, "%s: plist size: %i\nbuffer :\n%s\n", __func__, length, XMLContent);  	free(XMLContent); - -	char *content = NULL; -	length = 0; - -	plist_to_bin(plist, &content, &length); - -	char *real_query; -	int bytes; -	mobilesync_error_t ret = MOBILESYNC_E_UNKNOWN_ERROR; - -	real_query = (char *) malloc(sizeof(char) * (length + 4)); -	length = htonl(length); -	memcpy(real_query, &length, sizeof(length)); -	memcpy(real_query + 4, content, ntohl(length)); - -	ret = iphone_device_send(client->connection, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes); -	free(real_query); -	return (ret == 0 ? MOBILESYNC_E_SUCCESS: MOBILESYNC_E_MUX_ERROR); +#endif +	return (iphone_device_send_binary_plist(client->connection, plist) == IPHONE_E_SUCCESS ? MOBILESYNC_E_SUCCESS : MOBILESYNC_E_MUX_ERROR);  } - diff --git a/src/NotificationProxy.c b/src/NotificationProxy.c index cba12b9..b73b521 100644 --- a/src/NotificationProxy.c +++ b/src/NotificationProxy.c @@ -56,53 +56,28 @@ static void np_unlock(np_client_t client)  }  /** - * Sends an xml plist to the device using the connection specified in client. - * This function is only used internally. + * Convert an iphone_error_t value to an np_error_t value. + * Used internally to get correct error codes when using plist helper + * functions.   * - * @param client NP to send data to - * @param dict plist to send + * @param err An iphone_error_t error code   * - * @return NP_E_SUCCESS on success, NP_E_INVALID_ARG when client or dict - *      are NULL, NP_E_PLIST_ERROR when dict is not a valid plist, - *      or NP_E_UNKNOWN_ERROR when an unspecified error occurs. + * @return A matching np_error_t error code, + *     NP_E_UNKNOWN_ERROR otherwise.   */ -static np_error_t np_plist_send(np_client_t client, plist_t dict) +static np_error_t iphone_to_np_error(iphone_error_t err)  { -	char *XML_content = NULL; -	uint32_t length = 0; -	uint32_t nlen = 0; -	int bytes = 0; -	np_error_t res = NP_E_UNKNOWN_ERROR; - -	if (!client || !dict) { -		return NP_E_INVALID_ARG; -	} - -	plist_to_xml(dict, &XML_content, &length); - -	if (!XML_content || length == 0) { -		return NP_E_PLIST_ERROR; -	} - -	nlen = htonl(length); -	iphone_device_send(client->connection, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); -	if (bytes == sizeof(nlen)) { -		iphone_device_send(client->connection, XML_content, length, (uint32_t*)&bytes); -		if (bytes > 0) { -			if ((uint32_t)bytes == length) { -				res = NP_E_SUCCESS; -			} else { -				log_debug_msg("%s: ERROR: Could not send all data (%d of %d)!\n", __func__, bytes, length); -			} -		} -	} -	if (bytes <= 0) { -		log_debug_msg("%s: ERROR: sending to device failed.\n", __func__); +	switch (err) { +		case IPHONE_E_SUCCESS: +			return NP_E_SUCCESS; +		case IPHONE_E_INVALID_ARG: +			return NP_E_INVALID_ARG; +		case IPHONE_E_PLIST_ERROR: +			return NP_E_PLIST_ERROR; +		default: +			break;  	} - -	free(XML_content); - -	return res; +	return NP_E_UNKNOWN_ERROR;  }  /** Makes a connection to the NP service on the phone.  @@ -185,13 +160,13 @@ np_error_t np_post_notification(np_client_t client, const char *notification)  	plist_dict_insert_item(dict,"Command", plist_new_string("PostNotification"));  	plist_dict_insert_item(dict,"Name", plist_new_string(notification)); -	np_error_t res = np_plist_send(client, dict); +	np_error_t res = iphone_to_np_error(iphone_device_send_xml_plist(client->connection, dict));  	plist_free(dict);  	dict = plist_new_dict();  	plist_dict_insert_item(dict,"Command", plist_new_string("Shutdown")); -	res = np_plist_send(client, dict); +	res = iphone_to_np_error(iphone_device_send_xml_plist(client->connection, dict));  	plist_free(dict);  	if (res != NP_E_SUCCESS) { @@ -221,7 +196,7 @@ np_error_t np_observe_notification( np_client_t client, const char *notification  	plist_dict_insert_item(dict,"Command", plist_new_string("ObserveNotification"));  	plist_dict_insert_item(dict,"Name", plist_new_string(notification)); -	np_error_t res = np_plist_send(client, dict); +	np_error_t res = iphone_to_np_error(iphone_device_send_xml_plist(client->connection, dict));  	if (res != NP_E_SUCCESS) {  		log_debug_msg("%s: Error sending XML plist to device!\n", __func__);  	} @@ -281,10 +256,7 @@ np_error_t np_observe_notifications(np_client_t client, const char **notificatio   */  static int np_get_notification(np_client_t client, char **notification)  { -	uint32_t bytes = 0;  	int res = 0; -	uint32_t pktlen = 0; -	char *XML_content = NULL;  	plist_t dict = NULL;  	if (!client || !client->connection || *notification) @@ -292,72 +264,46 @@ static int np_get_notification(np_client_t client, char **notification)  	np_lock(client); -	iphone_device_recv_timeout(client->connection, (char*)&pktlen, sizeof(pktlen), &bytes, 500); -	log_debug_msg("NotificationProxy: initial read=%i\n", bytes); -	if (bytes < 4) { +	iphone_device_receive_plist_with_timeout(client->connection, &dict, 500); +	if (!dict) {  		log_debug_msg("NotificationProxy: no notification received!\n");  		res = 0;  	} else { -		if ((char)pktlen == 0) { -			pktlen = ntohl(pktlen); -			log_debug_msg("NotificationProxy: %d bytes following\n", pktlen); -			XML_content = (char*)malloc(pktlen); -			log_debug_msg("pointer %p\n", XML_content); - -			iphone_device_recv_timeout(client->connection, XML_content, pktlen, &bytes, 1000); -			if (bytes <= 0) { -				res = -1; -			} else { -				log_debug_msg("NotificationProxy: received data:\n"); -				log_debug_buffer(XML_content, pktlen); - -				plist_from_xml(XML_content, bytes, &dict); -				if (!dict) { -					np_unlock(client); -					return -2; -				} - -				char *cmd_value = NULL; -				plist_t cmd_value_node = plist_dict_get_item(dict, "Command"); - -				if (plist_get_node_type(cmd_value_node) == PLIST_STRING) { -					plist_get_string_val(cmd_value_node, &cmd_value); -				} - -				if (cmd_value && !strcmp(cmd_value, "RelayNotification")) { -					char *name_value = NULL; -					plist_t name_value_node = plist_dict_get_item(dict, "Name"); - -					if (plist_get_node_type(name_value_node) == PLIST_STRING) { -						plist_get_string_val(name_value_node, &name_value); -					} - -					res = -2; -					if (name_value_node && name_value) { -						*notification = name_value; -						log_debug_msg("%s: got notification %s\n", __func__, name_value); -						res = 0; -					} -				} else if (cmd_value && !strcmp(cmd_value, "ProxyDeath")) { -					log_debug_msg("%s: ERROR: NotificationProxy died!\n", __func__); -					res = -1; -				} else if (cmd_value) { -					log_debug_msg("%d: unknown NotificationProxy command '%s' received!\n", __func__); -					res = -1; -				} else { -					res = -2; -				} -				if (cmd_value) { -					free(cmd_value); -				} -				plist_free(dict); -				dict = NULL; -				free(XML_content); -				XML_content = NULL; +		char *cmd_value = NULL; +		plist_t cmd_value_node = plist_dict_get_item(dict, "Command"); + +		if (plist_get_node_type(cmd_value_node) == PLIST_STRING) { +			plist_get_string_val(cmd_value_node, &cmd_value); +		} + +		if (cmd_value && !strcmp(cmd_value, "RelayNotification")) { +			char *name_value = NULL; +			plist_t name_value_node = plist_dict_get_item(dict, "Name"); + +			if (plist_get_node_type(name_value_node) == PLIST_STRING) { +				plist_get_string_val(name_value_node, &name_value);  			} -		} else { + +			res = -2; +			if (name_value_node && name_value) { +				*notification = name_value; +				log_debug_msg("%s: got notification %s\n", __func__, name_value); +				res = 0; +			} +		} else if (cmd_value && !strcmp(cmd_value, "ProxyDeath")) { +			log_debug_msg("%s: ERROR: NotificationProxy died!\n", __func__);  			res = -1; +		} else if (cmd_value) { +			log_debug_msg("%d: unknown NotificationProxy command '%s' received!\n", __func__); +			res = -1; +		} else { +			res = -2; +		} +		if (cmd_value) { +			free(cmd_value);  		} +		plist_free(dict); +		dict = NULL;  	}  	np_unlock(client); diff --git a/src/SBServices.c b/src/SBServices.c index 9849415..1296245 100644 --- a/src/SBServices.c +++ b/src/SBServices.c @@ -87,112 +87,39 @@ sbservices_error_t sbservices_client_free(sbservices_client_t client)  	return SBSERVICES_E_SUCCESS;  } -/** - * Sends a binary plist to the device using the connection specified in client. - * This function is only used internally. - * - * @param client InstallationProxy to send data to - * @param dict plist to send - * - * @return SBSERVICES_E_SUCCESS on success, SBSERVICES_E_INVALID_ARG when - *     client or dict are NULL, SBSERVICES_E_PLIST_ERROR when dict is not a - *     valid plist, or SBSERVICES_E_UNKNOWN_ERROR when an unspecified error - *     occurs. - */ -static sbservices_error_t sbservices_plist_send(sbservices_client_t client, plist_t dict) -{ -	char *content = NULL; -	uint32_t length = 0; -	uint32_t nlen = 0; -	int bytes = 0; -	sbservices_error_t res = SBSERVICES_E_UNKNOWN_ERROR; - -	if (!client || !dict) { -		return SBSERVICES_E_INVALID_ARG; -	} - -	plist_to_bin(dict, &content, &length); - -	if (!content || length == 0) { -		return SBSERVICES_E_PLIST_ERROR; -	} - -	nlen = htonl(length); -	log_debug_msg("%s: sending %d bytes\n", __func__, length); -	iphone_device_send(client->connection, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); -	if (bytes == sizeof(nlen)) { -		iphone_device_send(client->connection, content, length, (uint32_t*)&bytes); -		if (bytes > 0) { -			if ((uint32_t)bytes == length) { -				res = SBSERVICES_E_SUCCESS; -			} else { -				log_debug_msg("%s: ERROR: Could not send all data (%d of %d)!\n", __func__, bytes, length); -			} -		} -	} -	if (bytes <= 0) { -		log_debug_msg("%s: ERROR: sending to device failed.\n", __func__); -	} - -	free(content); - -	return res; -} -  sbservices_error_t sbservices_get_icon_state(sbservices_client_t client, plist_t *state)  {  	if (!client || !client->connection || !state)  		return SBSERVICES_E_INVALID_ARG;  	sbservices_error_t res = SBSERVICES_E_UNKNOWN_ERROR; -	uint32_t pktlen = 0; -	uint32_t bytes = 0;  	plist_t dict = plist_new_dict();  	plist_dict_insert_item(dict, "command", plist_new_string("getIconState"));  	sbs_lock(client); -	res = sbservices_plist_send(client, dict); -	plist_free(dict); -	if (res != SBSERVICES_E_SUCCESS) { +	if (iphone_device_send_binary_plist(client->connection, dict) != IPHONE_E_SUCCESS) {  		log_debug_msg("%s: could not send plist\n", __func__);  		goto leave_unlock;  	} +	plist_free(dict); +	dict = NULL; -	iphone_device_recv(client->connection, (char*)&pktlen, sizeof(pktlen), &bytes); -	log_debug_msg("%s: initial read=%i\n", __func__, bytes); -	if (bytes < 4) { -		log_debug_msg("%s: initial read failed!\n"); -		res = 0; +	if (iphone_device_receive_plist(client->connection, state) == IPHONE_E_SUCCESS) { +		res = SBSERVICES_E_SUCCESS;  	} else { -		if ((char)pktlen == 0) { -			char *content = NULL; -			uint32_t curlen = 0; -			pktlen = ntohl(pktlen); -			log_debug_msg("%s: %d bytes following\n", __func__, pktlen); -			content = (char*)malloc(pktlen); -			log_debug_msg("pointer %p\n", content); - -			while (curlen < pktlen) { -				iphone_device_recv(client->connection, content+curlen, pktlen-curlen, &bytes); -				if (bytes <= 0) { -					res = SBSERVICES_E_UNKNOWN_ERROR; -					break; -				} -				log_debug_msg("%s: received %d bytes\n", __func__, bytes); -				curlen += bytes; -			} -			log_debug_buffer(content, pktlen); -			plist_from_bin(content, pktlen, state); -			res = SBSERVICES_E_SUCCESS; -			free(content); -		} else { -			res = SBSERVICES_E_UNKNOWN_ERROR; +		log_debug_msg("%s: could not get icon state!\n", __func__); +		if (*state) { +			plist_free(*state); +			*state = NULL;  		}  	}  leave_unlock: +	if (dict) { +		plist_free(dict); +	}  	sbs_unlock(client);  	return res;  } @@ -210,15 +137,16 @@ sbservices_error_t sbservices_set_icon_state(sbservices_client_t client, plist_t  	sbs_lock(client); -	res = sbservices_plist_send(client, dict); -	plist_free(dict); -	if (res != SBSERVICES_E_SUCCESS) { +	if (iphone_device_send_binary_plist(client->connection, dict) != IPHONE_E_SUCCESS) {  		log_debug_msg("%s: could not send plist\n", __func__);  		goto leave_unlock;  	}  	// NO RESPONSE  leave_unlock: +	if (dict) { +		plist_free(dict); +	}  	sbs_unlock(client);  	return res;  } @@ -229,8 +157,6 @@ sbservices_error_t sbservices_get_icon_pngdata(sbservices_client_t client, const  		return SBSERVICES_E_INVALID_ARG;  	sbservices_error_t res = SBSERVICES_E_UNKNOWN_ERROR; -	uint32_t pktlen = 0; -	uint32_t bytes = 0;  	plist_t dict = plist_new_dict();  	plist_dict_insert_item(dict, "command", plist_new_string("getIconPNGData")); @@ -238,52 +164,25 @@ sbservices_error_t sbservices_get_icon_pngdata(sbservices_client_t client, const  	sbs_lock(client); -	res = sbservices_plist_send(client, dict); -	plist_free(dict); -	if (res != SBSERVICES_E_SUCCESS) { +	if (iphone_device_send_binary_plist(client->connection, dict) != IPHONE_E_SUCCESS) {  		log_debug_msg("%s: could not send plist\n", __func__);  		goto leave_unlock;  	} +	plist_free(dict); -	iphone_device_recv(client->connection, (char*)&pktlen, sizeof(pktlen), &bytes); -	log_debug_msg("%s: initial read=%i\n", __func__, bytes); -	if (bytes < 4) { -		log_debug_msg("%s: initial read failed!\n"); -		res = 0; -	} else { -		if ((char)pktlen == 0) { -			char *content = NULL; -			uint32_t curlen = 0; -			pktlen = ntohl(pktlen); -			log_debug_msg("%s: %d bytes following\n", __func__, pktlen); -			content = (char*)malloc(pktlen); -			log_debug_msg("pointer %p\n", content); - -			while (curlen < pktlen) { -				iphone_device_recv(client->connection, content+curlen, pktlen-curlen, &bytes); -				if (bytes <= 0) { -					res = SBSERVICES_E_UNKNOWN_ERROR; -					break; -				} -				log_debug_msg("%s: received %d bytes\n", __func__, bytes); -				curlen += bytes; -			} -			log_debug_buffer(content, pktlen); -			plist_t pngdict = NULL; -			plist_from_bin(content, pktlen, &pngdict); -			plist_t node = plist_dict_get_item(pngdict, "pngData"); -			if (node) { -				plist_get_data_val(node, pngdata, pngsize); -			} -			plist_free(pngdict); -			res = SBSERVICES_E_SUCCESS; -			free(content); -		} else { -			res = SBSERVICES_E_UNKNOWN_ERROR; +	dict = NULL; +	if (iphone_device_receive_plist(client->connection, &dict) == IPHONE_E_SUCCESS) { +		plist_t node = plist_dict_get_item(dict, "pngData"); +		if (node) { +			plist_get_data_val(node, pngdata, pngsize);  		} +		res = SBSERVICES_E_SUCCESS;  	}  leave_unlock: +	if (dict) { +		plist_free(dict); +	}  	sbs_unlock(client);  	return res; diff --git a/src/iphone.c b/src/iphone.c index 586b3bc..3c13859 100644 --- a/src/iphone.c +++ b/src/iphone.c @@ -23,6 +23,7 @@  #include <stdlib.h>  #include <string.h>  #include <errno.h> +#include <arpa/inet.h>  #include <usbmuxd.h>  #include "iphone.h" @@ -350,6 +351,286 @@ iphone_error_t iphone_device_recv(iphone_connection_t connection, char *data, ui  	return IPHONE_E_UNKNOWN_ERROR;  } +/** + * Sends a plist over the given connection. + * Internally used generic plist send function. + * + * @param connection The connection to use for sending. + *        Can be NULL if ssl_session is non-NULL. + * @param plist plist to send + * @param binary 1 = send binary plist, 0 = send xml plist + * @param ssl_session If set to NULL, the communication will be unencrypted. + *        For encrypted communication, pass a valid and properly initialized + *        gnutls_session_t. connection is ignored when ssl_session is non-NULL. + * + * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when one or more + *      parameters are invalid, IPHONE_E_PLIST_ERROR when dict is not a valid + *      plist, or IPHONE_E_UNKNOWN_ERROR when an unspecified error occurs. + */ +static iphone_error_t internal_plist_send(iphone_connection_t connection, plist_t plist, int binary, gnutls_session_t ssl_session) +{ +	iphone_error_t res = IPHONE_E_UNKNOWN_ERROR; +	char *content = NULL; +	uint32_t length = 0; +	uint32_t nlen = 0; +	int bytes = 0; + +	if ((!connection && !ssl_session) || !plist) { +		return IPHONE_E_INVALID_ARG; +	} + +	if (binary) { +		plist_to_bin(plist, &content, &length); +	} else { +		plist_to_xml(plist, &content, &length); +	} + +	if (!content || length == 0) { +		return IPHONE_E_PLIST_ERROR; +	} + +	nlen = htonl(length); +	log_debug_msg("%s: sending %d bytes\n", __func__, length); +	if (ssl_session) { +		bytes = gnutls_record_send(ssl_session, (const char*)&nlen, sizeof(nlen)); +	} else { +		iphone_device_send(connection, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); +	} +	if (bytes == sizeof(nlen)) { +		if (ssl_session) { +			bytes = gnutls_record_send(ssl_session, content, length); +		} else { +			iphone_device_send(connection, content, length, (uint32_t*)&bytes); +		} +		if (bytes > 0) { +			log_debug_msg("%s: received %d bytes\n", __func__, bytes); +			log_debug_buffer(content, bytes); +			if ((uint32_t)bytes == length) { +				res = IPHONE_E_SUCCESS; +			} else { +				log_debug_msg("%s: ERROR: Could not send all data (%d of %d)!\n", __func__, bytes, length); +			} +		} +	} +	if (bytes <= 0) { +		log_debug_msg("%s: ERROR: sending to device failed.\n", __func__); +	} + +	free(content); + +	return res; +} + +/** + * Sends an XML plist over the given connection. + * + * @param connection The connection to send data over + * @param plist plist to send + * + * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when connection + *      or plist is NULL, IPHONE_E_PLIST_ERROR when dict is not a valid plist, + *      or IPHONE_E_UNKNOWN_ERROR when an unspecified error occurs. + */ +iphone_error_t iphone_device_send_xml_plist(iphone_connection_t connection, plist_t plist) +{ +	return internal_plist_send(connection, plist, 0, NULL); +} + +/** + * Sends a binary plist over the given connection. + * + * @param connection The connection to send data over + * @param plist plist to send + * + * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when connection + *      or plist is NULL, IPHONE_E_PLIST_ERROR when dict is not a valid plist, + *      or IPHONE_E_UNKNOWN_ERROR when an unspecified error occurs. + */ +iphone_error_t iphone_device_send_binary_plist(iphone_connection_t connection, plist_t plist) +{ +	return internal_plist_send(connection, plist, 1, NULL); +} + +/** + * Sends an encrypted XML plist. + * + * @param ssl_session Valid and properly initialized gnutls_session_t. + * @param plist plist to send + * + * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when ssl_session + *      or plist is NULL, IPHONE_E_PLIST_ERROR when dict is not a valid plist, + *      or IPHONE_E_UNKNOWN_ERROR when an unspecified error occurs. + */ +iphone_error_t iphone_device_send_encrypted_xml_plist(gnutls_session_t ssl_session, plist_t plist) +{ +	return internal_plist_send(NULL, plist, 0, ssl_session); +} + +/** + * Sends an encrypted binary plist. + * + * @param ssl_session Valid and properly initialized gnutls_session_t. + * @param plist plist to send + * + * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when ssl_session + *      or plist is NULL, IPHONE_E_PLIST_ERROR when dict is not a valid plist, + *      or IPHONE_E_UNKNOWN_ERROR when an unspecified error occurs. + */ +iphone_error_t iphone_device_send_encrypted_binary_plist(gnutls_session_t ssl_session, plist_t plist) +{ +	return internal_plist_send(NULL, plist, 1, ssl_session); +} + +/** + * Receives a plist over the given connection.  + * Internally used generic plist send function. + * + * @param connection The connection to receive data on + * @param plist pointer to a plist_t that will point to the received plist + *              upon successful return + * @param timeout Maximum time in milliseconds to wait for data. + * @param ssl_session If set to NULL, the communication will be unencrypted. + *        For encrypted communication, pass a valid and properly initialized + *        gnutls_session_t. + * + * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when connection + *    or *plist is NULL, IPHONE_E_PLIST_ERROR when the received data cannot be + *    converted to a plist, or IPHONE_E_UNKNOWN_ERROR when an unspecified + *    error occurs. + */ +static iphone_error_t internal_plist_recv_timeout(iphone_connection_t connection, plist_t *plist, unsigned int timeout, gnutls_session_t ssl_session) +{ +	iphone_error_t res = IPHONE_E_UNKNOWN_ERROR; +	uint32_t pktlen = 0; +	uint32_t bytes = 0; + +	if ((!connection && !ssl_session) || !plist) { +		return IPHONE_E_INVALID_ARG; +	} + +	iphone_device_recv_timeout(connection, (char*)&pktlen, sizeof(pktlen), &bytes, timeout); +	log_debug_msg("%s: initial read=%i\n", __func__, bytes); +	if (bytes < 4) { +		log_debug_msg("%s: initial read failed!\n", __func__); +		return IPHONE_E_NOT_ENOUGH_DATA; +	} else { +		if ((char)pktlen == 0) { /* prevent huge buffers */ +			uint32_t curlen = 0; +			char *content = NULL; +			pktlen = ntohl(pktlen); +			log_debug_msg("%s: %d bytes following\n", __func__, pktlen); +			content = (char*)malloc(pktlen); + +			while (curlen < pktlen) { +				iphone_device_recv(connection, content+curlen, pktlen-curlen, &bytes); +				if (bytes <= 0) { +					res = IPHONE_E_UNKNOWN_ERROR; +					break; +				} +				log_debug_msg("%s: received %d bytes\n", __func__, bytes); +				curlen += bytes; +			} +			log_debug_buffer(content, pktlen); +			if (!memcmp(content, "bplist00", 8)) { +				plist_from_bin(content, pktlen, plist); +			} else { +				plist_from_xml(content, pktlen, plist); +			} +			if (*plist) { +				res = IPHONE_E_SUCCESS; +			} else { +				res = IPHONE_E_PLIST_ERROR; +			} +			free(content); +			content = NULL; +		} else { +			res = IPHONE_E_UNKNOWN_ERROR; +		} +	} +	return res; +} + +/** + * Receives a plist over the given connection with specified timeout. + * Binary or XML plists are automatically handled. + * + * @param connection The connection to receive data on + * @param plist pointer to a plist_t that will point to the received plist + *              upon successful return + * @param timeout Maximum time in milliseconds to wait for data. + * + * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when connection + *    or *plist is NULL, IPHONE_E_PLIST_ERROR when the received data cannot be + *    converted to a plist, or IPHONE_E_UNKNOWN_ERROR when an unspecified + *    error occurs. + */ +iphone_error_t iphone_device_receive_plist_with_timeout(iphone_connection_t connection, plist_t *plist, unsigned int timeout) +{ +	return internal_plist_recv_timeout(connection, plist, timeout, NULL); +} + +/** + * Receives a plist over the given connection. + * Binary or XML plists are automatically handled. + * + * This function is like iphone_device_receive_plist_with_timeout + *   using a timeout of 10 seconds. + * @see iphone_device_receive_plist_with_timeout + * + * @param connection The connection to receive data on + * @param plist pointer to a plist_t that will point to the received plist + *              upon successful return + * + * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when connection + *    or *plist is NULL, IPHONE_E_PLIST_ERROR when the received data cannot be + *    converted to a plist, or IPHONE_E_UNKNOWN_ERROR when an unspecified + *    error occurs. + */ +iphone_error_t iphone_device_receive_plist(iphone_connection_t connection, plist_t *plist) +{ +	return internal_plist_recv_timeout(connection, plist, 10000, NULL); +} + +/** + * Receives an encrypted plist with specified timeout. + * Binary or XML plists are automatically handled. + * + * @param ssl_session Valid and properly initialized gnutls_session_t. + * @param plist pointer to a plist_t that will point to the received plist + *              upon successful return + * @param timeout Maximum time in milliseconds to wait for data. + * + * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when ssl_session + *    or *plist is NULL, IPHONE_E_PLIST_ERROR when the received data cannot be + *    converted to a plist, or IPHONE_E_UNKNOWN_ERROR when an unspecified + *    error occurs. + */ +iphone_error_t iphone_device_receive_encrypted_plist_with_timeout(gnutls_session_t ssl_session, plist_t *plist, unsigned int timeout) +{ +	return internal_plist_recv_timeout(NULL, plist, timeout, ssl_session); +} + +/** + * Receives an encrypted plist. + * Binary or XML plists are automatically handled. + * This function is like iphone_device_receive_encrypted_plist_with_timeout + *   with a timeout value of 10 seconds. + * + * @param ssl_session Valid and properly initialized gnutls_session_t. + * @param connection The connection to receive data on + * @param plist pointer to a plist_t that will point to the received plist + *              upon successful return + * + * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when ssl_session + *    or *plist is NULL, IPHONE_E_PLIST_ERROR when the received data cannot be + *    converted to a plist, or IPHONE_E_UNKNOWN_ERROR when an unspecified + *    error occurs. + */ +iphone_error_t iphone_device_receive_encrypted_plist(gnutls_session_t ssl_session, plist_t *plist) +{ +	return internal_plist_recv_timeout(NULL, plist, 10000, ssl_session); +} +  iphone_error_t iphone_device_get_handle(iphone_device_t device, uint32_t *handle)  {  	if (!device) diff --git a/src/iphone.h b/src/iphone.h index 98b0ed8..7ffc811 100644 --- a/src/iphone.h +++ b/src/iphone.h @@ -21,6 +21,9 @@  #ifndef IPHONE_H  #define IPHONE_H +#include <plist/plist.h> +#include <gnutls/gnutls.h> +  #include "libiphone/libiphone.h"  enum connection_type { @@ -38,4 +41,14 @@ struct iphone_device_int {  	void *conn_data;  }; +iphone_error_t iphone_device_send_xml_plist(iphone_connection_t connection, plist_t plist); +iphone_error_t iphone_device_send_binary_plist(iphone_connection_t connection, plist_t plist); +iphone_error_t iphone_device_send_encrypted_xml_plist(gnutls_session_t ssl_session, plist_t plist); +iphone_error_t iphone_device_send_encrypted_binary_plist(gnutls_session_t ssl_session, plist_t plist); + +iphone_error_t iphone_device_receive_plist_with_timeout(iphone_connection_t connection, plist_t *plist, unsigned int timeout); +iphone_error_t iphone_device_receive_plist(iphone_connection_t connection, plist_t *plist); +iphone_error_t iphone_device_receive_encrypted_plist_with_timeout(gnutls_session_t ssl_session, plist_t *plist, unsigned int timeout); +iphone_error_t iphone_device_receive_encrypted_plist(gnutls_session_t ssl_session, plist_t *plist); +  #endif diff --git a/src/lockdown.c b/src/lockdown.c index 1b33830..24dd4a1 100644 --- a/src/lockdown.c +++ b/src/lockdown.c @@ -271,61 +271,21 @@ lockdownd_error_t lockdownd_recv(lockdownd_client_t client, plist_t *plist)  {  	if (!client || !plist || (plist && *plist))  		return LOCKDOWN_E_INVALID_ARG; -	lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; -	char *receive = NULL; -	uint32_t datalen = 0, bytes = 0, received_bytes = 0; - -	if (!client->in_SSL) -		ret = iphone_device_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes); -	else { -		ssize_t res = gnutls_record_recv(client->ssl_session, &datalen, sizeof(datalen)); -		if (res < 0) { -			log_dbg_msg(DBGMASK_LOCKDOWND, "gnutls_record_recv: Error occured: %s\n", gnutls_strerror(res)); -			return LOCKDOWN_E_SSL_ERROR; -		} else { -			bytes = res; -			ret = LOCKDOWN_E_SUCCESS; -		} -	} -	datalen = ntohl(datalen); -	log_dbg_msg(DBGMASK_LOCKDOWND, "%s: datalen = %d\n", __func__, datalen); - -	receive = (char *) malloc(sizeof(char) * datalen); +	lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; +	iphone_error_t err; -	/* fill buffer and request more packets if needed */  	if (!client->in_SSL) { -		while ((received_bytes < datalen) && (ret == LOCKDOWN_E_SUCCESS)) { -			ret = iphone_device_recv(client->connection, receive + received_bytes, datalen - received_bytes, &bytes); -			received_bytes += bytes; +		err = iphone_device_receive_plist(client->connection, plist); +		if (err != IPHONE_E_SUCCESS) { +			ret = LOCKDOWN_E_UNKNOWN_ERROR;  		}  	} else { -		ssize_t res = 0; -		while ((received_bytes < datalen) && (ret == LOCKDOWN_E_SUCCESS)) { -			res = gnutls_record_recv(client->ssl_session, receive + received_bytes, datalen - received_bytes); -			if (res < 0) { -				log_dbg_msg(DBGMASK_LOCKDOWND, "gnutls_record_recv: Error occured: %s\n", gnutls_strerror(res)); -				ret = LOCKDOWN_E_SSL_ERROR; -			} else { -				received_bytes += res; -				ret = LOCKDOWN_E_SUCCESS; -			} +		err = iphone_device_receive_encrypted_plist(client->ssl_session, plist); +		if (err != IPHONE_E_SUCCESS) { +			return LOCKDOWN_E_SSL_ERROR;  		}  	} -	if (ret != LOCKDOWN_E_SUCCESS) { -		free(receive); -		return ret; -	} - -	if ((ssize_t)received_bytes <= 0) { -		free(receive); -		return LOCKDOWN_E_NOT_ENOUGH_DATA; -	} - -	log_dbg_msg(DBGMASK_LOCKDOWND, "%s: received msg size: %i, buffer follows:\n%s", __func__, received_bytes, receive); -	plist_from_xml(receive, received_bytes, plist); -	free(receive); -  	if (!*plist)  		ret = LOCKDOWN_E_PLIST_ERROR; @@ -346,41 +306,21 @@ lockdownd_error_t lockdownd_send(lockdownd_client_t client, plist_t plist)  {  	if (!client || !plist)  		return LOCKDOWN_E_INVALID_ARG; -	char *real_query; -	int bytes; -	char *XMLContent = NULL; -	uint32_t length = 0; -	lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; -	plist_to_xml(plist, &XMLContent, &length); -	log_dbg_msg(DBGMASK_LOCKDOWND, "%s: sending msg size %i, buffer follows:\n%s", __func__, length, XMLContent); - -	real_query = (char *) malloc(sizeof(char) * (length + 4)); -	length = htonl(length); -	memcpy(real_query, &length, sizeof(length)); -	memcpy(real_query + 4, XMLContent, ntohl(length)); -	free(XMLContent); -	log_dbg_msg(DBGMASK_LOCKDOWND, "%s: made the query, sending it along\n", __func__); - -	if (!client->in_SSL) -		ret = iphone_device_send(client->connection, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes); -	else { -		ssize_t res = gnutls_record_send(client->ssl_session, real_query, ntohl(length) + sizeof(length)); -		if (res < 0) { -			log_dbg_msg(DBGMASK_LOCKDOWND, "gnutls_record_send: Error occured: %s\n", gnutls_strerror(res)); -			ret = LOCKDOWN_E_SSL_ERROR; -		} else { -			bytes = res; -			ret = LOCKDOWN_E_SUCCESS; +	lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; +	iphone_error_t err; + +	if (!client->in_SSL) { +		err = iphone_device_send_xml_plist(client->connection, plist); +		if (err != IPHONE_E_SUCCESS) { +			ret = LOCKDOWN_E_UNKNOWN_ERROR;  		} -	} -	if (ret == LOCKDOWN_E_SUCCESS) { -		log_dbg_msg(DBGMASK_LOCKDOWND, "%s: sent it!\n", __func__);  	} else { -		log_dbg_msg(DBGMASK_LOCKDOWND, "%s: sending failed!\n", __func__); +		err = iphone_device_send_encrypted_xml_plist(client->ssl_session, plist); +		if (err != IPHONE_E_SUCCESS) { +			ret = LOCKDOWN_E_SSL_ERROR; +		}  	} -	free(real_query); -  	return ret;  } | 
