StreamPeerIO.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. /**
  2. * @file StreamPeerIO.c
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * This file is part of BadVPN.
  8. *
  9. * BadVPN is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2
  11. * as published by the Free Software Foundation.
  12. *
  13. * BadVPN is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, write to the Free Software Foundation, Inc.,
  20. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. */
  22. #include <stdlib.h>
  23. #include <openssl/rand.h>
  24. #include <prio.h>
  25. #include <ssl.h>
  26. #include <sslerr.h>
  27. #include <misc/offset.h>
  28. #include <misc/debug.h>
  29. #include <misc/jenkins_hash.h>
  30. #include <misc/byteorder.h>
  31. #include <system/BLog.h>
  32. #include <client/StreamPeerIO.h>
  33. #include <generated/blog_channel_StreamPeerIO.h>
  34. #define STREAMPEERIO_COMPONENT_SEND_SINK 0
  35. #define STREAMPEERIO_COMPONENT_RECEIVE_SOURCE 1
  36. #define STREAMPEERIO_COMPONENT_RECEIVE_DECODER 2
  37. #define MODE_NONE 0
  38. #define MODE_CONNECT 1
  39. #define MODE_LISTEN 2
  40. #define CONNECT_STATE_CONNECTING 0
  41. #define CONNECT_STATE_HANDSHAKE 1
  42. #define CONNECT_STATE_SENDING 2
  43. #define CONNECT_STATE_SENT 3
  44. #define CONNECT_STATE_FINISHED 4
  45. #define LISTEN_STATE_LISTENER 0
  46. #define LISTEN_STATE_GOTCLIENT 1
  47. #define LISTEN_STATE_FINISHED 2
  48. static int init_persistent_io (StreamPeerIO *pio, PacketPassInterface *user_recv_if);
  49. static void free_persistent_io (StreamPeerIO *pio);
  50. static void connecting_connect_handler (StreamPeerIO *pio, int event);
  51. static SECStatus client_auth_certificate_callback (StreamPeerIO *pio, PRFileDesc *fd, PRBool checkSig, PRBool isServer);
  52. static SECStatus client_client_auth_data_callback (StreamPeerIO *pio, PRFileDesc *fd, CERTDistNames *caNames, CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey);
  53. static void connecting_try_handshake (StreamPeerIO *pio);
  54. static void connecting_handshake_read_handler (StreamPeerIO *pio, PRInt16 event);
  55. static void connecting_pwsender_handler (StreamPeerIO *pio, int is_error);
  56. static void error_handler (StreamPeerIO *pio, int component, const void *data);
  57. static void listener_handler_client (StreamPeerIO *pio, sslsocket *sock);
  58. static int init_io (StreamPeerIO *pio, sslsocket *sock);
  59. static void free_io (StreamPeerIO *pio);
  60. static int compare_certificate (StreamPeerIO *pio, CERTCertificate *cert);
  61. static void reset_state (StreamPeerIO *pio);
  62. static void cleanup_socket (sslsocket *sock, int ssl);
  63. static void reset_and_report_error (StreamPeerIO *pio);
  64. #define COMPONENT_SOURCE 1
  65. #define COMPONENT_SINK 2
  66. #define COMPONENT_DECODER 3
  67. void connecting_connect_handler (StreamPeerIO *pio, int event)
  68. {
  69. ASSERT(event == BSOCKET_CONNECT)
  70. ASSERT(pio->mode == MODE_CONNECT)
  71. ASSERT(pio->connect.state == CONNECT_STATE_CONNECTING)
  72. DebugObject_Access(&pio->d_obj);
  73. // remove connect event handler
  74. BSocket_RemoveEventHandler(&pio->connect.sock.sock, BSOCKET_CONNECT);
  75. // check connection result
  76. int res = BSocket_GetConnectResult(&pio->connect.sock.sock);
  77. if (res != 0) {
  78. BLog(BLOG_NOTICE, "Connection failed (%d)", res);
  79. goto fail0;
  80. }
  81. if (pio->ssl) {
  82. // create BSocket NSPR file descriptor
  83. BSocketPRFileDesc_Create(&pio->connect.sock.bottom_prfd, &pio->connect.sock.sock);
  84. // create SSL file descriptor from the socket's BSocketPRFileDesc
  85. if (!(pio->connect.sock.ssl_prfd = SSL_ImportFD(NULL, &pio->connect.sock.bottom_prfd))) {
  86. ASSERT_FORCE(PR_Close(&pio->connect.sock.bottom_prfd) == PR_SUCCESS)
  87. goto fail0;
  88. }
  89. // set client mode
  90. if (SSL_ResetHandshake(pio->connect.sock.ssl_prfd, PR_FALSE) != SECSuccess) {
  91. BLog(BLOG_ERROR, "SSL_ResetHandshake failed");
  92. goto fail_ssl1;
  93. }
  94. // set verify peer certificate hook
  95. if (SSL_AuthCertificateHook(pio->connect.sock.ssl_prfd, (SSLAuthCertificate)client_auth_certificate_callback, pio) != SECSuccess) {
  96. BLog(BLOG_ERROR, "SSL_AuthCertificateHook failed");
  97. goto fail_ssl1;
  98. }
  99. // set client certificate callback
  100. if (SSL_GetClientAuthDataHook(pio->connect.sock.ssl_prfd, (SSLGetClientAuthData)client_client_auth_data_callback, pio) != SECSuccess) {
  101. BLog(BLOG_ERROR, "SSL_GetClientAuthDataHook failed");
  102. goto fail_ssl1;
  103. }
  104. // initialize BPRFileDesc on SSL file descriptor
  105. BPRFileDesc_Init(&pio->connect.sock.ssl_bprfd, pio->connect.sock.ssl_prfd);
  106. // add event handler for driving handshake
  107. BPRFileDesc_AddEventHandler(&pio->connect.sock.ssl_bprfd, PR_POLL_READ, (BPRFileDesc_handler)connecting_handshake_read_handler, pio);
  108. // change state
  109. pio->connect.state = CONNECT_STATE_HANDSHAKE;
  110. // start handshake
  111. connecting_try_handshake(pio);
  112. return;
  113. } else {
  114. // init password sender
  115. PasswordSender_Init(&pio->connect.pwsender, pio->connect.password, 0, &pio->connect.sock.sock, NULL, (PasswordSender_handler)connecting_pwsender_handler, pio, pio->reactor);
  116. // change state
  117. pio->connect.state = CONNECT_STATE_SENDING;
  118. return;
  119. }
  120. // cleanup
  121. fail_ssl1:
  122. ASSERT_FORCE(PR_Close(pio->connect.sock.ssl_prfd) == PR_SUCCESS)
  123. fail0:
  124. reset_and_report_error(pio);
  125. return;
  126. }
  127. SECStatus client_auth_certificate_callback (StreamPeerIO *pio, PRFileDesc *fd, PRBool checkSig, PRBool isServer)
  128. {
  129. ASSERT(pio->ssl)
  130. ASSERT(pio->mode == MODE_CONNECT)
  131. ASSERT(pio->connect.state == CONNECT_STATE_HANDSHAKE)
  132. DebugObject_Access(&pio->d_obj);
  133. // This callback is used to bypass checking the server's domain name, as peers
  134. // don't have domain names. We byte-compare the certificate to the one reported
  135. // by the server anyway.
  136. CERTCertificate *server_cert = SSL_PeerCertificate(pio->connect.sock.ssl_prfd);
  137. if (!server_cert) {
  138. BLog(BLOG_ERROR, "SSL_PeerCertificate failed");
  139. PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
  140. return SECFailure;
  141. }
  142. SECStatus verify_result = CERT_VerifyCertNow(CERT_GetDefaultCertDB(), server_cert, PR_TRUE, certUsageSSLServer, SSL_RevealPinArg(pio->connect.sock.ssl_prfd));
  143. if (verify_result == SECFailure) {
  144. goto out;
  145. }
  146. // compare to certificate provided by the server
  147. if (!compare_certificate(pio, server_cert)) {
  148. verify_result = SECFailure;
  149. PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
  150. goto out;
  151. }
  152. out:
  153. CERT_DestroyCertificate(server_cert);
  154. return verify_result;
  155. }
  156. SECStatus client_client_auth_data_callback (StreamPeerIO *pio, PRFileDesc *fd, CERTDistNames *caNames, CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey)
  157. {
  158. ASSERT(pio->ssl)
  159. ASSERT(pio->mode == MODE_CONNECT)
  160. ASSERT(pio->connect.state == CONNECT_STATE_HANDSHAKE)
  161. DebugObject_Access(&pio->d_obj);
  162. if (!(*pRetCert = CERT_DupCertificate(pio->connect.ssl_cert))) {
  163. return SECFailure;
  164. }
  165. if (!(*pRetKey = SECKEY_CopyPrivateKey(pio->connect.ssl_key))) {
  166. CERT_DestroyCertificate(*pRetCert);
  167. return SECFailure;
  168. }
  169. return SECSuccess;
  170. }
  171. void connecting_try_handshake (StreamPeerIO *pio)
  172. {
  173. ASSERT(pio->ssl)
  174. ASSERT(pio->mode == MODE_CONNECT)
  175. ASSERT(pio->connect.state == CONNECT_STATE_HANDSHAKE)
  176. if (SSL_ForceHandshake(pio->connect.sock.ssl_prfd) != SECSuccess) {
  177. PRErrorCode error = PR_GetError();
  178. if (error == PR_WOULD_BLOCK_ERROR) {
  179. BPRFileDesc_EnableEvent(&pio->connect.sock.ssl_bprfd, PR_POLL_READ);
  180. return;
  181. }
  182. BLog(BLOG_NOTICE, "SSL_ForceHandshake failed (%d)", (int)error);
  183. goto fail0;
  184. }
  185. // remove client certificate callback
  186. if (SSL_GetClientAuthDataHook(pio->connect.sock.ssl_prfd, NULL, NULL) != SECSuccess) {
  187. BLog(BLOG_ERROR, "SSL_GetClientAuthDataHook failed");
  188. goto fail0;
  189. }
  190. // remove verify peer certificate callback
  191. if (SSL_AuthCertificateHook(pio->connect.sock.ssl_prfd, NULL, NULL) != SECSuccess) {
  192. BLog(BLOG_ERROR, "SSL_AuthCertificateHook failed");
  193. goto fail0;
  194. }
  195. // remove read handler
  196. BPRFileDesc_RemoveEventHandler(&pio->connect.sock.ssl_bprfd, PR_POLL_READ);
  197. // init password sender
  198. PasswordSender_Init(&pio->connect.pwsender, pio->connect.password, 1, NULL, &pio->connect.sock.ssl_bprfd, (PasswordSender_handler)connecting_pwsender_handler, pio, pio->reactor);
  199. // change state
  200. pio->connect.state = CONNECT_STATE_SENDING;
  201. return;
  202. // cleanup
  203. fail0:
  204. reset_and_report_error(pio);
  205. return;
  206. }
  207. void connecting_handshake_read_handler (StreamPeerIO *pio, PRInt16 event)
  208. {
  209. DebugObject_Access(&pio->d_obj);
  210. connecting_try_handshake(pio);
  211. return;
  212. }
  213. static void connecting_pwsender_handler (StreamPeerIO *pio, int is_error)
  214. {
  215. ASSERT(pio->mode == MODE_CONNECT)
  216. ASSERT(pio->connect.state == CONNECT_STATE_SENDING)
  217. DebugObject_Access(&pio->d_obj);
  218. if (is_error) {
  219. BLog(BLOG_NOTICE, "error sending password");
  220. BLog(BLOG_NOTICE,"BSocket error %d", BSocket_GetError(&pio->connect.sock.sock));
  221. if (pio->ssl) {
  222. BLog(BLOG_NOTICE, "NSPR error %d", (int)PR_GetError());
  223. }
  224. goto fail0;
  225. }
  226. // free password sender
  227. PasswordSender_Free(&pio->connect.pwsender);
  228. // change state
  229. pio->connect.state = CONNECT_STATE_SENT;
  230. // setup i/o
  231. if (!init_io(pio, &pio->connect.sock)) {
  232. goto fail0;
  233. }
  234. // change state
  235. pio->connect.state = CONNECT_STATE_FINISHED;
  236. return;
  237. fail0:
  238. reset_and_report_error(pio);
  239. return;
  240. }
  241. void error_handler (StreamPeerIO *pio, int component, const void *data)
  242. {
  243. ASSERT(pio->sock)
  244. DebugObject_Access(&pio->d_obj);
  245. switch (component) {
  246. case COMPONENT_SOURCE:
  247. case COMPONENT_SINK:
  248. BLog(BLOG_NOTICE,"BSocket error %d", BSocket_GetError(&pio->sock->sock));
  249. if (pio->ssl) {
  250. BLog(BLOG_NOTICE, "NSPR error %d", (int)PR_GetError());
  251. }
  252. break;
  253. case COMPONENT_DECODER:
  254. BLog(BLOG_NOTICE, "decoder error %d", *((int *)data));
  255. break;
  256. default:
  257. ASSERT(0);
  258. }
  259. // cleanup
  260. reset_and_report_error(pio);
  261. return;
  262. }
  263. void listener_handler_client (StreamPeerIO *pio, sslsocket *sock)
  264. {
  265. ASSERT(pio->mode == MODE_LISTEN)
  266. ASSERT(pio->listen.state == LISTEN_STATE_LISTENER)
  267. DebugObject_Access(&pio->d_obj);
  268. // remember socket
  269. pio->listen.sock = sock;
  270. // change state
  271. pio->listen.state = LISTEN_STATE_GOTCLIENT;
  272. // check ceritficate
  273. if (pio->ssl) {
  274. CERTCertificate *peer_cert = SSL_PeerCertificate(pio->listen.sock->ssl_prfd);
  275. if (!peer_cert) {
  276. BLog(BLOG_ERROR, "SSL_PeerCertificate failed");
  277. goto fail0;
  278. }
  279. // compare certificate to the one provided by the server
  280. if (!compare_certificate(pio, peer_cert)) {
  281. CERT_DestroyCertificate(peer_cert);
  282. goto fail0;
  283. }
  284. CERT_DestroyCertificate(peer_cert);
  285. }
  286. // setup i/o
  287. if (!init_io(pio, pio->listen.sock)) {
  288. goto fail0;
  289. }
  290. // change state
  291. pio->listen.state = LISTEN_STATE_FINISHED;
  292. return;
  293. // cleanup
  294. fail0:
  295. reset_and_report_error(pio);
  296. return;
  297. }
  298. int init_persistent_io (StreamPeerIO *pio, PacketPassInterface *user_recv_if)
  299. {
  300. // init error domain
  301. FlowErrorDomain_Init(&pio->ioerrdomain, (FlowErrorDomain_handler)error_handler, pio);
  302. // init receiveing objects
  303. StreamRecvConnector_Init(&pio->input_connector, BReactor_PendingGroup(pio->reactor));
  304. if (!PacketProtoDecoder_Init(
  305. &pio->input_decoder, FlowErrorReporter_Create(&pio->ioerrdomain, COMPONENT_DECODER),
  306. StreamRecvConnector_GetOutput(&pio->input_connector), user_recv_if, BReactor_PendingGroup(pio->reactor)
  307. )) {
  308. goto fail1;
  309. }
  310. // init sending objects
  311. PacketCopier_Init(&pio->output_user_copier, pio->payload_mtu, BReactor_PendingGroup(pio->reactor));
  312. PacketProtoEncoder_Init(&pio->output_user_ppe, PacketCopier_GetOutput(&pio->output_user_copier), BReactor_PendingGroup(pio->reactor));
  313. PacketPassConnector_Init(&pio->output_connector, PACKETPROTO_ENCLEN(pio->payload_mtu), BReactor_PendingGroup(pio->reactor));
  314. if (!SinglePacketBuffer_Init(&pio->output_user_spb, PacketProtoEncoder_GetOutput(&pio->output_user_ppe), PacketPassConnector_GetInput(&pio->output_connector), BReactor_PendingGroup(pio->reactor))) {
  315. goto fail2;
  316. }
  317. return 1;
  318. fail2:
  319. PacketPassConnector_Free(&pio->output_connector);
  320. PacketProtoEncoder_Free(&pio->output_user_ppe);
  321. PacketCopier_Free(&pio->output_user_copier);
  322. PacketProtoDecoder_Free(&pio->input_decoder);
  323. fail1:
  324. StreamRecvConnector_Free(&pio->input_connector);
  325. return 0;
  326. }
  327. void free_persistent_io (StreamPeerIO *pio)
  328. {
  329. // free sending objects
  330. SinglePacketBuffer_Free(&pio->output_user_spb);
  331. PacketPassConnector_Free(&pio->output_connector);
  332. PacketProtoEncoder_Free(&pio->output_user_ppe);
  333. PacketCopier_Free(&pio->output_user_copier);
  334. // free receiveing objects
  335. PacketProtoDecoder_Free(&pio->input_decoder);
  336. StreamRecvConnector_Free(&pio->input_connector);
  337. }
  338. int init_io (StreamPeerIO *pio, sslsocket *sock)
  339. {
  340. ASSERT(!pio->sock)
  341. // init receiving
  342. StreamRecvInterface *source_interface;
  343. if (pio->ssl) {
  344. PRStreamSource_Init(
  345. &pio->input_source.ssl, FlowErrorReporter_Create(&pio->ioerrdomain, COMPONENT_SOURCE),
  346. &sock->ssl_bprfd, BReactor_PendingGroup(pio->reactor)
  347. );
  348. source_interface = PRStreamSource_GetOutput(&pio->input_source.ssl);
  349. } else {
  350. StreamSocketSource_Init(
  351. &pio->input_source.plain, FlowErrorReporter_Create(&pio->ioerrdomain, COMPONENT_SOURCE),
  352. &sock->sock, BReactor_PendingGroup(pio->reactor)
  353. );
  354. source_interface = StreamSocketSource_GetOutput(&pio->input_source.plain);
  355. }
  356. StreamRecvConnector_ConnectInput(&pio->input_connector, source_interface);
  357. // init sending
  358. StreamPassInterface *sink_interface;
  359. if (pio->ssl) {
  360. PRStreamSink_Init(
  361. &pio->output_sink.ssl, FlowErrorReporter_Create(&pio->ioerrdomain, COMPONENT_SINK),
  362. &sock->ssl_bprfd, BReactor_PendingGroup(pio->reactor)
  363. );
  364. sink_interface = PRStreamSink_GetInput(&pio->output_sink.ssl);
  365. } else {
  366. StreamSocketSink_Init(
  367. &pio->output_sink.plain, FlowErrorReporter_Create(&pio->ioerrdomain, COMPONENT_SINK),
  368. &sock->sock, BReactor_PendingGroup(pio->reactor)
  369. );
  370. sink_interface = StreamSocketSink_GetInput(&pio->output_sink.plain);
  371. }
  372. PacketStreamSender_Init(&pio->output_pss, sink_interface, PACKETPROTO_ENCLEN(pio->payload_mtu), BReactor_PendingGroup(pio->reactor));
  373. PacketPassConnector_ConnectOutput(&pio->output_connector, PacketStreamSender_GetInput(&pio->output_pss));
  374. pio->sock = sock;
  375. return 1;
  376. }
  377. void free_io (StreamPeerIO *pio)
  378. {
  379. ASSERT(pio->sock)
  380. // reset decoder
  381. PacketProtoDecoder_Reset(&pio->input_decoder);
  382. // free sending
  383. PacketPassConnector_DisconnectOutput(&pio->output_connector);
  384. PacketStreamSender_Free(&pio->output_pss);
  385. if (pio->ssl) {
  386. PRStreamSink_Free(&pio->output_sink.ssl);
  387. } else {
  388. StreamSocketSink_Free(&pio->output_sink.plain);
  389. }
  390. // free receiving
  391. StreamRecvConnector_DisconnectInput(&pio->input_connector);
  392. if (pio->ssl) {
  393. PRStreamSource_Free(&pio->input_source.ssl);
  394. } else {
  395. StreamSocketSource_Free(&pio->input_source.plain);
  396. }
  397. pio->sock = NULL;
  398. }
  399. int compare_certificate (StreamPeerIO *pio, CERTCertificate *cert)
  400. {
  401. ASSERT(pio->ssl)
  402. PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  403. if (!arena) {
  404. BLog(BLOG_ERROR, "WARNING: PORT_NewArena failed");
  405. return 0;
  406. }
  407. // encode server certificate
  408. SECItem der;
  409. der.len = 0;
  410. der.data = NULL;
  411. if (!SEC_ASN1EncodeItem(arena, &der, cert, SEC_ASN1_GET(CERT_CertificateTemplate))) {
  412. BLog(BLOG_ERROR, "SEC_ASN1EncodeItem failed");
  413. PORT_FreeArena(arena, PR_FALSE);
  414. return 0;
  415. }
  416. // byte compare
  417. if (der.len != pio->ssl_peer_cert_len || memcmp(der.data, pio->ssl_peer_cert, der.len)) {
  418. BLog(BLOG_NOTICE, "Client certificate doesn't match");
  419. PORT_FreeArena(arena, PR_FALSE);
  420. return 0;
  421. }
  422. PORT_FreeArena(arena, PR_FALSE);
  423. return 1;
  424. }
  425. void reset_state (StreamPeerIO *pio)
  426. {
  427. // free resources
  428. switch (pio->mode) {
  429. case MODE_NONE:
  430. break;
  431. case MODE_LISTEN:
  432. switch (pio->listen.state) {
  433. case LISTEN_STATE_FINISHED:
  434. free_io(pio);
  435. case LISTEN_STATE_GOTCLIENT:
  436. cleanup_socket(pio->listen.sock, pio->ssl);
  437. free(pio->listen.sock);
  438. break;
  439. case LISTEN_STATE_LISTENER:
  440. PasswordListener_RemoveEntry(pio->listen.listener, &pio->listen.pwentry);
  441. break;
  442. default:
  443. ASSERT(0);
  444. }
  445. pio->mode = MODE_NONE;
  446. break;
  447. case MODE_CONNECT:
  448. switch (pio->connect.state) {
  449. case CONNECT_STATE_FINISHED:
  450. free_io(pio);
  451. case CONNECT_STATE_SENT:
  452. case CONNECT_STATE_SENDING:
  453. if (pio->connect.state == CONNECT_STATE_SENDING) {
  454. PasswordSender_Free(&pio->connect.pwsender);
  455. }
  456. case CONNECT_STATE_HANDSHAKE:
  457. if (pio->ssl) {
  458. BPRFileDesc_Free(&pio->connect.sock.ssl_bprfd);
  459. ASSERT_FORCE(PR_Close(pio->connect.sock.ssl_prfd) == PR_SUCCESS)
  460. }
  461. case CONNECT_STATE_CONNECTING:
  462. BSocket_Free(&pio->connect.sock.sock);
  463. break;
  464. default:
  465. ASSERT(0);
  466. }
  467. pio->mode = MODE_NONE;
  468. break;
  469. default:
  470. ASSERT(0);
  471. }
  472. ASSERT(!pio->sock)
  473. }
  474. void cleanup_socket (sslsocket *sock, int ssl)
  475. {
  476. if (ssl) {
  477. // free BPRFileDesc
  478. BPRFileDesc_Free(&sock->ssl_bprfd);
  479. // free SSL NSPR file descriptor
  480. ASSERT_FORCE(PR_Close(sock->ssl_prfd) == PR_SUCCESS)
  481. }
  482. // free socket
  483. BSocket_Free(&sock->sock);
  484. }
  485. void reset_and_report_error (StreamPeerIO *pio)
  486. {
  487. reset_state(pio);
  488. pio->handler_error(pio->user);
  489. return;
  490. }
  491. int StreamPeerIO_Init (
  492. StreamPeerIO *pio,
  493. BReactor *reactor,
  494. int ssl,
  495. uint8_t *ssl_peer_cert,
  496. int ssl_peer_cert_len,
  497. int payload_mtu,
  498. PacketPassInterface *user_recv_if,
  499. StreamPeerIO_handler_error handler_error,
  500. void *user
  501. )
  502. {
  503. ASSERT(ssl == 0 || ssl == 1)
  504. ASSERT(payload_mtu >= 0)
  505. ASSERT(PacketPassInterface_GetMTU(user_recv_if) >= payload_mtu)
  506. // init arguments
  507. pio->reactor = reactor;
  508. pio->ssl = ssl;
  509. if (pio->ssl) {
  510. pio->ssl_peer_cert = ssl_peer_cert;
  511. pio->ssl_peer_cert_len = ssl_peer_cert_len;
  512. }
  513. pio->payload_mtu = payload_mtu;
  514. pio->handler_error = handler_error;
  515. pio->user = user;
  516. // init persistent I/O modules
  517. if (!init_persistent_io(pio, user_recv_if)) {
  518. return 0;
  519. }
  520. // set mode none
  521. pio->mode = MODE_NONE;
  522. // set no socket
  523. pio->sock = NULL;
  524. DebugObject_Init(&pio->d_obj);
  525. return 1;
  526. }
  527. void StreamPeerIO_Free (StreamPeerIO *pio)
  528. {
  529. DebugObject_Free(&pio->d_obj);
  530. // reset state
  531. reset_state(pio);
  532. // free persistent I/O modules
  533. free_persistent_io(pio);
  534. }
  535. PacketPassInterface * StreamPeerIO_GetSendInput (StreamPeerIO *pio)
  536. {
  537. DebugObject_Access(&pio->d_obj);
  538. return PacketCopier_GetInput(&pio->output_user_copier);
  539. }
  540. int StreamPeerIO_Connect (StreamPeerIO *pio, BAddr addr, uint64_t password, CERTCertificate *ssl_cert, SECKEYPrivateKey *ssl_key)
  541. {
  542. ASSERT(BAddr_IsRecognized(&addr) && !BAddr_IsInvalid(&addr))
  543. DebugObject_Access(&pio->d_obj);
  544. // reset state
  545. reset_state(pio);
  546. // create socket
  547. if (BSocket_Init(&pio->connect.sock.sock, pio->reactor, addr.type, BSOCKET_TYPE_STREAM) < 0) {
  548. BLog(BLOG_ERROR, "BSocket_Init failed");
  549. goto fail0;
  550. }
  551. // attempt connection
  552. if (BSocket_Connect(&pio->connect.sock.sock, &addr) >= 0 || BSocket_GetError(&pio->connect.sock.sock) != BSOCKET_ERROR_IN_PROGRESS) {
  553. BLog(BLOG_NOTICE, "BSocket_Connect failed");
  554. goto fail1;
  555. }
  556. // waiting for connection result
  557. BSocket_AddEventHandler(&pio->connect.sock.sock, BSOCKET_CONNECT, (BSocket_handler)connecting_connect_handler, pio);
  558. BSocket_EnableEvent(&pio->connect.sock.sock, BSOCKET_CONNECT);
  559. // remember data
  560. if (pio->ssl) {
  561. pio->connect.ssl_cert = ssl_cert;
  562. pio->connect.ssl_key = ssl_key;
  563. }
  564. pio->connect.password = htol64(password);
  565. // set state
  566. pio->mode = MODE_CONNECT;
  567. pio->connect.state = CONNECT_STATE_CONNECTING;
  568. return 1;
  569. fail1:
  570. BSocket_Free(&pio->connect.sock.sock);
  571. fail0:
  572. return 0;
  573. }
  574. void StreamPeerIO_Listen (StreamPeerIO *pio, PasswordListener *listener, uint64_t *password)
  575. {
  576. ASSERT(listener->ssl == pio->ssl)
  577. DebugObject_Access(&pio->d_obj);
  578. // reset state
  579. reset_state(pio);
  580. // add PasswordListener entry
  581. uint64_t newpass = PasswordListener_AddEntry(listener, &pio->listen.pwentry, (PasswordListener_handler_client)listener_handler_client, pio);
  582. // remember data
  583. pio->listen.listener = listener;
  584. // set state
  585. pio->mode = MODE_LISTEN;
  586. pio->listen.state = LISTEN_STATE_LISTENER;
  587. *password = newpass;
  588. }