bss_conn.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. /* crypto/bio/bss_conn.c */
  2. /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  3. * All rights reserved.
  4. *
  5. * This package is an SSL implementation written
  6. * by Eric Young (eay@cryptsoft.com).
  7. * The implementation was written so as to conform with Netscapes SSL.
  8. *
  9. * This library is free for commercial and non-commercial use as long as
  10. * the following conditions are aheared to. The following conditions
  11. * apply to all code found in this distribution, be it the RC4, RSA,
  12. * lhash, DES, etc., code; not just the SSL code. The SSL documentation
  13. * included with this distribution is covered by the same copyright terms
  14. * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  15. *
  16. * Copyright remains Eric Young's, and as such any Copyright notices in
  17. * the code are not to be removed.
  18. * If this package is used in a product, Eric Young should be given attribution
  19. * as the author of the parts of the library used.
  20. * This can be in the form of a textual message at program startup or
  21. * in documentation (online or textual) provided with the package.
  22. *
  23. * Redistribution and use in source and binary forms, with or without
  24. * modification, are permitted provided that the following conditions
  25. * are met:
  26. * 1. Redistributions of source code must retain the copyright
  27. * notice, this list of conditions and the following disclaimer.
  28. * 2. Redistributions in binary form must reproduce the above copyright
  29. * notice, this list of conditions and the following disclaimer in the
  30. * documentation and/or other materials provided with the distribution.
  31. * 3. All advertising materials mentioning features or use of this software
  32. * must display the following acknowledgement:
  33. * "This product includes cryptographic software written by
  34. * Eric Young (eay@cryptsoft.com)"
  35. * The word 'cryptographic' can be left out if the rouines from the library
  36. * being used are not cryptographic related :-).
  37. * 4. If you include any Windows specific code (or a derivative thereof) from
  38. * the apps directory (application code) you must include an acknowledgement:
  39. * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  40. *
  41. * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  42. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  43. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  44. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  45. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  46. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  47. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  48. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  49. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  50. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  51. * SUCH DAMAGE.
  52. *
  53. * The licence and distribution terms for any publically available version or
  54. * derivative of this code cannot be changed. i.e. this code cannot simply be
  55. * copied and put under another distribution licence
  56. * [including the GNU Public Licence.]
  57. */
  58. #include <stdio.h>
  59. #include <errno.h>
  60. #define USE_SOCKETS
  61. #include "cryptlib.h"
  62. #include <openssl/bio.h>
  63. #ifndef OPENSSL_NO_SOCK
  64. # ifdef OPENSSL_SYS_WIN16
  65. # define SOCKET_PROTOCOL 0 /* more microsoft stupidity */
  66. # else
  67. # define SOCKET_PROTOCOL IPPROTO_TCP
  68. # endif
  69. # if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000)
  70. /* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */
  71. # undef FIONBIO
  72. # endif
  73. typedef struct bio_connect_st {
  74. int state;
  75. char *param_hostname;
  76. char *param_port;
  77. int nbio;
  78. unsigned char ip[4];
  79. unsigned short port;
  80. struct sockaddr_in them;
  81. /*
  82. * int socket; this will be kept in bio->num so that it is compatible
  83. * with the bss_sock bio
  84. */
  85. /*
  86. * called when the connection is initially made callback(BIO,state,ret);
  87. * The callback should return 'ret'. state is for compatibility with the
  88. * ssl info_callback
  89. */
  90. int (*info_callback) (const BIO *bio, int state, int ret);
  91. } BIO_CONNECT;
  92. static int conn_write(BIO *h, const char *buf, int num);
  93. static int conn_read(BIO *h, char *buf, int size);
  94. static int conn_puts(BIO *h, const char *str);
  95. static long conn_ctrl(BIO *h, int cmd, long arg1, void *arg2);
  96. static int conn_new(BIO *h);
  97. static int conn_free(BIO *data);
  98. static long conn_callback_ctrl(BIO *h, int cmd, bio_info_cb *);
  99. static int conn_state(BIO *b, BIO_CONNECT *c);
  100. static void conn_close_socket(BIO *data);
  101. BIO_CONNECT *BIO_CONNECT_new(void);
  102. void BIO_CONNECT_free(BIO_CONNECT *a);
  103. static BIO_METHOD methods_connectp = {
  104. BIO_TYPE_CONNECT,
  105. "socket connect",
  106. conn_write,
  107. conn_read,
  108. conn_puts,
  109. NULL, /* connect_gets, */
  110. conn_ctrl,
  111. conn_new,
  112. conn_free,
  113. conn_callback_ctrl,
  114. };
  115. static int conn_state(BIO *b, BIO_CONNECT *c)
  116. {
  117. int ret = -1, i;
  118. unsigned long l;
  119. char *p, *q;
  120. int (*cb) (const BIO *, int, int) = NULL;
  121. if (c->info_callback != NULL)
  122. cb = c->info_callback;
  123. for (;;) {
  124. switch (c->state) {
  125. case BIO_CONN_S_BEFORE:
  126. p = c->param_hostname;
  127. if (p == NULL) {
  128. BIOerr(BIO_F_CONN_STATE, BIO_R_NO_HOSTNAME_SPECIFIED);
  129. goto exit_loop;
  130. }
  131. for (; *p != '\0'; p++) {
  132. if ((*p == ':') || (*p == '/'))
  133. break;
  134. }
  135. i = *p;
  136. if ((i == ':') || (i == '/')) {
  137. *(p++) = '\0';
  138. if (i == ':') {
  139. for (q = p; *q; q++)
  140. if (*q == '/') {
  141. *q = '\0';
  142. break;
  143. }
  144. if (c->param_port != NULL)
  145. OPENSSL_free(c->param_port);
  146. c->param_port = BUF_strdup(p);
  147. }
  148. }
  149. if (c->param_port == NULL) {
  150. BIOerr(BIO_F_CONN_STATE, BIO_R_NO_PORT_SPECIFIED);
  151. ERR_add_error_data(2, "host=", c->param_hostname);
  152. goto exit_loop;
  153. }
  154. c->state = BIO_CONN_S_GET_IP;
  155. break;
  156. case BIO_CONN_S_GET_IP:
  157. if (BIO_get_host_ip(c->param_hostname, &(c->ip[0])) <= 0)
  158. goto exit_loop;
  159. c->state = BIO_CONN_S_GET_PORT;
  160. break;
  161. case BIO_CONN_S_GET_PORT:
  162. if (c->param_port == NULL) {
  163. /* abort(); */
  164. goto exit_loop;
  165. } else if (BIO_get_port(c->param_port, &c->port) <= 0)
  166. goto exit_loop;
  167. c->state = BIO_CONN_S_CREATE_SOCKET;
  168. break;
  169. case BIO_CONN_S_CREATE_SOCKET:
  170. /* now setup address */
  171. memset((char *)&c->them, 0, sizeof(c->them));
  172. c->them.sin_family = AF_INET;
  173. c->them.sin_port = htons((unsigned short)c->port);
  174. l = (unsigned long)
  175. ((unsigned long)c->ip[0] << 24L) |
  176. ((unsigned long)c->ip[1] << 16L) |
  177. ((unsigned long)c->ip[2] << 8L) | ((unsigned long)c->ip[3]);
  178. c->them.sin_addr.s_addr = htonl(l);
  179. c->state = BIO_CONN_S_CREATE_SOCKET;
  180. ret = socket(AF_INET, SOCK_STREAM, SOCKET_PROTOCOL);
  181. if (ret == INVALID_SOCKET) {
  182. SYSerr(SYS_F_SOCKET, get_last_socket_error());
  183. ERR_add_error_data(4, "host=", c->param_hostname,
  184. ":", c->param_port);
  185. BIOerr(BIO_F_CONN_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET);
  186. goto exit_loop;
  187. }
  188. b->num = ret;
  189. c->state = BIO_CONN_S_NBIO;
  190. break;
  191. case BIO_CONN_S_NBIO:
  192. if (c->nbio) {
  193. if (!BIO_socket_nbio(b->num, 1)) {
  194. BIOerr(BIO_F_CONN_STATE, BIO_R_ERROR_SETTING_NBIO);
  195. ERR_add_error_data(4, "host=",
  196. c->param_hostname, ":", c->param_port);
  197. goto exit_loop;
  198. }
  199. }
  200. c->state = BIO_CONN_S_CONNECT;
  201. # if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE)
  202. i = 1;
  203. i = setsockopt(b->num, SOL_SOCKET, SO_KEEPALIVE, (char *)&i,
  204. sizeof(i));
  205. if (i < 0) {
  206. SYSerr(SYS_F_SOCKET, get_last_socket_error());
  207. ERR_add_error_data(4, "host=", c->param_hostname,
  208. ":", c->param_port);
  209. BIOerr(BIO_F_CONN_STATE, BIO_R_KEEPALIVE);
  210. goto exit_loop;
  211. }
  212. # endif
  213. break;
  214. case BIO_CONN_S_CONNECT:
  215. BIO_clear_retry_flags(b);
  216. ret = connect(b->num,
  217. (struct sockaddr *)&c->them, sizeof(c->them));
  218. b->retry_reason = 0;
  219. if (ret < 0) {
  220. if (BIO_sock_should_retry(ret)) {
  221. BIO_set_retry_special(b);
  222. c->state = BIO_CONN_S_BLOCKED_CONNECT;
  223. b->retry_reason = BIO_RR_CONNECT;
  224. } else {
  225. SYSerr(SYS_F_CONNECT, get_last_socket_error());
  226. ERR_add_error_data(4, "host=",
  227. c->param_hostname, ":", c->param_port);
  228. BIOerr(BIO_F_CONN_STATE, BIO_R_CONNECT_ERROR);
  229. }
  230. goto exit_loop;
  231. } else
  232. c->state = BIO_CONN_S_OK;
  233. break;
  234. case BIO_CONN_S_BLOCKED_CONNECT:
  235. i = BIO_sock_error(b->num);
  236. if (i) {
  237. BIO_clear_retry_flags(b);
  238. SYSerr(SYS_F_CONNECT, i);
  239. ERR_add_error_data(4, "host=",
  240. c->param_hostname, ":", c->param_port);
  241. BIOerr(BIO_F_CONN_STATE, BIO_R_NBIO_CONNECT_ERROR);
  242. ret = 0;
  243. goto exit_loop;
  244. } else
  245. c->state = BIO_CONN_S_OK;
  246. break;
  247. case BIO_CONN_S_OK:
  248. ret = 1;
  249. goto exit_loop;
  250. default:
  251. /* abort(); */
  252. goto exit_loop;
  253. }
  254. if (cb != NULL) {
  255. if (!(ret = cb((BIO *)b, c->state, ret)))
  256. goto end;
  257. }
  258. }
  259. /* Loop does not exit */
  260. exit_loop:
  261. if (cb != NULL)
  262. ret = cb((BIO *)b, c->state, ret);
  263. end:
  264. return (ret);
  265. }
  266. BIO_CONNECT *BIO_CONNECT_new(void)
  267. {
  268. BIO_CONNECT *ret;
  269. if ((ret = (BIO_CONNECT *)OPENSSL_malloc(sizeof(BIO_CONNECT))) == NULL)
  270. return (NULL);
  271. ret->state = BIO_CONN_S_BEFORE;
  272. ret->param_hostname = NULL;
  273. ret->param_port = NULL;
  274. ret->info_callback = NULL;
  275. ret->nbio = 0;
  276. ret->ip[0] = 0;
  277. ret->ip[1] = 0;
  278. ret->ip[2] = 0;
  279. ret->ip[3] = 0;
  280. ret->port = 0;
  281. memset((char *)&ret->them, 0, sizeof(ret->them));
  282. return (ret);
  283. }
  284. void BIO_CONNECT_free(BIO_CONNECT *a)
  285. {
  286. if (a == NULL)
  287. return;
  288. if (a->param_hostname != NULL)
  289. OPENSSL_free(a->param_hostname);
  290. if (a->param_port != NULL)
  291. OPENSSL_free(a->param_port);
  292. OPENSSL_free(a);
  293. }
  294. BIO_METHOD *BIO_s_connect(void)
  295. {
  296. return (&methods_connectp);
  297. }
  298. static int conn_new(BIO *bi)
  299. {
  300. bi->init = 0;
  301. bi->num = INVALID_SOCKET;
  302. bi->flags = 0;
  303. if ((bi->ptr = (char *)BIO_CONNECT_new()) == NULL)
  304. return (0);
  305. else
  306. return (1);
  307. }
  308. static void conn_close_socket(BIO *bio)
  309. {
  310. BIO_CONNECT *c;
  311. c = (BIO_CONNECT *)bio->ptr;
  312. if (bio->num != INVALID_SOCKET) {
  313. /* Only do a shutdown if things were established */
  314. if (c->state == BIO_CONN_S_OK)
  315. shutdown(bio->num, 2);
  316. closesocket(bio->num);
  317. bio->num = INVALID_SOCKET;
  318. }
  319. }
  320. static int conn_free(BIO *a)
  321. {
  322. BIO_CONNECT *data;
  323. if (a == NULL)
  324. return (0);
  325. data = (BIO_CONNECT *)a->ptr;
  326. if (a->shutdown) {
  327. conn_close_socket(a);
  328. BIO_CONNECT_free(data);
  329. a->ptr = NULL;
  330. a->flags = 0;
  331. a->init = 0;
  332. }
  333. return (1);
  334. }
  335. static int conn_read(BIO *b, char *out, int outl)
  336. {
  337. int ret = 0;
  338. BIO_CONNECT *data;
  339. data = (BIO_CONNECT *)b->ptr;
  340. if (data->state != BIO_CONN_S_OK) {
  341. ret = conn_state(b, data);
  342. if (ret <= 0)
  343. return (ret);
  344. }
  345. if (out != NULL) {
  346. clear_socket_error();
  347. ret = readsocket(b->num, out, outl);
  348. BIO_clear_retry_flags(b);
  349. if (ret <= 0) {
  350. if (BIO_sock_should_retry(ret))
  351. BIO_set_retry_read(b);
  352. }
  353. }
  354. return (ret);
  355. }
  356. static int conn_write(BIO *b, const char *in, int inl)
  357. {
  358. int ret;
  359. BIO_CONNECT *data;
  360. data = (BIO_CONNECT *)b->ptr;
  361. if (data->state != BIO_CONN_S_OK) {
  362. ret = conn_state(b, data);
  363. if (ret <= 0)
  364. return (ret);
  365. }
  366. clear_socket_error();
  367. ret = writesocket(b->num, in, inl);
  368. BIO_clear_retry_flags(b);
  369. if (ret <= 0) {
  370. if (BIO_sock_should_retry(ret))
  371. BIO_set_retry_write(b);
  372. }
  373. return (ret);
  374. }
  375. static long conn_ctrl(BIO *b, int cmd, long num, void *ptr)
  376. {
  377. BIO *dbio;
  378. int *ip;
  379. const char **pptr = NULL;
  380. long ret = 1;
  381. BIO_CONNECT *data;
  382. data = (BIO_CONNECT *)b->ptr;
  383. switch (cmd) {
  384. case BIO_CTRL_RESET:
  385. ret = 0;
  386. data->state = BIO_CONN_S_BEFORE;
  387. conn_close_socket(b);
  388. b->flags = 0;
  389. break;
  390. case BIO_C_DO_STATE_MACHINE:
  391. /* use this one to start the connection */
  392. if (data->state != BIO_CONN_S_OK)
  393. ret = (long)conn_state(b, data);
  394. else
  395. ret = 1;
  396. break;
  397. case BIO_C_GET_CONNECT:
  398. if (ptr != NULL) {
  399. pptr = (const char **)ptr;
  400. }
  401. if (b->init) {
  402. if (pptr != NULL) {
  403. ret = 1;
  404. if (num == 0) {
  405. *pptr = data->param_hostname;
  406. } else if (num == 1) {
  407. *pptr = data->param_port;
  408. } else if (num == 2) {
  409. *pptr = (char *)&(data->ip[0]);
  410. } else {
  411. ret = 0;
  412. }
  413. }
  414. if (num == 3) {
  415. ret = data->port;
  416. }
  417. } else {
  418. if (pptr != NULL)
  419. *pptr = "not initialized";
  420. ret = 0;
  421. }
  422. break;
  423. case BIO_C_SET_CONNECT:
  424. if (ptr != NULL) {
  425. b->init = 1;
  426. if (num == 0) {
  427. if (data->param_hostname != NULL)
  428. OPENSSL_free(data->param_hostname);
  429. data->param_hostname = BUF_strdup(ptr);
  430. } else if (num == 1) {
  431. if (data->param_port != NULL)
  432. OPENSSL_free(data->param_port);
  433. data->param_port = BUF_strdup(ptr);
  434. } else if (num == 2) {
  435. char buf[16];
  436. unsigned char *p = ptr;
  437. BIO_snprintf(buf, sizeof buf, "%d.%d.%d.%d",
  438. p[0], p[1], p[2], p[3]);
  439. if (data->param_hostname != NULL)
  440. OPENSSL_free(data->param_hostname);
  441. data->param_hostname = BUF_strdup(buf);
  442. memcpy(&(data->ip[0]), ptr, 4);
  443. } else if (num == 3) {
  444. char buf[DECIMAL_SIZE(int) + 1];
  445. BIO_snprintf(buf, sizeof buf, "%d", *(int *)ptr);
  446. if (data->param_port != NULL)
  447. OPENSSL_free(data->param_port);
  448. data->param_port = BUF_strdup(buf);
  449. data->port = *(int *)ptr;
  450. }
  451. }
  452. break;
  453. case BIO_C_SET_NBIO:
  454. data->nbio = (int)num;
  455. break;
  456. case BIO_C_GET_FD:
  457. if (b->init) {
  458. ip = (int *)ptr;
  459. if (ip != NULL)
  460. *ip = b->num;
  461. ret = b->num;
  462. } else
  463. ret = -1;
  464. break;
  465. case BIO_CTRL_GET_CLOSE:
  466. ret = b->shutdown;
  467. break;
  468. case BIO_CTRL_SET_CLOSE:
  469. b->shutdown = (int)num;
  470. break;
  471. case BIO_CTRL_PENDING:
  472. case BIO_CTRL_WPENDING:
  473. ret = 0;
  474. break;
  475. case BIO_CTRL_FLUSH:
  476. break;
  477. case BIO_CTRL_DUP:
  478. {
  479. dbio = (BIO *)ptr;
  480. if (data->param_port)
  481. BIO_set_conn_port(dbio, data->param_port);
  482. if (data->param_hostname)
  483. BIO_set_conn_hostname(dbio, data->param_hostname);
  484. BIO_set_nbio(dbio, data->nbio);
  485. /*
  486. * FIXME: the cast of the function seems unlikely to be a good
  487. * idea
  488. */
  489. (void)BIO_set_info_callback(dbio,
  490. (bio_info_cb *)data->info_callback);
  491. }
  492. break;
  493. case BIO_CTRL_SET_CALLBACK:
  494. {
  495. # if 0 /* FIXME: Should this be used? -- Richard
  496. * Levitte */
  497. BIOerr(BIO_F_CONN_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
  498. ret = -1;
  499. # else
  500. ret = 0;
  501. # endif
  502. }
  503. break;
  504. case BIO_CTRL_GET_CALLBACK:
  505. {
  506. int (**fptr) (const BIO *bio, int state, int xret);
  507. fptr = (int (**)(const BIO *bio, int state, int xret))ptr;
  508. *fptr = data->info_callback;
  509. }
  510. break;
  511. default:
  512. ret = 0;
  513. break;
  514. }
  515. return (ret);
  516. }
  517. static long conn_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
  518. {
  519. long ret = 1;
  520. BIO_CONNECT *data;
  521. data = (BIO_CONNECT *)b->ptr;
  522. switch (cmd) {
  523. case BIO_CTRL_SET_CALLBACK:
  524. {
  525. data->info_callback =
  526. (int (*)(const struct bio_st *, int, int))fp;
  527. }
  528. break;
  529. default:
  530. ret = 0;
  531. break;
  532. }
  533. return (ret);
  534. }
  535. static int conn_puts(BIO *bp, const char *str)
  536. {
  537. int n, ret;
  538. n = strlen(str);
  539. ret = conn_write(bp, str, n);
  540. return (ret);
  541. }
  542. BIO *BIO_new_connect(const char *str)
  543. {
  544. BIO *ret;
  545. ret = BIO_new(BIO_s_connect());
  546. if (ret == NULL)
  547. return (NULL);
  548. if (BIO_set_conn_hostname(ret, str))
  549. return (ret);
  550. else {
  551. BIO_free(ret);
  552. return (NULL);
  553. }
  554. }
  555. #endif