StreamPeerIO.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  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_FINISHED 3
  44. #define LISTEN_STATE_LISTENER 0
  45. #define LISTEN_STATE_GOTCLIENT 1
  46. #define LISTEN_STATE_FINISHED 2
  47. static int init_persistent_io (StreamPeerIO *pio, PacketPassInterface *user_recv_if);
  48. static void free_persistent_io (StreamPeerIO *pio);
  49. static void connecting_connect_handler (StreamPeerIO *pio, int event);
  50. static SECStatus client_auth_certificate_callback (StreamPeerIO *pio, PRFileDesc *fd, PRBool checkSig, PRBool isServer);
  51. static SECStatus client_client_auth_data_callback (StreamPeerIO *pio, PRFileDesc *fd, CERTDistNames *caNames, CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey);
  52. static void connecting_try_handshake (StreamPeerIO *pio);
  53. static void connecting_handshake_read_handler (StreamPeerIO *pio, PRInt16 event);
  54. static void connecting_try_send_ssl (StreamPeerIO *pio);
  55. static void connecting_try_send_plain (StreamPeerIO *pio);
  56. static void connecting_socket_write_handler_ssl (StreamPeerIO *pio, PRInt16 event);
  57. static void connecting_socket_write_handler_plain (StreamPeerIO *pio, int event);
  58. static void error_handler (StreamPeerIO *pio, int component, const void *data);
  59. static void listener_handler_client (StreamPeerIO *pio, sslsocket *sock);
  60. static int init_io (StreamPeerIO *pio, sslsocket *sock);
  61. static void free_io (StreamPeerIO *pio);
  62. static int compare_certificate (StreamPeerIO *pio, CERTCertificate *cert);
  63. static void reset_state (StreamPeerIO *pio);
  64. static void cleanup_socket (sslsocket *sock, int ssl);
  65. #define COMPONENT_SOURCE 1
  66. #define COMPONENT_SINK 2
  67. #define COMPONENT_DECODER 3
  68. void connecting_connect_handler (StreamPeerIO *pio, int event)
  69. {
  70. ASSERT(event == BSOCKET_CONNECT)
  71. ASSERT(pio->mode == MODE_CONNECT)
  72. ASSERT(pio->connect.state == CONNECT_STATE_CONNECTING)
  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. // add write handler
  115. BSocket_AddEventHandler(&pio->connect.sock.sock, BSOCKET_WRITE, (BSocket_handler)connecting_socket_write_handler_plain, pio);
  116. // haven't sent anything yet
  117. pio->connect.connecting_sending_sent = 0;
  118. // change state
  119. pio->connect.state = CONNECT_STATE_SENDING;
  120. // start sending password
  121. connecting_try_send_plain(pio);
  122. return;
  123. }
  124. // cleanup
  125. fail_ssl1:
  126. ASSERT_FORCE(PR_Close(pio->connect.sock.ssl_prfd) == PR_SUCCESS)
  127. fail0:
  128. reset_state(pio);
  129. // report error
  130. pio->handler_error(pio->user);
  131. return;
  132. }
  133. SECStatus client_auth_certificate_callback (StreamPeerIO *pio, PRFileDesc *fd, PRBool checkSig, PRBool isServer)
  134. {
  135. ASSERT(pio->ssl)
  136. ASSERT(pio->mode == MODE_CONNECT)
  137. ASSERT(pio->connect.state == CONNECT_STATE_HANDSHAKE)
  138. // This callback is used to bypass checking the server's domain name, as peers
  139. // don't have domain names. We byte-compare the certificate to the one reported
  140. // by the server anyway.
  141. CERTCertificate *server_cert = SSL_PeerCertificate(pio->connect.sock.ssl_prfd);
  142. if (!server_cert) {
  143. BLog(BLOG_ERROR, "SSL_PeerCertificate failed");
  144. PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
  145. return SECFailure;
  146. }
  147. SECStatus verify_result = CERT_VerifyCertNow(CERT_GetDefaultCertDB(), server_cert, PR_TRUE, certUsageSSLServer, SSL_RevealPinArg(pio->connect.sock.ssl_prfd));
  148. if (verify_result == SECFailure) {
  149. goto out;
  150. }
  151. // compare to certificate provided by the server
  152. if (!compare_certificate(pio, server_cert)) {
  153. verify_result = SECFailure;
  154. PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
  155. goto out;
  156. }
  157. out:
  158. CERT_DestroyCertificate(server_cert);
  159. return verify_result;
  160. }
  161. SECStatus client_client_auth_data_callback (StreamPeerIO *pio, PRFileDesc *fd, CERTDistNames *caNames, CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey)
  162. {
  163. ASSERT(pio->ssl)
  164. ASSERT(pio->mode == MODE_CONNECT)
  165. ASSERT(pio->connect.state == CONNECT_STATE_HANDSHAKE)
  166. if (!(*pRetCert = CERT_DupCertificate(pio->connect.ssl_cert))) {
  167. return SECFailure;
  168. }
  169. if (!(*pRetKey = SECKEY_CopyPrivateKey(pio->connect.ssl_key))) {
  170. CERT_DestroyCertificate(*pRetCert);
  171. return SECFailure;
  172. }
  173. return SECSuccess;
  174. }
  175. void connecting_try_handshake (StreamPeerIO *pio)
  176. {
  177. ASSERT(pio->ssl)
  178. ASSERT(pio->mode == MODE_CONNECT)
  179. ASSERT(pio->connect.state == CONNECT_STATE_HANDSHAKE)
  180. if (SSL_ForceHandshake(pio->connect.sock.ssl_prfd) != SECSuccess) {
  181. PRErrorCode error = PR_GetError();
  182. if (error == PR_WOULD_BLOCK_ERROR) {
  183. BPRFileDesc_EnableEvent(&pio->connect.sock.ssl_bprfd, PR_POLL_READ);
  184. return;
  185. }
  186. BLog(BLOG_NOTICE, "SSL_ForceHandshake failed (%d)", (int)error);
  187. goto fail0;
  188. }
  189. // remove client certificate callback
  190. if (SSL_GetClientAuthDataHook(pio->connect.sock.ssl_prfd, NULL, NULL) != SECSuccess) {
  191. BLog(BLOG_ERROR, "SSL_GetClientAuthDataHook failed");
  192. goto fail0;
  193. }
  194. // remove verify peer certificate callback
  195. if (SSL_AuthCertificateHook(pio->connect.sock.ssl_prfd, NULL, NULL) != SECSuccess) {
  196. BLog(BLOG_ERROR, "SSL_AuthCertificateHook failed");
  197. goto fail0;
  198. }
  199. // remove read handler
  200. BPRFileDesc_RemoveEventHandler(&pio->connect.sock.ssl_bprfd, PR_POLL_READ);
  201. // add write handler
  202. BPRFileDesc_AddEventHandler(&pio->connect.sock.ssl_bprfd, PR_POLL_WRITE, (BPRFileDesc_handler)connecting_socket_write_handler_ssl, pio);
  203. // haven't send anything yet
  204. pio->connect.connecting_sending_sent = 0;
  205. // change state
  206. pio->connect.state = CONNECT_STATE_SENDING;
  207. // start sending password
  208. connecting_try_send_ssl(pio);
  209. return;
  210. // cleanup
  211. fail0:
  212. reset_state(pio);
  213. // report error
  214. pio->handler_error(pio->user);
  215. return;
  216. }
  217. void connecting_handshake_read_handler (StreamPeerIO *pio, PRInt16 event)
  218. {
  219. connecting_try_handshake(pio);
  220. return;
  221. }
  222. void connecting_try_send_ssl (StreamPeerIO *pio)
  223. {
  224. ASSERT(pio->ssl)
  225. ASSERT(pio->mode == MODE_CONNECT)
  226. ASSERT(pio->connect.state == CONNECT_STATE_SENDING)
  227. while (pio->connect.connecting_sending_sent < sizeof(pio->connect.connecting_password)) {
  228. PRInt32 sent = PR_Write(
  229. pio->connect.sock.ssl_prfd,
  230. (uint8_t *)&pio->connect.connecting_password + pio->connect.connecting_sending_sent,
  231. sizeof(pio->connect.connecting_password) - pio->connect.connecting_sending_sent
  232. );
  233. if (sent < 0) {
  234. PRErrorCode error = PR_GetError();
  235. if (error == PR_WOULD_BLOCK_ERROR) {
  236. BPRFileDesc_EnableEvent(&pio->connect.sock.ssl_bprfd, PR_POLL_WRITE);
  237. return;
  238. }
  239. BLog(BLOG_NOTICE, "PR_Write failed (%d)", (int)error);
  240. goto fail0;
  241. }
  242. pio->connect.connecting_sending_sent += sent;
  243. }
  244. // remove write handler
  245. BPRFileDesc_RemoveEventHandler(&pio->connect.sock.ssl_bprfd, PR_POLL_WRITE);
  246. // setup i/o
  247. if (!init_io(pio, &pio->connect.sock)) {
  248. goto fail0;
  249. }
  250. // change state
  251. pio->connect.state = CONNECT_STATE_FINISHED;
  252. return;
  253. // cleanup
  254. fail0:
  255. reset_state(pio);
  256. // report error
  257. pio->handler_error(pio->user);
  258. return;
  259. }
  260. void connecting_try_send_plain (StreamPeerIO *pio)
  261. {
  262. ASSERT(!pio->ssl)
  263. ASSERT(pio->mode == MODE_CONNECT)
  264. ASSERT(pio->connect.state == CONNECT_STATE_SENDING)
  265. while (pio->connect.connecting_sending_sent < sizeof(pio->connect.connecting_password)) {
  266. int sent = BSocket_Send(
  267. &pio->connect.sock.sock,
  268. (uint8_t *)&pio->connect.connecting_password + pio->connect.connecting_sending_sent,
  269. sizeof(pio->connect.connecting_password) - pio->connect.connecting_sending_sent
  270. );
  271. if (sent < 0) {
  272. int error = BSocket_GetError(&pio->connect.sock.sock);
  273. if (error == BSOCKET_ERROR_LATER) {
  274. BSocket_EnableEvent(&pio->connect.sock.sock, BSOCKET_WRITE);
  275. return;
  276. }
  277. BLog(BLOG_NOTICE, "BSocket_Send failed (%d)", error);
  278. goto fail0;
  279. }
  280. pio->connect.connecting_sending_sent += sent;
  281. }
  282. // remove write event handler
  283. BSocket_RemoveEventHandler(&pio->connect.sock.sock, BSOCKET_WRITE);
  284. // setup i/o
  285. if (!init_io(pio, &pio->connect.sock)) {
  286. goto fail0;
  287. }
  288. // change state
  289. pio->connect.state = CONNECT_STATE_FINISHED;
  290. return;
  291. // cleanup
  292. fail0:
  293. reset_state(pio);
  294. // report error
  295. pio->handler_error(pio->user);
  296. return;
  297. }
  298. void connecting_socket_write_handler_ssl (StreamPeerIO *pio, PRInt16 event)
  299. {
  300. ASSERT(event == PR_POLL_WRITE)
  301. // try to send data
  302. connecting_try_send_ssl(pio);
  303. return;
  304. }
  305. void connecting_socket_write_handler_plain (StreamPeerIO *pio, int event)
  306. {
  307. ASSERT(event == BSOCKET_WRITE)
  308. // disable write event
  309. BSocket_DisableEvent(&pio->connect.sock.sock, BSOCKET_WRITE);
  310. // try to send data
  311. connecting_try_send_plain(pio);
  312. return;
  313. }
  314. void error_handler (StreamPeerIO *pio, int component, const void *data)
  315. {
  316. ASSERT(pio->sock)
  317. switch (component) {
  318. case COMPONENT_SOURCE:
  319. case COMPONENT_SINK:
  320. BLog(BLOG_NOTICE,"BSocket error %d", BSocket_GetError(&pio->sock->sock));
  321. if (pio->ssl) {
  322. BLog(BLOG_NOTICE, "NSPR error %d", (int)PR_GetError());
  323. }
  324. break;
  325. case COMPONENT_DECODER:
  326. BLog(BLOG_NOTICE, "decoder error %d", *((int *)data));
  327. break;
  328. default:
  329. ASSERT(0);
  330. }
  331. // cleanup
  332. reset_state(pio);
  333. // report error
  334. pio->handler_error(pio->user);
  335. return;
  336. }
  337. void listener_handler_client (StreamPeerIO *pio, sslsocket *sock)
  338. {
  339. ASSERT(pio->mode == MODE_LISTEN)
  340. ASSERT(pio->listen.state == LISTEN_STATE_LISTENER)
  341. // remember socket
  342. pio->listen.sock = sock;
  343. // change state
  344. pio->listen.state = LISTEN_STATE_GOTCLIENT;
  345. // check ceritficate
  346. if (pio->ssl) {
  347. CERTCertificate *peer_cert = SSL_PeerCertificate(pio->listen.sock->ssl_prfd);
  348. if (!peer_cert) {
  349. BLog(BLOG_ERROR, "SSL_PeerCertificate failed");
  350. goto fail0;
  351. }
  352. // compare certificate to the one provided by the server
  353. if (!compare_certificate(pio, peer_cert)) {
  354. CERT_DestroyCertificate(peer_cert);
  355. goto fail0;
  356. }
  357. CERT_DestroyCertificate(peer_cert);
  358. }
  359. // setup i/o
  360. if (!init_io(pio, pio->listen.sock)) {
  361. goto fail0;
  362. }
  363. // change state
  364. pio->listen.state = LISTEN_STATE_FINISHED;
  365. return;
  366. // cleanup
  367. fail0:
  368. reset_state(pio);
  369. // report error
  370. pio->handler_error(pio->user);
  371. return;
  372. }
  373. int init_persistent_io (StreamPeerIO *pio, PacketPassInterface *user_recv_if)
  374. {
  375. // init error domain
  376. FlowErrorDomain_Init(&pio->ioerrdomain, (FlowErrorDomain_handler)error_handler, pio);
  377. // init sending objects
  378. PacketCopier_Init(&pio->output_user_copier, pio->payload_mtu);
  379. PacketProtoEncoder_Init(&pio->output_user_ppe, PacketCopier_GetOutput(&pio->output_user_copier));
  380. PacketPassConnector_Init(&pio->output_connector, PACKETPROTO_ENCLEN(pio->payload_mtu), BReactor_PendingGroup(pio->reactor));
  381. if (!SinglePacketBuffer_Init(&pio->output_user_spb, PacketProtoEncoder_GetOutput(&pio->output_user_ppe), PacketPassConnector_GetInput(&pio->output_connector), BReactor_PendingGroup(pio->reactor))) {
  382. goto fail1;
  383. }
  384. // init receiveing objects
  385. StreamRecvConnector_Init(&pio->input_connector, BReactor_PendingGroup(pio->reactor));
  386. if (!PacketProtoDecoder_Init(
  387. &pio->input_decoder,
  388. FlowErrorReporter_Create(&pio->ioerrdomain, COMPONENT_DECODER),
  389. StreamRecvConnector_GetOutput(&pio->input_connector),
  390. user_recv_if,
  391. BReactor_PendingGroup(pio->reactor)
  392. )) {
  393. goto fail2;
  394. }
  395. return 1;
  396. // free receiveing objects
  397. fail2:
  398. StreamRecvConnector_Free(&pio->input_connector);
  399. // free sending objects
  400. SinglePacketBuffer_Free(&pio->output_user_spb);
  401. fail1:
  402. PacketPassConnector_Free(&pio->output_connector);
  403. PacketProtoEncoder_Free(&pio->output_user_ppe);
  404. PacketCopier_Free(&pio->output_user_copier);
  405. return 0;
  406. }
  407. void free_persistent_io (StreamPeerIO *pio)
  408. {
  409. // free receiveing objects
  410. PacketProtoDecoder_Free(&pio->input_decoder);
  411. StreamRecvConnector_Free(&pio->input_connector);
  412. // free sending objects
  413. SinglePacketBuffer_Free(&pio->output_user_spb);
  414. PacketPassConnector_Free(&pio->output_connector);
  415. PacketProtoEncoder_Free(&pio->output_user_ppe);
  416. PacketCopier_Free(&pio->output_user_copier);
  417. }
  418. int init_io (StreamPeerIO *pio, sslsocket *sock)
  419. {
  420. ASSERT(!pio->sock)
  421. // init sending
  422. StreamPassInterface *sink_interface;
  423. if (pio->ssl) {
  424. PRStreamSink_Init(
  425. &pio->output_sink.ssl,
  426. FlowErrorReporter_Create(&pio->ioerrdomain, COMPONENT_SINK),
  427. &sock->ssl_bprfd
  428. );
  429. sink_interface = PRStreamSink_GetInput(&pio->output_sink.ssl);
  430. } else {
  431. StreamSocketSink_Init(
  432. &pio->output_sink.plain,
  433. FlowErrorReporter_Create(&pio->ioerrdomain, COMPONENT_SINK),
  434. &sock->sock
  435. );
  436. sink_interface = StreamSocketSink_GetInput(&pio->output_sink.plain);
  437. }
  438. PacketStreamSender_Init(&pio->output_pss, sink_interface, PACKETPROTO_ENCLEN(pio->payload_mtu));
  439. PacketPassConnector_ConnectOutput(&pio->output_connector, PacketStreamSender_GetInput(&pio->output_pss));
  440. // init receiving
  441. StreamRecvInterface *source_interface;
  442. if (pio->ssl) {
  443. PRStreamSource_Init(
  444. &pio->input_source.ssl,
  445. FlowErrorReporter_Create(&pio->ioerrdomain, COMPONENT_SOURCE),
  446. &sock->ssl_bprfd
  447. );
  448. source_interface = PRStreamSource_GetOutput(&pio->input_source.ssl);
  449. } else {
  450. StreamSocketSource_Init(
  451. &pio->input_source.plain,
  452. FlowErrorReporter_Create(&pio->ioerrdomain, COMPONENT_SOURCE),
  453. &sock->sock
  454. );
  455. source_interface = StreamSocketSource_GetOutput(&pio->input_source.plain);
  456. }
  457. StreamRecvConnector_ConnectInput(&pio->input_connector, source_interface);
  458. pio->sock = sock;
  459. return 1;
  460. }
  461. void free_io (StreamPeerIO *pio)
  462. {
  463. ASSERT(pio->sock)
  464. // reset decoder
  465. PacketProtoDecoder_Reset(&pio->input_decoder);
  466. // free receiving
  467. StreamRecvConnector_DisconnectInput(&pio->input_connector);
  468. if (pio->ssl) {
  469. PRStreamSource_Free(&pio->input_source.ssl);
  470. } else {
  471. StreamSocketSource_Free(&pio->input_source.plain);
  472. }
  473. // free sending
  474. PacketPassConnector_DisconnectOutput(&pio->output_connector);
  475. PacketStreamSender_Free(&pio->output_pss);
  476. if (pio->ssl) {
  477. PRStreamSink_Free(&pio->output_sink.ssl);
  478. } else {
  479. StreamSocketSink_Free(&pio->output_sink.plain);
  480. }
  481. pio->sock = NULL;
  482. }
  483. int compare_certificate (StreamPeerIO *pio, CERTCertificate *cert)
  484. {
  485. ASSERT(pio->ssl)
  486. PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  487. if (!arena) {
  488. BLog(BLOG_ERROR, "WARNING: PORT_NewArena failed");
  489. return 0;
  490. }
  491. // encode server certificate
  492. SECItem der;
  493. der.len = 0;
  494. der.data = NULL;
  495. if (!SEC_ASN1EncodeItem(arena, &der, cert, SEC_ASN1_GET(CERT_CertificateTemplate))) {
  496. BLog(BLOG_ERROR, "SEC_ASN1EncodeItem failed");
  497. PORT_FreeArena(arena, PR_FALSE);
  498. return 0;
  499. }
  500. // byte compare
  501. if (der.len != pio->ssl_peer_cert_len || memcmp(der.data, pio->ssl_peer_cert, der.len)) {
  502. BLog(BLOG_NOTICE, "Client certificate doesn't match");
  503. PORT_FreeArena(arena, PR_FALSE);
  504. return 0;
  505. }
  506. PORT_FreeArena(arena, PR_FALSE);
  507. return 1;
  508. }
  509. void reset_state (StreamPeerIO *pio)
  510. {
  511. // free resources
  512. switch (pio->mode) {
  513. case MODE_NONE:
  514. break;
  515. case MODE_LISTEN:
  516. switch (pio->listen.state) {
  517. case LISTEN_STATE_FINISHED:
  518. free_io(pio);
  519. case LISTEN_STATE_GOTCLIENT:
  520. cleanup_socket(pio->listen.sock, pio->ssl);
  521. free(pio->listen.sock);
  522. break;
  523. case LISTEN_STATE_LISTENER:
  524. PasswordListener_RemoveEntry(pio->listen.listener, &pio->listen.pwentry);
  525. break;
  526. default:
  527. ASSERT(0);
  528. }
  529. DEAD_KILL(pio->mode_dead);
  530. pio->mode = MODE_NONE;
  531. break;
  532. case MODE_CONNECT:
  533. switch (pio->connect.state) {
  534. case CONNECT_STATE_FINISHED:
  535. free_io(pio);
  536. case CONNECT_STATE_SENDING:
  537. case CONNECT_STATE_HANDSHAKE:
  538. if (pio->ssl) {
  539. BPRFileDesc_Free(&pio->connect.sock.ssl_bprfd);
  540. ASSERT_FORCE(PR_Close(pio->connect.sock.ssl_prfd) == PR_SUCCESS)
  541. }
  542. case CONNECT_STATE_CONNECTING:
  543. BSocket_Free(&pio->connect.sock.sock);
  544. break;
  545. default:
  546. ASSERT(0);
  547. }
  548. DEAD_KILL(pio->mode_dead);
  549. pio->mode = MODE_NONE;
  550. break;
  551. default:
  552. ASSERT(0);
  553. }
  554. ASSERT(!pio->sock)
  555. }
  556. void cleanup_socket (sslsocket *sock, int ssl)
  557. {
  558. if (ssl) {
  559. // free BPRFileDesc
  560. BPRFileDesc_Free(&sock->ssl_bprfd);
  561. // free SSL NSPR file descriptor
  562. ASSERT_FORCE(PR_Close(sock->ssl_prfd) == PR_SUCCESS)
  563. }
  564. // free socket
  565. BSocket_Free(&sock->sock);
  566. }
  567. int StreamPeerIO_Init (
  568. StreamPeerIO *pio,
  569. BReactor *reactor,
  570. int ssl,
  571. uint8_t *ssl_peer_cert,
  572. int ssl_peer_cert_len,
  573. int payload_mtu,
  574. PacketPassInterface *user_recv_if,
  575. StreamPeerIO_handler_error handler_error,
  576. void *user
  577. )
  578. {
  579. ASSERT(ssl == 0 || ssl == 1)
  580. ASSERT(payload_mtu >= 0)
  581. ASSERT(PacketPassInterface_GetMTU(user_recv_if) >= payload_mtu)
  582. // init arguments
  583. pio->reactor = reactor;
  584. pio->ssl = ssl;
  585. if (pio->ssl) {
  586. pio->ssl_peer_cert = ssl_peer_cert;
  587. pio->ssl_peer_cert_len = ssl_peer_cert_len;
  588. }
  589. pio->payload_mtu = payload_mtu;
  590. pio->handler_error = handler_error;
  591. pio->user = user;
  592. // init dead variable
  593. DEAD_INIT(pio->dead);
  594. // init persistent I/O modules
  595. if (!init_persistent_io(pio, user_recv_if)) {
  596. return 0;
  597. }
  598. // set mode none
  599. pio->mode = MODE_NONE;
  600. // set no socket
  601. pio->sock = NULL;
  602. // init debug object
  603. DebugObject_Init(&pio->d_obj);
  604. return 1;
  605. }
  606. void StreamPeerIO_Free (StreamPeerIO *pio)
  607. {
  608. // free debug object
  609. DebugObject_Free(&pio->d_obj);
  610. // reset state
  611. reset_state(pio);
  612. // free persistent I/O modules
  613. free_persistent_io(pio);
  614. // kill dead variable
  615. DEAD_KILL(pio->dead);
  616. }
  617. PacketPassInterface * StreamPeerIO_GetSendInput (StreamPeerIO *pio)
  618. {
  619. return PacketCopier_GetInput(&pio->output_user_copier);
  620. }
  621. int StreamPeerIO_Connect (StreamPeerIO *pio, BAddr addr, uint64_t password, CERTCertificate *ssl_cert, SECKEYPrivateKey *ssl_key)
  622. {
  623. ASSERT(BAddr_IsRecognized(&addr) && !BAddr_IsInvalid(&addr))
  624. // reset state
  625. reset_state(pio);
  626. // create socket
  627. if (BSocket_Init(&pio->connect.sock.sock, pio->reactor, addr.type, BSOCKET_TYPE_STREAM) < 0) {
  628. BLog(BLOG_ERROR, "BSocket_Init failed");
  629. goto fail0;
  630. }
  631. // attempt connection
  632. if (BSocket_Connect(&pio->connect.sock.sock, &addr) >= 0 || BSocket_GetError(&pio->connect.sock.sock) != BSOCKET_ERROR_IN_PROGRESS) {
  633. BLog(BLOG_NOTICE, "BSocket_Connect failed");
  634. goto fail1;
  635. }
  636. // waiting for connection result
  637. BSocket_AddEventHandler(&pio->connect.sock.sock, BSOCKET_CONNECT, (BSocket_handler)connecting_connect_handler, pio);
  638. BSocket_EnableEvent(&pio->connect.sock.sock, BSOCKET_CONNECT);
  639. // remember data
  640. if (pio->ssl) {
  641. pio->connect.ssl_cert = ssl_cert;
  642. pio->connect.ssl_key = ssl_key;
  643. }
  644. pio->connect.connecting_password = htol64(password);
  645. // set state
  646. pio->mode = MODE_CONNECT;
  647. DEAD_INIT(pio->mode_dead);
  648. pio->connect.state = CONNECT_STATE_CONNECTING;
  649. return 1;
  650. fail1:
  651. BSocket_Free(&pio->connect.sock.sock);
  652. fail0:
  653. return 0;
  654. }
  655. void StreamPeerIO_Listen (StreamPeerIO *pio, PasswordListener *listener, uint64_t *password)
  656. {
  657. ASSERT(listener->ssl == pio->ssl)
  658. // reset state
  659. reset_state(pio);
  660. // add PasswordListener entry
  661. uint64_t newpass = PasswordListener_AddEntry(listener, &pio->listen.pwentry, (PasswordListener_handler_client)listener_handler_client, pio);
  662. // remember data
  663. pio->listen.listener = listener;
  664. // set state
  665. pio->mode = MODE_LISTEN;
  666. DEAD_INIT(pio->mode_dead);
  667. pio->listen.state = LISTEN_STATE_LISTENER;
  668. *password = newpass;
  669. }