diff options
| author | 2010-01-13 00:11:43 +0100 | |
|---|---|---|
| committer | 2010-01-13 01:03:03 +0100 | |
| commit | b578398a2883e1e81dbf5bdbd8b8ae917bf9e29d (patch) | |
| tree | 03e25d7cca039f6c97fcaec4891327c6b58e23fe /src/lockdown.c | |
| parent | 65346c9ddd92e6ea3650040d791a411b9ac308af (diff) | |
| download | libimobiledevice-b578398a2883e1e81dbf5bdbd8b8ae917bf9e29d.tar.gz libimobiledevice-b578398a2883e1e81dbf5bdbd8b8ae917bf9e29d.tar.bz2 | |
lockdown/property_list_service: use new SSL code
Diffstat (limited to 'src/lockdown.c')
| -rw-r--r-- | src/lockdown.c | 210 |
1 files changed, 14 insertions, 196 deletions
diff --git a/src/lockdown.c b/src/lockdown.c index 7609426..5568f03 100644 --- a/src/lockdown.c +++ b/src/lockdown.c | |||
| @@ -123,173 +123,6 @@ static void plist_dict_add_label(plist_t plist, const char *label) | |||
| 123 | } | 123 | } |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | /** gnutls callback for writing data to the device. | ||
| 127 | * | ||
| 128 | * @param transport It's really the lockdownd client, but the method signature has to match | ||
| 129 | * @param buffer The data to send | ||
| 130 | * @param length The length of data to send in bytes | ||
| 131 | * | ||
| 132 | * @return The number of bytes sent | ||
| 133 | */ | ||
| 134 | static ssize_t lockdownd_ssl_write(gnutls_transport_ptr_t transport, char *buffer, size_t length) | ||
| 135 | { | ||
| 136 | uint32_t bytes = 0; | ||
| 137 | lockdownd_client_t client; | ||
| 138 | client = (lockdownd_client_t) transport; | ||
| 139 | debug_info("pre-send length = %zi", length); | ||
| 140 | iphone_device_send(property_list_service_get_connection(client->parent), buffer, length, &bytes); | ||
| 141 | debug_info("post-send sent %i bytes", bytes); | ||
| 142 | return bytes; | ||
| 143 | } | ||
| 144 | |||
| 145 | /** gnutls callback for reading data from the device. | ||
| 146 | * | ||
| 147 | * @param transport It's really the lockdownd client, but the method signature has to match | ||
| 148 | * @param buffer The buffer to store data in | ||
| 149 | * @param length The length of data to read in bytes | ||
| 150 | * | ||
| 151 | * @return The number of bytes read | ||
| 152 | */ | ||
| 153 | static ssize_t lockdownd_ssl_read(gnutls_transport_ptr_t transport, char *buffer, size_t length) | ||
| 154 | { | ||
| 155 | int bytes = 0, pos_start_fill = 0; | ||
| 156 | size_t tbytes = 0; | ||
| 157 | int this_len = length; | ||
| 158 | iphone_error_t res; | ||
| 159 | lockdownd_client_t client; | ||
| 160 | client = (lockdownd_client_t) transport; | ||
| 161 | char *recv_buffer; | ||
| 162 | |||
| 163 | debug_info("pre-read client wants %zi bytes", length); | ||
| 164 | |||
| 165 | recv_buffer = (char *) malloc(sizeof(char) * this_len); | ||
| 166 | |||
| 167 | /* repeat until we have the full data or an error occurs */ | ||
| 168 | do { | ||
| 169 | if ((res = iphone_device_recv(property_list_service_get_connection(client->parent), recv_buffer, this_len, (uint32_t*)&bytes)) != LOCKDOWN_E_SUCCESS) { | ||
| 170 | debug_info("ERROR: iphone_device_recv returned %d", res); | ||
| 171 | return res; | ||
| 172 | } | ||
| 173 | debug_info("post-read we got %i bytes", bytes); | ||
| 174 | |||
| 175 | // increase read count | ||
| 176 | tbytes += bytes; | ||
| 177 | |||
| 178 | // fill the buffer with what we got right now | ||
| 179 | memcpy(buffer + pos_start_fill, recv_buffer, bytes); | ||
| 180 | pos_start_fill += bytes; | ||
| 181 | |||
| 182 | if (tbytes >= length) { | ||
| 183 | break; | ||
| 184 | } | ||
| 185 | |||
| 186 | this_len = length - tbytes; | ||
| 187 | debug_info("re-read trying to read missing %i bytes", this_len); | ||
| 188 | } while (tbytes < length); | ||
| 189 | |||
| 190 | if (recv_buffer) { | ||
| 191 | free(recv_buffer); | ||
| 192 | } | ||
| 193 | |||
| 194 | return tbytes; | ||
| 195 | } | ||
| 196 | |||
| 197 | /** Starts communication with lockdownd after the iPhone has been paired, | ||
| 198 | * and if the device requires it, switches to SSL mode. | ||
| 199 | * | ||
| 200 | * @param client The lockdownd client | ||
| 201 | * | ||
| 202 | * @return an error code (LOCKDOWN_E_SUCCESS on success) | ||
| 203 | */ | ||
| 204 | static lockdownd_error_t lockdownd_ssl_start_session(lockdownd_client_t client) | ||
| 205 | { | ||
| 206 | lockdownd_error_t ret = LOCKDOWN_E_SSL_ERROR; | ||
| 207 | uint32_t return_me = 0; | ||
| 208 | |||
| 209 | // Set up GnuTLS... | ||
| 210 | debug_info("enabling SSL mode"); | ||
| 211 | errno = 0; | ||
| 212 | gnutls_global_init(); | ||
| 213 | gnutls_certificate_allocate_credentials(&client->ssl_certificate); | ||
| 214 | gnutls_certificate_set_x509_trust_file(client->ssl_certificate, "hostcert.pem", GNUTLS_X509_FMT_PEM); | ||
| 215 | gnutls_init(&client->ssl_session, GNUTLS_CLIENT); | ||
| 216 | { | ||
| 217 | int protocol_priority[16] = { GNUTLS_SSL3, 0 }; | ||
| 218 | int kx_priority[16] = { GNUTLS_KX_ANON_DH, GNUTLS_KX_RSA, 0 }; | ||
| 219 | int cipher_priority[16] = { GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_AES_256_CBC, 0 }; | ||
| 220 | int mac_priority[16] = { GNUTLS_MAC_SHA1, GNUTLS_MAC_MD5, 0 }; | ||
| 221 | int comp_priority[16] = { GNUTLS_COMP_NULL, 0 }; | ||
| 222 | |||
| 223 | gnutls_cipher_set_priority(client->ssl_session, cipher_priority); | ||
| 224 | gnutls_compression_set_priority(client->ssl_session, comp_priority); | ||
| 225 | gnutls_kx_set_priority(client->ssl_session, kx_priority); | ||
| 226 | gnutls_protocol_set_priority(client->ssl_session, protocol_priority); | ||
| 227 | gnutls_mac_set_priority(client->ssl_session, mac_priority); | ||
| 228 | } | ||
| 229 | gnutls_credentials_set(client->ssl_session, GNUTLS_CRD_CERTIFICATE, client->ssl_certificate); // this part is killing me. | ||
| 230 | |||
| 231 | debug_info("GnuTLS step 1..."); | ||
| 232 | gnutls_transport_set_ptr(client->ssl_session, (gnutls_transport_ptr_t) client); | ||
| 233 | debug_info("GnuTLS step 2..."); | ||
| 234 | gnutls_transport_set_push_function(client->ssl_session, (gnutls_push_func) & lockdownd_ssl_write); | ||
| 235 | debug_info("GnuTLS step 3..."); | ||
| 236 | gnutls_transport_set_pull_function(client->ssl_session, (gnutls_pull_func) & lockdownd_ssl_read); | ||
| 237 | debug_info("GnuTLS step 4 -- now handshaking..."); | ||
| 238 | if (errno) | ||
| 239 | debug_info("WARN: errno says %s before handshake!", strerror(errno)); | ||
| 240 | return_me = gnutls_handshake(client->ssl_session); | ||
| 241 | debug_info("GnuTLS handshake done..."); | ||
| 242 | |||
| 243 | if (return_me != GNUTLS_E_SUCCESS) { | ||
| 244 | debug_info("GnuTLS reported something wrong."); | ||
| 245 | gnutls_perror(return_me); | ||
| 246 | debug_info("oh.. errno says %s", strerror(errno)); | ||
| 247 | } else { | ||
| 248 | client->ssl_enabled = 1; | ||
| 249 | ret = LOCKDOWN_E_SUCCESS; | ||
| 250 | debug_info("SSL mode enabled"); | ||
| 251 | } | ||
| 252 | |||
| 253 | return ret; | ||
| 254 | } | ||
| 255 | |||
| 256 | /** | ||
| 257 | * Shuts down the SSL session by performing a close notify, which is done | ||
| 258 | * by "gnutls_bye". | ||
| 259 | * | ||
| 260 | * @param client The lockdown client | ||
| 261 | * | ||
| 262 | * @return an error code (LOCKDOWN_E_SUCCESS on success) | ||
| 263 | */ | ||
| 264 | static lockdownd_error_t lockdownd_ssl_stop_session(lockdownd_client_t client) | ||
| 265 | { | ||
| 266 | if (!client) { | ||
| 267 | debug_info("invalid argument!"); | ||
| 268 | return LOCKDOWN_E_INVALID_ARG; | ||
| 269 | } | ||
| 270 | lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; | ||
| 271 | |||
| 272 | if (client->ssl_enabled) { | ||
| 273 | debug_info("sending SSL close notify"); | ||
| 274 | gnutls_bye(client->ssl_session, GNUTLS_SHUT_RDWR); | ||
| 275 | } | ||
| 276 | if (client->ssl_session) { | ||
| 277 | gnutls_deinit(client->ssl_session); | ||
| 278 | } | ||
| 279 | if (client->ssl_certificate) { | ||
| 280 | gnutls_certificate_free_credentials(client->ssl_certificate); | ||
| 281 | } | ||
| 282 | client->ssl_enabled = 0; | ||
| 283 | |||
| 284 | if (client->session_id) | ||
| 285 | free(client->session_id); | ||
| 286 | client->session_id = NULL; | ||
| 287 | |||
| 288 | debug_info("SSL mode disabled"); | ||
| 289 | |||
| 290 | return ret; | ||
| 291 | } | ||
| 292 | |||
| 293 | /** | 126 | /** |
| 294 | * Closes the lockdownd communication session, by sending the StopSession | 127 | * Closes the lockdownd communication session, by sending the StopSession |
| 295 | * Request to the device. | 128 | * Request to the device. |
| @@ -339,10 +172,9 @@ lockdownd_error_t lockdownd_stop_session(lockdownd_client_t client, const char * | |||
| 339 | } | 172 | } |
| 340 | plist_free(dict); | 173 | plist_free(dict); |
| 341 | dict = NULL; | 174 | dict = NULL; |
| 342 | 175 | if (client->ssl_enabled) { | |
| 343 | /* stop ssl session */ | 176 | property_list_service_disable_ssl(client->parent); |
| 344 | lockdownd_ssl_stop_session(client); | 177 | } |
| 345 | |||
| 346 | return ret; | 178 | return ret; |
| 347 | } | 179 | } |
| 348 | 180 | ||
| @@ -411,16 +243,9 @@ lockdownd_error_t lockdownd_recv(lockdownd_client_t client, plist_t *plist) | |||
| 411 | lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; | 243 | lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; |
| 412 | property_list_service_error_t err; | 244 | property_list_service_error_t err; |
| 413 | 245 | ||
| 414 | if (!client->ssl_enabled) { | 246 | err = property_list_service_receive_plist(client->parent, plist); |
| 415 | err = property_list_service_receive_plist(client->parent, plist); | 247 | if (err != PROPERTY_LIST_SERVICE_E_SUCCESS) { |
| 416 | if (err != PROPERTY_LIST_SERVICE_E_SUCCESS) { | 248 | ret = LOCKDOWN_E_UNKNOWN_ERROR; |
| 417 | ret = LOCKDOWN_E_UNKNOWN_ERROR; | ||
| 418 | } | ||
| 419 | } else { | ||
| 420 | err = property_list_service_receive_encrypted_plist(client->ssl_session, plist); | ||
| 421 | if (err != PROPERTY_LIST_SERVICE_E_SUCCESS) { | ||
| 422 | return LOCKDOWN_E_SSL_ERROR; | ||
| 423 | } | ||
| 424 | } | 249 | } |
| 425 | 250 | ||
| 426 | if (!*plist) | 251 | if (!*plist) |
| @@ -447,16 +272,9 @@ lockdownd_error_t lockdownd_send(lockdownd_client_t client, plist_t plist) | |||
| 447 | lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; | 272 | lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; |
| 448 | iphone_error_t err; | 273 | iphone_error_t err; |
| 449 | 274 | ||
| 450 | if (!client->ssl_enabled) { | 275 | err = property_list_service_send_xml_plist(client->parent, plist); |
| 451 | err = property_list_service_send_xml_plist(client->parent, plist); | 276 | if (err != PROPERTY_LIST_SERVICE_E_SUCCESS) { |
| 452 | if (err != PROPERTY_LIST_SERVICE_E_SUCCESS) { | 277 | ret = LOCKDOWN_E_UNKNOWN_ERROR; |
| 453 | ret = LOCKDOWN_E_UNKNOWN_ERROR; | ||
| 454 | } | ||
| 455 | } else { | ||
| 456 | err = property_list_service_send_encrypted_xml_plist(client->ssl_session, plist); | ||
| 457 | if (err != PROPERTY_LIST_SERVICE_E_SUCCESS) { | ||
| 458 | ret = LOCKDOWN_E_SSL_ERROR; | ||
| 459 | } | ||
| 460 | } | 278 | } |
| 461 | return ret; | 279 | return ret; |
| 462 | } | 280 | } |
| @@ -775,8 +593,6 @@ lockdownd_error_t lockdownd_client_new(iphone_device_t device, lockdownd_client_ | |||
| 775 | 593 | ||
| 776 | lockdownd_client_t client_loc = (lockdownd_client_t) malloc(sizeof(struct lockdownd_client_int)); | 594 | lockdownd_client_t client_loc = (lockdownd_client_t) malloc(sizeof(struct lockdownd_client_int)); |
| 777 | client_loc->parent = plistclient; | 595 | client_loc->parent = plistclient; |
| 778 | client_loc->ssl_session = NULL; | ||
| 779 | client_loc->ssl_certificate = NULL; | ||
| 780 | client_loc->ssl_enabled = 0; | 596 | client_loc->ssl_enabled = 0; |
| 781 | client_loc->session_id = NULL; | 597 | client_loc->session_id = NULL; |
| 782 | client_loc->uuid = NULL; | 598 | client_loc->uuid = NULL; |
| @@ -848,8 +664,7 @@ lockdownd_error_t lockdownd_client_new_with_handshake(iphone_device_t device, lo | |||
| 848 | if (LOCKDOWN_E_SUCCESS == ret) { | 664 | if (LOCKDOWN_E_SUCCESS == ret) { |
| 849 | ret = lockdownd_start_session(client_loc, host_id, NULL, NULL); | 665 | ret = lockdownd_start_session(client_loc, host_id, NULL, NULL); |
| 850 | if (LOCKDOWN_E_SUCCESS != ret) { | 666 | if (LOCKDOWN_E_SUCCESS != ret) { |
| 851 | ret = LOCKDOWN_E_SSL_ERROR; | 667 | debug_info("Session opening failed."); |
| 852 | debug_info("SSL Session opening failed."); | ||
| 853 | } | 668 | } |
| 854 | 669 | ||
| 855 | if (host_id) { | 670 | if (host_id) { |
| @@ -1313,7 +1128,10 @@ lockdownd_error_t lockdownd_start_session(lockdownd_client_t client, const char | |||
| 1313 | } | 1128 | } |
| 1314 | debug_info("Enable SSL Session: %s", (use_ssl?"true":"false")); | 1129 | debug_info("Enable SSL Session: %s", (use_ssl?"true":"false")); |
| 1315 | if (use_ssl) { | 1130 | if (use_ssl) { |
| 1316 | ret = lockdownd_ssl_start_session(client); | 1131 | ret = property_list_service_enable_ssl(client->parent); |
| 1132 | if (ret == PROPERTY_LIST_SERVICE_E_SUCCESS) { | ||
| 1133 | client->ssl_enabled = 1; | ||
| 1134 | } | ||
| 1317 | } else { | 1135 | } else { |
| 1318 | client->ssl_enabled = 0; | 1136 | client->ssl_enabled = 0; |
| 1319 | ret = LOCKDOWN_E_SUCCESS; | 1137 | ret = LOCKDOWN_E_SUCCESS; |
