1
0

tls-socket.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /*
  2. * nixio - Linux I/O library for lua
  3. *
  4. * Copyright (C) 2009 Steven Barth <steven@midlink.org>
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. #include "nixio-tls.h"
  19. #include <string.h>
  20. #include <stdlib.h>
  21. static int nixio__tls_sock_perror(lua_State *L, SSL *sock, int code) {
  22. lua_pushnil(L);
  23. lua_pushinteger(L, SSL_get_error(sock, code));
  24. return 2;
  25. }
  26. static int nixio__tls_sock_pstatus(lua_State *L, SSL *sock, int code) {
  27. if (code > 0) {
  28. lua_pushboolean(L, 1);
  29. return 1;
  30. } else {
  31. return nixio__tls_sock_perror(L, sock, code);
  32. }
  33. }
  34. static SSL* nixio__checktlssock(lua_State *L) {
  35. if (lua_istable(L, 1)) {
  36. lua_getfield(L, 1, "connection");
  37. lua_replace(L, 1);
  38. }
  39. nixio_tls_sock *sock = luaL_checkudata(L, 1, NIXIO_TLS_SOCK_META);
  40. luaL_argcheck(L, sock->socket, 1, "invalid context");
  41. return sock->socket;
  42. }
  43. #ifndef WITH_AXTLS
  44. #define nixio_tls__check_connected(L) ;
  45. #define nixio_tls__set_connected(L, val) ;
  46. #else
  47. #define nixio_tls__check_connected(L) \
  48. nixio_tls_sock *ctsock = luaL_checkudata(L, 1, NIXIO_TLS_SOCK_META); \
  49. if (!ctsock->connected) { \
  50. lua_pushnil(L); \
  51. lua_pushinteger(L, 1); \
  52. return 2; \
  53. }
  54. #define nixio_tls__set_connected(L, val) \
  55. ((nixio_tls_sock*)luaL_checkudata(L, 1, NIXIO_TLS_SOCK_META))->connected = val;
  56. #endif /* WITH_AXTLS */
  57. static int nixio_tls_sock_recv(lua_State *L) {
  58. SSL *sock = nixio__checktlssock(L);
  59. nixio_tls__check_connected(L);
  60. uint req = luaL_checkinteger(L, 2);
  61. luaL_argcheck(L, req >= 0, 2, "out of range");
  62. /* We limit the readsize to NIXIO_BUFFERSIZE */
  63. req = (req > NIXIO_BUFFERSIZE) ? NIXIO_BUFFERSIZE : req;
  64. #ifndef WITH_AXTLS
  65. char buffer[NIXIO_BUFFERSIZE];
  66. int readc = SSL_read(sock, buffer, req);
  67. if (readc < 0) {
  68. return nixio__tls_sock_pstatus(L, sock, readc);
  69. } else {
  70. lua_pushlstring(L, buffer, readc);
  71. return 1;
  72. }
  73. #else
  74. if (!req) {
  75. lua_pushliteral(L, "");
  76. return 1;
  77. }
  78. nixio_tls_sock *t = lua_touserdata(L, 1);
  79. /* AXTLS doesn't handle buffering for us, so we have to hack around*/
  80. if (req < t->pbufsiz) {
  81. lua_pushlstring(L, t->pbufpos, req);
  82. t->pbufpos += req;
  83. t->pbufsiz -= req;
  84. return 1;
  85. } else {
  86. uint8_t *axbuf;
  87. int axread;
  88. /* while handshake pending */
  89. while ((axread = ssl_read(sock, &axbuf)) == SSL_OK);
  90. if (t->pbufsiz) {
  91. lua_pushlstring(L, t->pbufpos, t->pbufsiz);
  92. }
  93. if (axread < 0) {
  94. /* There is an error */
  95. free(t->pbuffer);
  96. t->pbuffer = t->pbufpos = NULL;
  97. if (axread != SSL_ERROR_CONN_LOST) {
  98. t->pbufsiz = 0;
  99. return nixio__tls_sock_perror(L, sock, axread);
  100. } else {
  101. if (!t->pbufsiz) {
  102. lua_pushliteral(L, "");
  103. } else {
  104. t->pbufsiz = 0;
  105. }
  106. }
  107. } else {
  108. int stillwant = req - t->pbufsiz;
  109. if (stillwant < axread) {
  110. /* we got more data than we need */
  111. lua_pushlstring(L, (char *)axbuf, stillwant);
  112. if(t->pbufsiz) {
  113. lua_concat(L, 2);
  114. }
  115. /* remaining data goes into the buffer */
  116. t->pbufpos = t->pbuffer;
  117. t->pbufsiz = axread - stillwant;
  118. t->pbuffer = realloc(t->pbuffer, t->pbufsiz);
  119. if (!t->pbuffer) {
  120. free(t->pbufpos);
  121. t->pbufpos = NULL;
  122. t->pbufsiz = 0;
  123. return luaL_error(L, "out of memory");
  124. }
  125. t->pbufpos = t->pbuffer;
  126. memcpy(t->pbufpos, axbuf + stillwant, t->pbufsiz);
  127. } else {
  128. lua_pushlstring(L, (char *)axbuf, axread);
  129. if(t->pbufsiz) {
  130. lua_concat(L, 2);
  131. }
  132. /* free buffer */
  133. free(t->pbuffer);
  134. t->pbuffer = t->pbufpos = NULL;
  135. t->pbufsiz = 0;
  136. }
  137. }
  138. return 1;
  139. }
  140. #endif /* WITH_AXTLS */
  141. }
  142. static int nixio_tls_sock_send(lua_State *L) {
  143. SSL *sock = nixio__checktlssock(L);
  144. nixio_tls__check_connected(L);
  145. size_t len;
  146. ssize_t sent;
  147. const char *data = luaL_checklstring(L, 2, &len);
  148. if (lua_gettop(L) > 2) {
  149. int offset = luaL_optint(L, 3, 0);
  150. if (offset) {
  151. if (offset < len) {
  152. data += offset;
  153. len -= offset;
  154. } else {
  155. len = 0;
  156. }
  157. }
  158. unsigned int wlen = luaL_optint(L, 4, len);
  159. if (wlen < len) {
  160. len = wlen;
  161. }
  162. }
  163. sent = SSL_write(sock, data, len);
  164. if (sent > 0) {
  165. lua_pushinteger(L, sent);
  166. return 1;
  167. } else {
  168. return nixio__tls_sock_pstatus(L, sock, sent);
  169. }
  170. }
  171. static int nixio_tls_sock_accept(lua_State *L) {
  172. SSL *sock = nixio__checktlssock(L);
  173. const int stat = SSL_accept(sock);
  174. nixio_tls__set_connected(L, stat == 1);
  175. return nixio__tls_sock_pstatus(L, sock, stat);
  176. }
  177. static int nixio_tls_sock_connect(lua_State *L) {
  178. SSL *sock = nixio__checktlssock(L);
  179. const int stat = SSL_connect(sock);
  180. nixio_tls__set_connected(L, stat == 1);
  181. return nixio__tls_sock_pstatus(L, sock, stat);
  182. }
  183. static int nixio_tls_sock_shutdown(lua_State *L) {
  184. SSL *sock = nixio__checktlssock(L);
  185. nixio_tls__set_connected(L, 0);
  186. return nixio__tls_sock_pstatus(L, sock, SSL_shutdown(sock));
  187. }
  188. static int nixio_tls_sock__gc(lua_State *L) {
  189. nixio_tls_sock *sock = luaL_checkudata(L, 1, NIXIO_TLS_SOCK_META);
  190. if (sock->socket) {
  191. SSL_free(sock->socket);
  192. sock->socket = NULL;
  193. #ifdef WITH_AXTLS
  194. free(sock->pbuffer);
  195. #endif
  196. }
  197. return 0;
  198. }
  199. static int nixio_tls_sock__tostring(lua_State *L) {
  200. SSL *sock = nixio__checktlssock(L);
  201. lua_pushfstring(L, "nixio TLS connection: %p", sock);
  202. return 1;
  203. }
  204. /* ctx function table */
  205. static const luaL_Reg M[] = {
  206. {"recv", nixio_tls_sock_recv},
  207. {"send", nixio_tls_sock_send},
  208. {"read", nixio_tls_sock_recv},
  209. {"write", nixio_tls_sock_send},
  210. {"accept", nixio_tls_sock_accept},
  211. {"connect", nixio_tls_sock_connect},
  212. {"shutdown", nixio_tls_sock_shutdown},
  213. {"__gc", nixio_tls_sock__gc},
  214. {"__tostring", nixio_tls_sock__tostring},
  215. {NULL, NULL}
  216. };
  217. void nixio_open_tls_socket(lua_State *L) {
  218. /* create socket metatable */
  219. luaL_newmetatable(L, NIXIO_TLS_SOCK_META);
  220. luaL_register(L, NULL, M);
  221. lua_pushvalue(L, -1);
  222. lua_setfield(L, -2, "__index");
  223. lua_setfield(L, -2, "meta_tls_socket");
  224. }