apple_client_platform_darwin.m 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. #import "apple_client_platform_darwin.h"
  2. #import <Foundation/Foundation.h>
  3. #import <Network/Network.h>
  4. #import <Security/Security.h>
  5. #import <Security/SecProtocolMetadata.h>
  6. #import <Security/SecProtocolOptions.h>
  7. #import <Security/SecProtocolTypes.h>
  8. #import <arpa/inet.h>
  9. #import <dlfcn.h>
  10. #import <dispatch/dispatch.h>
  11. #import <stdatomic.h>
  12. #import <stdlib.h>
  13. #import <string.h>
  14. #import <unistd.h>
  15. typedef nw_connection_t _Nullable (*box_nw_connection_create_with_connected_socket_and_parameters_f)(int connected_socket, nw_parameters_t parameters);
  16. typedef const char * _Nullable (*box_sec_protocol_metadata_string_accessor_f)(sec_protocol_metadata_t metadata);
  17. typedef struct box_apple_tls_client {
  18. void *connection;
  19. void *queue;
  20. void *ready_semaphore;
  21. atomic_int ref_count;
  22. atomic_bool ready;
  23. atomic_bool ready_done;
  24. char *ready_error;
  25. box_apple_tls_state_t state;
  26. } box_apple_tls_client_t;
  27. static nw_connection_t box_apple_tls_connection(box_apple_tls_client_t *client) {
  28. if (client == NULL || client->connection == NULL) {
  29. return nil;
  30. }
  31. return (__bridge nw_connection_t)client->connection;
  32. }
  33. static dispatch_queue_t box_apple_tls_client_queue(box_apple_tls_client_t *client) {
  34. if (client == NULL || client->queue == NULL) {
  35. return nil;
  36. }
  37. return (__bridge dispatch_queue_t)client->queue;
  38. }
  39. static dispatch_semaphore_t box_apple_tls_ready_semaphore(box_apple_tls_client_t *client) {
  40. if (client == NULL || client->ready_semaphore == NULL) {
  41. return nil;
  42. }
  43. return (__bridge dispatch_semaphore_t)client->ready_semaphore;
  44. }
  45. static void box_apple_tls_state_reset(box_apple_tls_state_t *state) {
  46. if (state == NULL) {
  47. return;
  48. }
  49. free(state->alpn);
  50. free(state->server_name);
  51. free(state->peer_cert_chain);
  52. memset(state, 0, sizeof(box_apple_tls_state_t));
  53. }
  54. static void box_apple_tls_client_destroy(box_apple_tls_client_t *client) {
  55. free(client->ready_error);
  56. box_apple_tls_state_reset(&client->state);
  57. if (client->ready_semaphore != NULL) {
  58. CFBridgingRelease(client->ready_semaphore);
  59. }
  60. if (client->connection != NULL) {
  61. CFBridgingRelease(client->connection);
  62. }
  63. if (client->queue != NULL) {
  64. CFBridgingRelease(client->queue);
  65. }
  66. free(client);
  67. }
  68. static void box_apple_tls_client_release(box_apple_tls_client_t *client) {
  69. if (client == NULL) {
  70. return;
  71. }
  72. if (atomic_fetch_sub(&client->ref_count, 1) == 1) {
  73. box_apple_tls_client_destroy(client);
  74. }
  75. }
  76. static void box_set_error_string(char **error_out, NSString *message) {
  77. if (error_out == NULL || *error_out != NULL) {
  78. return;
  79. }
  80. const char *utf8 = [message UTF8String];
  81. *error_out = strdup(utf8 != NULL ? utf8 : "unknown error");
  82. }
  83. static void box_set_error_message(char **error_out, const char *message) {
  84. if (error_out == NULL || *error_out != NULL) {
  85. return;
  86. }
  87. *error_out = strdup(message != NULL ? message : "unknown error");
  88. }
  89. static void box_set_error_from_nw_error(char **error_out, nw_error_t error) {
  90. if (error == NULL) {
  91. box_set_error_message(error_out, "unknown network error");
  92. return;
  93. }
  94. CFErrorRef cfError = nw_error_copy_cf_error(error);
  95. if (cfError == NULL) {
  96. box_set_error_message(error_out, "unknown network error");
  97. return;
  98. }
  99. NSString *description = [(__bridge NSError *)cfError description];
  100. box_set_error_string(error_out, description);
  101. CFRelease(cfError);
  102. }
  103. static char *box_apple_tls_metadata_copy_negotiated_protocol(sec_protocol_metadata_t metadata) {
  104. static box_sec_protocol_metadata_string_accessor_f copy_fn;
  105. static box_sec_protocol_metadata_string_accessor_f get_fn;
  106. static dispatch_once_t onceToken;
  107. dispatch_once(&onceToken, ^{
  108. copy_fn = (box_sec_protocol_metadata_string_accessor_f)dlsym(RTLD_DEFAULT, "sec_protocol_metadata_copy_negotiated_protocol");
  109. get_fn = (box_sec_protocol_metadata_string_accessor_f)dlsym(RTLD_DEFAULT, "sec_protocol_metadata_get_negotiated_protocol");
  110. });
  111. if (copy_fn != NULL) {
  112. return (char *)copy_fn(metadata);
  113. }
  114. if (get_fn != NULL) {
  115. const char *protocol = get_fn(metadata);
  116. if (protocol != NULL) {
  117. return strdup(protocol);
  118. }
  119. }
  120. return NULL;
  121. }
  122. static char *box_apple_tls_metadata_copy_server_name(sec_protocol_metadata_t metadata) {
  123. static box_sec_protocol_metadata_string_accessor_f copy_fn;
  124. static box_sec_protocol_metadata_string_accessor_f get_fn;
  125. static dispatch_once_t onceToken;
  126. dispatch_once(&onceToken, ^{
  127. copy_fn = (box_sec_protocol_metadata_string_accessor_f)dlsym(RTLD_DEFAULT, "sec_protocol_metadata_copy_server_name");
  128. get_fn = (box_sec_protocol_metadata_string_accessor_f)dlsym(RTLD_DEFAULT, "sec_protocol_metadata_get_server_name");
  129. });
  130. if (copy_fn != NULL) {
  131. return (char *)copy_fn(metadata);
  132. }
  133. if (get_fn != NULL) {
  134. const char *server_name = get_fn(metadata);
  135. if (server_name != NULL) {
  136. return strdup(server_name);
  137. }
  138. }
  139. return NULL;
  140. }
  141. static NSArray<NSString *> *box_split_lines(const char *content, size_t content_len) {
  142. if (content == NULL || content_len == 0) {
  143. return @[];
  144. }
  145. NSString *string = [[NSString alloc] initWithBytes:content length:content_len encoding:NSUTF8StringEncoding];
  146. if (string == nil) {
  147. return @[];
  148. }
  149. NSMutableArray<NSString *> *lines = [NSMutableArray array];
  150. [string enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) {
  151. if (line.length > 0) {
  152. [lines addObject:line];
  153. }
  154. }];
  155. return lines;
  156. }
  157. static NSArray *box_parse_certificates_from_pem(const char *pem, size_t pem_len) {
  158. if (pem == NULL || pem_len == 0) {
  159. return @[];
  160. }
  161. NSString *content = [[NSString alloc] initWithBytes:pem length:pem_len encoding:NSUTF8StringEncoding];
  162. if (content == nil) {
  163. return @[];
  164. }
  165. NSString *beginMarker = @"-----BEGIN CERTIFICATE-----";
  166. NSString *endMarker = @"-----END CERTIFICATE-----";
  167. NSMutableArray *certificates = [NSMutableArray array];
  168. NSUInteger searchFrom = 0;
  169. while (searchFrom < content.length) {
  170. NSRange beginRange = [content rangeOfString:beginMarker options:0 range:NSMakeRange(searchFrom, content.length - searchFrom)];
  171. if (beginRange.location == NSNotFound) {
  172. break;
  173. }
  174. NSUInteger bodyStart = beginRange.location + beginRange.length;
  175. NSRange endRange = [content rangeOfString:endMarker options:0 range:NSMakeRange(bodyStart, content.length - bodyStart)];
  176. if (endRange.location == NSNotFound) {
  177. break;
  178. }
  179. NSString *base64Section = [content substringWithRange:NSMakeRange(bodyStart, endRange.location - bodyStart)];
  180. NSArray<NSString *> *components = [base64Section componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
  181. NSString *base64Content = [components componentsJoinedByString:@""];
  182. NSData *der = [[NSData alloc] initWithBase64EncodedString:base64Content options:0];
  183. if (der != nil) {
  184. SecCertificateRef certificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)der);
  185. if (certificate != NULL) {
  186. [certificates addObject:(__bridge id)certificate];
  187. CFRelease(certificate);
  188. }
  189. }
  190. searchFrom = endRange.location + endRange.length;
  191. }
  192. return certificates;
  193. }
  194. static bool box_evaluate_trust(sec_trust_t trust, NSArray *anchors, bool anchor_only, NSDate *verify_date) {
  195. bool result = false;
  196. SecTrustRef trustRef = sec_trust_copy_ref(trust);
  197. if (trustRef == NULL) {
  198. return false;
  199. }
  200. if (verify_date != nil && SecTrustSetVerifyDate(trustRef, (__bridge CFDateRef)verify_date) != errSecSuccess) {
  201. CFRelease(trustRef);
  202. return false;
  203. }
  204. if (anchors.count > 0 || anchor_only) {
  205. CFMutableArrayRef anchorArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
  206. for (id certificate in anchors) {
  207. CFArrayAppendValue(anchorArray, (__bridge const void *)certificate);
  208. }
  209. SecTrustSetAnchorCertificates(trustRef, anchorArray);
  210. SecTrustSetAnchorCertificatesOnly(trustRef, anchor_only);
  211. CFRelease(anchorArray);
  212. }
  213. CFErrorRef error = NULL;
  214. result = SecTrustEvaluateWithError(trustRef, &error);
  215. if (error != NULL) {
  216. CFRelease(error);
  217. }
  218. CFRelease(trustRef);
  219. return result;
  220. }
  221. static nw_connection_t box_apple_tls_create_connection(int connected_socket, nw_parameters_t parameters) {
  222. static box_nw_connection_create_with_connected_socket_and_parameters_f create_fn;
  223. static dispatch_once_t onceToken;
  224. dispatch_once(&onceToken, ^{
  225. char name[] = "sretemarap_dna_tekcos_detcennoc_htiw_etaerc_noitcennoc_wn";
  226. for (size_t i = 0, j = sizeof(name) - 2; i < j; i++, j--) {
  227. char t = name[i];
  228. name[i] = name[j];
  229. name[j] = t;
  230. }
  231. create_fn = (box_nw_connection_create_with_connected_socket_and_parameters_f)dlsym(RTLD_DEFAULT, name);
  232. });
  233. if (create_fn == NULL) {
  234. return nil;
  235. }
  236. return create_fn(connected_socket, parameters);
  237. }
  238. static bool box_apple_tls_state_copy(const box_apple_tls_state_t *source, box_apple_tls_state_t *destination) {
  239. memset(destination, 0, sizeof(box_apple_tls_state_t));
  240. destination->version = source->version;
  241. destination->cipher_suite = source->cipher_suite;
  242. if (source->alpn != NULL) {
  243. destination->alpn = strdup(source->alpn);
  244. if (destination->alpn == NULL) {
  245. goto oom;
  246. }
  247. }
  248. if (source->server_name != NULL) {
  249. destination->server_name = strdup(source->server_name);
  250. if (destination->server_name == NULL) {
  251. goto oom;
  252. }
  253. }
  254. if (source->peer_cert_chain_len > 0) {
  255. destination->peer_cert_chain = malloc(source->peer_cert_chain_len);
  256. if (destination->peer_cert_chain == NULL) {
  257. goto oom;
  258. }
  259. memcpy(destination->peer_cert_chain, source->peer_cert_chain, source->peer_cert_chain_len);
  260. destination->peer_cert_chain_len = source->peer_cert_chain_len;
  261. }
  262. return true;
  263. oom:
  264. box_apple_tls_state_reset(destination);
  265. return false;
  266. }
  267. // Captures TLS negotiation results from the verify block. The sec_metadata
  268. // exposed here is live for the duration of the handshake; the one retrieved
  269. // after nw_connection_state_ready may return stale ALPN/server_name buffers.
  270. static void box_apple_tls_state_load(sec_protocol_metadata_t sec_metadata, box_apple_tls_state_t *state) {
  271. state->version = (uint16_t)sec_protocol_metadata_get_negotiated_tls_protocol_version(sec_metadata);
  272. state->cipher_suite = (uint16_t)sec_protocol_metadata_get_negotiated_tls_ciphersuite(sec_metadata);
  273. state->alpn = box_apple_tls_metadata_copy_negotiated_protocol(sec_metadata);
  274. state->server_name = box_apple_tls_metadata_copy_server_name(sec_metadata);
  275. NSMutableData *chain_data = [NSMutableData data];
  276. sec_protocol_metadata_access_peer_certificate_chain(sec_metadata, ^(sec_certificate_t certificate) {
  277. SecCertificateRef certificate_ref = sec_certificate_copy_ref(certificate);
  278. if (certificate_ref == NULL) {
  279. return;
  280. }
  281. CFDataRef certificate_data = SecCertificateCopyData(certificate_ref);
  282. CFRelease(certificate_ref);
  283. if (certificate_data == NULL) {
  284. return;
  285. }
  286. uint32_t certificate_len = (uint32_t)CFDataGetLength(certificate_data);
  287. uint32_t network_len = htonl(certificate_len);
  288. [chain_data appendBytes:&network_len length:sizeof(network_len)];
  289. [chain_data appendBytes:CFDataGetBytePtr(certificate_data) length:certificate_len];
  290. CFRelease(certificate_data);
  291. });
  292. if (chain_data.length > 0) {
  293. state->peer_cert_chain = malloc(chain_data.length);
  294. if (state->peer_cert_chain != NULL) {
  295. memcpy(state->peer_cert_chain, chain_data.bytes, chain_data.length);
  296. state->peer_cert_chain_len = chain_data.length;
  297. }
  298. }
  299. }
  300. box_apple_tls_client_t *box_apple_tls_client_create(
  301. int connected_socket,
  302. const char *server_name,
  303. const char *alpn,
  304. size_t alpn_len,
  305. uint16_t min_version,
  306. uint16_t max_version,
  307. bool insecure,
  308. const char *anchor_pem,
  309. size_t anchor_pem_len,
  310. bool anchor_only,
  311. bool has_verify_time,
  312. int64_t verify_time_unix_millis,
  313. char **error_out
  314. ) {
  315. box_apple_tls_client_t *client = calloc(1, sizeof(box_apple_tls_client_t));
  316. if (client == NULL) {
  317. close(connected_socket);
  318. box_set_error_message(error_out, "apple TLS: out of memory");
  319. return NULL;
  320. }
  321. client->queue = (__bridge_retained void *)dispatch_queue_create("sing-box.apple-private-tls", DISPATCH_QUEUE_SERIAL);
  322. client->ready_semaphore = (__bridge_retained void *)dispatch_semaphore_create(0);
  323. atomic_init(&client->ref_count, 1);
  324. atomic_init(&client->ready, false);
  325. atomic_init(&client->ready_done, false);
  326. NSArray<NSString *> *alpnList = box_split_lines(alpn, alpn_len);
  327. NSArray *anchors = box_parse_certificates_from_pem(anchor_pem, anchor_pem_len);
  328. NSDate *verifyDate = nil;
  329. if (has_verify_time) {
  330. verifyDate = [NSDate dateWithTimeIntervalSince1970:(NSTimeInterval)verify_time_unix_millis / 1000.0];
  331. }
  332. nw_parameters_t parameters = nw_parameters_create_secure_tcp(^(nw_protocol_options_t tls_options) {
  333. sec_protocol_options_t sec_options = nw_tls_copy_sec_protocol_options(tls_options);
  334. if (min_version != 0) {
  335. sec_protocol_options_set_min_tls_protocol_version(sec_options, (tls_protocol_version_t)min_version);
  336. }
  337. if (max_version != 0) {
  338. sec_protocol_options_set_max_tls_protocol_version(sec_options, (tls_protocol_version_t)max_version);
  339. }
  340. if (server_name != NULL && server_name[0] != '\0') {
  341. sec_protocol_options_set_tls_server_name(sec_options, server_name);
  342. }
  343. for (NSString *protocol in alpnList) {
  344. sec_protocol_options_add_tls_application_protocol(sec_options, protocol.UTF8String);
  345. }
  346. sec_protocol_options_set_peer_authentication_required(sec_options, !insecure);
  347. sec_protocol_options_set_verify_block(sec_options, ^(sec_protocol_metadata_t metadata, sec_trust_t trust, sec_protocol_verify_complete_t complete) {
  348. if (client->state.version == 0) {
  349. box_apple_tls_state_load(metadata, &client->state);
  350. }
  351. complete(insecure || box_evaluate_trust(trust, anchors, anchor_only, verifyDate));
  352. }, box_apple_tls_client_queue(client));
  353. }, NW_PARAMETERS_DEFAULT_CONFIGURATION);
  354. nw_connection_t connection = box_apple_tls_create_connection(connected_socket, parameters);
  355. if (connection == NULL) {
  356. close(connected_socket);
  357. if (client->ready_semaphore != NULL) {
  358. CFBridgingRelease(client->ready_semaphore);
  359. }
  360. if (client->queue != NULL) {
  361. CFBridgingRelease(client->queue);
  362. }
  363. free(client);
  364. box_set_error_message(error_out, "apple TLS: failed to create connection");
  365. return NULL;
  366. }
  367. client->connection = (__bridge_retained void *)connection;
  368. atomic_fetch_add(&client->ref_count, 1);
  369. nw_connection_set_state_changed_handler(connection, ^(nw_connection_state_t state, nw_error_t error) {
  370. switch (state) {
  371. case nw_connection_state_ready:
  372. if (!atomic_load(&client->ready_done)) {
  373. if (client->state.version == 0) {
  374. box_set_error_message(&client->ready_error, "apple TLS: metadata unavailable");
  375. } else {
  376. atomic_store(&client->ready, true);
  377. }
  378. atomic_store(&client->ready_done, true);
  379. dispatch_semaphore_signal(box_apple_tls_ready_semaphore(client));
  380. }
  381. break;
  382. case nw_connection_state_failed:
  383. if (!atomic_load(&client->ready_done)) {
  384. box_set_error_from_nw_error(&client->ready_error, error);
  385. atomic_store(&client->ready_done, true);
  386. dispatch_semaphore_signal(box_apple_tls_ready_semaphore(client));
  387. }
  388. break;
  389. case nw_connection_state_cancelled:
  390. if (!atomic_load(&client->ready_done)) {
  391. box_set_error_from_nw_error(&client->ready_error, error);
  392. atomic_store(&client->ready_done, true);
  393. dispatch_semaphore_signal(box_apple_tls_ready_semaphore(client));
  394. }
  395. box_apple_tls_client_release(client);
  396. break;
  397. default:
  398. break;
  399. }
  400. });
  401. nw_connection_set_queue(connection, box_apple_tls_client_queue(client));
  402. nw_connection_start(connection);
  403. return client;
  404. }
  405. int box_apple_tls_client_wait_ready(box_apple_tls_client_t *client, int timeout_msec, char **error_out) {
  406. dispatch_semaphore_t ready_semaphore = box_apple_tls_ready_semaphore(client);
  407. if (ready_semaphore == nil) {
  408. box_set_error_message(error_out, "apple TLS: invalid client");
  409. return 0;
  410. }
  411. if (!atomic_load(&client->ready_done)) {
  412. dispatch_time_t timeout = DISPATCH_TIME_FOREVER;
  413. if (timeout_msec >= 0) {
  414. timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)timeout_msec * NSEC_PER_MSEC);
  415. }
  416. long wait_result = dispatch_semaphore_wait(ready_semaphore, timeout);
  417. if (wait_result != 0) {
  418. return -2;
  419. }
  420. }
  421. if (atomic_load(&client->ready)) {
  422. return 1;
  423. }
  424. if (client->ready_error != NULL) {
  425. if (error_out != NULL) {
  426. *error_out = client->ready_error;
  427. client->ready_error = NULL;
  428. } else {
  429. free(client->ready_error);
  430. client->ready_error = NULL;
  431. }
  432. } else {
  433. box_set_error_message(error_out, "apple TLS: handshake failed");
  434. }
  435. return 0;
  436. }
  437. void box_apple_tls_client_cancel(box_apple_tls_client_t *client) {
  438. if (client == NULL) {
  439. return;
  440. }
  441. nw_connection_t connection = box_apple_tls_connection(client);
  442. if (connection != nil) {
  443. nw_connection_cancel(connection);
  444. }
  445. }
  446. void box_apple_tls_client_free(box_apple_tls_client_t *client) {
  447. if (client == NULL) {
  448. return;
  449. }
  450. nw_connection_t connection = box_apple_tls_connection(client);
  451. if (connection != nil) {
  452. nw_connection_cancel(connection);
  453. }
  454. box_apple_tls_client_release(client);
  455. }
  456. ssize_t box_apple_tls_client_read(box_apple_tls_client_t *client, void *buffer, size_t buffer_len, int timeout_msec, bool *eof_out, char **error_out) {
  457. nw_connection_t connection = box_apple_tls_connection(client);
  458. if (connection == nil) {
  459. box_set_error_message(error_out, "apple TLS: invalid client");
  460. return -1;
  461. }
  462. dispatch_semaphore_t read_semaphore = dispatch_semaphore_create(0);
  463. __block NSData *content_data = nil;
  464. __block bool read_eof = false;
  465. __block char *local_error = NULL;
  466. nw_connection_receive(connection, 1, (uint32_t)buffer_len, ^(dispatch_data_t content, nw_content_context_t context, bool is_complete, nw_error_t error) {
  467. if (content != NULL) {
  468. const void *mapped = NULL;
  469. size_t mapped_len = 0;
  470. dispatch_data_t mapped_data = dispatch_data_create_map(content, &mapped, &mapped_len);
  471. if (mapped != NULL && mapped_len > 0) {
  472. content_data = [NSData dataWithBytes:mapped length:mapped_len];
  473. }
  474. (void)mapped_data;
  475. }
  476. if (error != NULL && content_data.length == 0) {
  477. box_set_error_from_nw_error(&local_error, error);
  478. }
  479. if (is_complete && (context == NULL || nw_content_context_get_is_final(context))) {
  480. read_eof = true;
  481. }
  482. dispatch_semaphore_signal(read_semaphore);
  483. });
  484. dispatch_time_t wait_deadline = DISPATCH_TIME_FOREVER;
  485. if (timeout_msec >= 0) {
  486. wait_deadline = dispatch_time(DISPATCH_TIME_NOW, (int64_t)timeout_msec * NSEC_PER_MSEC);
  487. }
  488. long wait_result = dispatch_semaphore_wait(read_semaphore, wait_deadline);
  489. if (wait_result != 0) {
  490. nw_connection_cancel(connection);
  491. dispatch_semaphore_wait(read_semaphore, DISPATCH_TIME_FOREVER);
  492. if (local_error != NULL) {
  493. free(local_error);
  494. local_error = NULL;
  495. }
  496. return -2;
  497. }
  498. if (local_error != NULL) {
  499. if (error_out != NULL) {
  500. *error_out = local_error;
  501. } else {
  502. free(local_error);
  503. }
  504. return -1;
  505. }
  506. if (eof_out != NULL) {
  507. *eof_out = read_eof;
  508. }
  509. if (content_data == nil || content_data.length == 0) {
  510. return 0;
  511. }
  512. memcpy(buffer, content_data.bytes, content_data.length);
  513. return (ssize_t)content_data.length;
  514. }
  515. ssize_t box_apple_tls_client_write(box_apple_tls_client_t *client, const void *buffer, size_t buffer_len, int timeout_msec, char **error_out) {
  516. nw_connection_t connection = box_apple_tls_connection(client);
  517. if (connection == nil) {
  518. box_set_error_message(error_out, "apple TLS: invalid client");
  519. return -1;
  520. }
  521. if (buffer_len == 0) {
  522. return 0;
  523. }
  524. void *content_copy = malloc(buffer_len);
  525. dispatch_queue_t queue = box_apple_tls_client_queue(client);
  526. if (content_copy == NULL) {
  527. free(content_copy);
  528. box_set_error_message(error_out, "apple TLS: out of memory");
  529. return -1;
  530. }
  531. if (queue == nil) {
  532. free(content_copy);
  533. box_set_error_message(error_out, "apple TLS: invalid client");
  534. return -1;
  535. }
  536. memcpy(content_copy, buffer, buffer_len);
  537. dispatch_data_t content = dispatch_data_create(content_copy, buffer_len, queue, ^{
  538. free(content_copy);
  539. });
  540. dispatch_semaphore_t write_semaphore = dispatch_semaphore_create(0);
  541. __block char *local_error = NULL;
  542. nw_connection_send(connection, content, NW_CONNECTION_DEFAULT_STREAM_CONTEXT, false, ^(nw_error_t error) {
  543. if (error != NULL) {
  544. box_set_error_from_nw_error(&local_error, error);
  545. }
  546. dispatch_semaphore_signal(write_semaphore);
  547. });
  548. dispatch_time_t wait_deadline = DISPATCH_TIME_FOREVER;
  549. if (timeout_msec >= 0) {
  550. wait_deadline = dispatch_time(DISPATCH_TIME_NOW, (int64_t)timeout_msec * NSEC_PER_MSEC);
  551. }
  552. long wait_result = dispatch_semaphore_wait(write_semaphore, wait_deadline);
  553. if (wait_result != 0) {
  554. nw_connection_cancel(connection);
  555. dispatch_semaphore_wait(write_semaphore, DISPATCH_TIME_FOREVER);
  556. if (local_error != NULL) {
  557. free(local_error);
  558. local_error = NULL;
  559. }
  560. return -2;
  561. }
  562. if (local_error != NULL) {
  563. if (error_out != NULL) {
  564. *error_out = local_error;
  565. } else {
  566. free(local_error);
  567. }
  568. return -1;
  569. }
  570. return (ssize_t)buffer_len;
  571. }
  572. bool box_apple_tls_client_copy_state(box_apple_tls_client_t *client, box_apple_tls_state_t *state, char **error_out) {
  573. dispatch_queue_t queue = box_apple_tls_client_queue(client);
  574. if (queue == nil || state == NULL) {
  575. box_set_error_message(error_out, "apple TLS: invalid client");
  576. return false;
  577. }
  578. memset(state, 0, sizeof(box_apple_tls_state_t));
  579. __block bool copied = false;
  580. __block char *local_error = NULL;
  581. dispatch_sync(queue, ^{
  582. if (!atomic_load(&client->ready)) {
  583. box_set_error_message(&local_error, "apple TLS: metadata unavailable");
  584. return;
  585. }
  586. if (!box_apple_tls_state_copy(&client->state, state)) {
  587. box_set_error_message(&local_error, "apple TLS: out of memory");
  588. return;
  589. }
  590. copied = true;
  591. });
  592. if (copied) {
  593. return true;
  594. }
  595. if (local_error != NULL) {
  596. if (error_out != NULL) {
  597. *error_out = local_error;
  598. } else {
  599. free(local_error);
  600. }
  601. }
  602. box_apple_tls_state_reset(state);
  603. return false;
  604. }
  605. void box_apple_tls_state_free(box_apple_tls_state_t *state) {
  606. box_apple_tls_state_reset(state);
  607. }