s_socket.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  2. * All rights reserved.
  3. *
  4. * This package is an SSL implementation written
  5. * by Eric Young (eay@cryptsoft.com).
  6. * The implementation was written so as to conform with Netscapes SSL.
  7. *
  8. * This library is free for commercial and non-commercial use as long as
  9. * the following conditions are aheared to. The following conditions
  10. * apply to all code found in this distribution, be it the RC4, RSA,
  11. * lhash, DES, etc., code; not just the SSL code. The SSL documentation
  12. * included with this distribution is covered by the same copyright terms
  13. * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  14. *
  15. * Copyright remains Eric Young's, and as such any Copyright notices in
  16. * the code are not to be removed.
  17. * If this package is used in a product, Eric Young should be given attribution
  18. * as the author of the parts of the library used.
  19. * This can be in the form of a textual message at program startup or
  20. * in documentation (online or textual) provided with the package.
  21. *
  22. * Redistribution and use in source and binary forms, with or without
  23. * modification, are permitted provided that the following conditions
  24. * are met:
  25. * 1. Redistributions of source code must retain the copyright
  26. * notice, this list of conditions and the following disclaimer.
  27. * 2. Redistributions in binary form must reproduce the above copyright
  28. * notice, this list of conditions and the following disclaimer in the
  29. * documentation and/or other materials provided with the distribution.
  30. * 3. All advertising materials mentioning features or use of this software
  31. * must display the following acknowledgement:
  32. * "This product includes cryptographic software written by
  33. * Eric Young (eay@cryptsoft.com)"
  34. * The word 'cryptographic' can be left out if the rouines from the library
  35. * being used are not cryptographic related :-).
  36. * 4. If you include any Windows specific code (or a derivative thereof) from
  37. * the apps directory (application code) you must include an acknowledgement:
  38. * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  39. *
  40. * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  41. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  42. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  43. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  44. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  45. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  46. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  47. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  48. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  49. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  50. * SUCH DAMAGE.
  51. *
  52. * The licence and distribution terms for any publically available version or
  53. * derivative of this code cannot be changed. i.e. this code cannot simply be
  54. * copied and put under another distribution licence
  55. * [including the GNU Public Licence.]
  56. */
  57. /* ====================================================================
  58. * Copyright (c) 199-2015 The OpenSSL Project. All rights reserved.
  59. *
  60. * Redistribution and use in source and binary forms, with or without
  61. * modification, are permitted provided that the following conditions
  62. * are met:
  63. *
  64. * 1. Redistributions of source code must retain the above copyright
  65. * notice, this list of conditions and the following disclaimer.
  66. *
  67. * 2. Redistributions in binary form must reproduce the above copyright
  68. * notice, this list of conditions and the following disclaimer in
  69. * the documentation and/or other materials provided with the
  70. * distribution.
  71. *
  72. * 3. All advertising materials mentioning features or use of this
  73. * software must display the following acknowledgment:
  74. * "This product includes software developed by the OpenSSL Project
  75. * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  76. *
  77. * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  78. * endorse or promote products derived from this software without
  79. * prior written permission. For written permission, please contact
  80. * licensing@OpenSSL.org.
  81. *
  82. * 5. Products derived from this software may not be called "OpenSSL"
  83. * nor may "OpenSSL" appear in their names without prior written
  84. * permission of the OpenSSL Project.
  85. *
  86. * 6. Redistributions of any form whatsoever must retain the following
  87. * acknowledgment:
  88. * "This product includes software developed by the OpenSSL Project
  89. * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  90. *
  91. * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  92. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  93. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  94. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
  95. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  96. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  97. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  98. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  99. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  100. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  101. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  102. * OF THE POSSIBILITY OF SUCH DAMAGE.
  103. * ====================================================================
  104. */
  105. /* socket-related functions used by s_client and s_server */
  106. #include <stdio.h>
  107. #include <stdlib.h>
  108. #include <string.h>
  109. #include <errno.h>
  110. #include <signal.h>
  111. /*
  112. * With IPv6, it looks like Digital has mixed up the proper order of
  113. * recursive header file inclusion, resulting in the compiler complaining
  114. * that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is
  115. * needed to have fileno() declared correctly... So let's define u_int
  116. */
  117. #if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT)
  118. # define __U_INT
  119. typedef unsigned int u_int;
  120. #endif
  121. #ifndef OPENSSL_NO_SOCK
  122. # define USE_SOCKETS
  123. # include "apps.h"
  124. # undef USE_SOCKETS
  125. # include "s_apps.h"
  126. # include <openssl/bio.h>
  127. # include <openssl/err.h>
  128. /*
  129. * init_client - helper routine to set up socket communication
  130. * @sock: pointer to storage of resulting socket.
  131. * @host: the host name or path (for AF_UNIX) to connect to.
  132. * @port: the port to connect to (ignored for AF_UNIX).
  133. * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or
  134. * AF_UNSPEC
  135. * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM
  136. *
  137. * This will create a socket and use it to connect to a host:port, or if
  138. * family == AF_UNIX, to the path found in host.
  139. *
  140. * If the host has more than one address, it will try them one by one until
  141. * a successful connection is established. The resulting socket will be
  142. * found in *sock on success, it will be given INVALID_SOCKET otherwise.
  143. *
  144. * Returns 1 on success, 0 on failure.
  145. */
  146. int init_client(int *sock, const char *host, const char *port,
  147. int family, int type)
  148. {
  149. BIO_ADDRINFO *res = NULL;
  150. const BIO_ADDRINFO *ai = NULL;
  151. int ret;
  152. if (!BIO_sock_init())
  153. return 0;
  154. ret = BIO_lookup(host, port, BIO_LOOKUP_CLIENT, family, type, &res);
  155. if (ret == 0) {
  156. ERR_print_errors(bio_err);
  157. return 0;
  158. }
  159. ret = 0;
  160. for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) {
  161. /* Admitedly, these checks are quite paranoid, we should
  162. not get anything in the BIO_ADDRINFO chain that we haven't
  163. asked for */
  164. OPENSSL_assert((family == AF_UNSPEC || family == BIO_ADDRINFO_family(res))
  165. && (type == 0 || type == BIO_ADDRINFO_socktype(res)));
  166. *sock = BIO_socket(BIO_ADDRINFO_family(ai), BIO_ADDRINFO_socktype(ai),
  167. BIO_ADDRINFO_protocol(res), 0);
  168. if (*sock == INVALID_SOCKET) {
  169. /* Maybe the kernel doesn't support the socket family, even if
  170. * BIO_lookup() added it in the returned result...
  171. */
  172. continue;
  173. }
  174. if (!BIO_connect(*sock, BIO_ADDRINFO_address(ai), 0)) {
  175. BIO_closesocket(*sock);
  176. *sock = INVALID_SOCKET;
  177. continue;
  178. }
  179. /* Success, don't try any more addresses */
  180. break;
  181. }
  182. if (*sock == INVALID_SOCKET) {
  183. ERR_print_errors(bio_err);
  184. } else {
  185. ret = 1;
  186. }
  187. BIO_ADDRINFO_free(res);
  188. return ret;
  189. }
  190. /*
  191. * do_server - helper routine to perform a server operation
  192. * @accept_sock: pointer to storage of resulting socket.
  193. * @host: the host name or path (for AF_UNIX) to connect to.
  194. * @port: the port to connect to (ignored for AF_UNIX).
  195. * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or
  196. * AF_UNSPEC
  197. * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM
  198. * @cb: pointer to a function that receives the accepted socket and
  199. * should perform the communication with the connecting client.
  200. * @context: pointer to memory that's passed verbatim to the cb function.
  201. * @naccept: number of times an incoming connect should be accepted. If -1,
  202. * unlimited number.
  203. *
  204. * This will create a socket and use it to listen to a host:port, or if
  205. * family == AF_UNIX, to the path found in host, then start accepting
  206. * incoming connections and run cb on the resulting socket.
  207. *
  208. * 0 on failure, something other on success.
  209. */
  210. int do_server(int *accept_sock, const char *host, const char *port,
  211. int family, int type,
  212. int (*cb) (const char *hostname, int s, int stype,
  213. unsigned char *context), unsigned char *context,
  214. int naccept)
  215. {
  216. int asock = 0;
  217. int sock;
  218. int i;
  219. BIO_ADDRINFO *res = NULL;
  220. int ret = 0;
  221. if (!BIO_sock_init())
  222. return 0;
  223. if (!BIO_lookup(host, port, BIO_LOOKUP_SERVER, family, type, &res)) {
  224. ERR_print_errors(bio_err);
  225. return 0;
  226. }
  227. /* Admitedly, these checks are quite paranoid, we should
  228. not get anything in the BIO_ADDRINFO chain that we haven't
  229. asked for */
  230. OPENSSL_assert((family == AF_UNSPEC || family == BIO_ADDRINFO_family(res))
  231. && (type == 0 || type == BIO_ADDRINFO_socktype(res)));
  232. asock = BIO_socket(BIO_ADDRINFO_family(res), BIO_ADDRINFO_socktype(res),
  233. BIO_ADDRINFO_protocol(res), 0);
  234. if (asock == INVALID_SOCKET
  235. || !BIO_listen(asock, BIO_ADDRINFO_address(res), BIO_SOCK_REUSEADDR)) {
  236. BIO_ADDRINFO_free(res);
  237. ERR_print_errors(bio_err);
  238. if (asock != INVALID_SOCKET)
  239. BIO_closesocket(asock);
  240. goto end;
  241. }
  242. BIO_ADDRINFO_free(res);
  243. if (accept_sock != NULL) {
  244. *accept_sock = asock;
  245. }
  246. for (;;) {
  247. BIO_ADDR *accepted_addr = NULL;
  248. char *name = NULL;
  249. if (type == SOCK_STREAM) {
  250. if ((accepted_addr = BIO_ADDR_new()) == NULL) {
  251. BIO_closesocket(asock);
  252. return 0;
  253. }
  254. redoit:
  255. sock = BIO_accept_ex(asock, accepted_addr, 0);
  256. if (sock < 0) {
  257. if (BIO_sock_should_retry(ret)) {
  258. goto redoit;
  259. } else {
  260. ERR_print_errors(bio_err);
  261. BIO_ADDR_free(accepted_addr);
  262. SHUTDOWN(asock);
  263. break;
  264. }
  265. }
  266. } else {
  267. sock = asock;
  268. }
  269. /* accepted_addr is NULL if we're dealing with SOCK_DGRAM
  270. * this means that for SOCK_DGRAM, name will be NULL
  271. */
  272. if (accepted_addr != NULL) {
  273. #ifdef AF_UNIX
  274. if (family == AF_UNIX)
  275. name = BIO_ADDR_path_string(accepted_addr);
  276. else
  277. #endif
  278. name = BIO_ADDR_hostname_string(accepted_addr, 0);
  279. }
  280. i = (*cb) (name, sock, type, context);
  281. OPENSSL_free(name);
  282. BIO_ADDR_free(accepted_addr);
  283. if (type == SOCK_STREAM)
  284. SHUTDOWN2(sock);
  285. if (naccept != -1)
  286. naccept--;
  287. if (i < 0 || naccept == 0) {
  288. SHUTDOWN2(asock);
  289. ret = i;
  290. break;
  291. }
  292. }
  293. end:
  294. # ifdef AF_UNIX
  295. if (family == AF_UNIX)
  296. unlink(host);
  297. # endif
  298. return ret;
  299. }
  300. #endif /* OPENSSL_NO_SOCK */