ustream-ssl.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /*
  2. * ustream-ssl - library for SSL over ustream
  3. *
  4. * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
  5. *
  6. * Permission to use, copy, modify, and/or distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. #include <errno.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <libubox/ustream.h>
  22. #include "ustream-ssl.h"
  23. #include "ustream-internal.h"
  24. static void ustream_ssl_error_cb(struct uloop_timeout *t)
  25. {
  26. struct ustream_ssl *us = container_of(t, struct ustream_ssl, error_timer);
  27. static char buffer[128];
  28. int error = us->error;
  29. if (us->notify_error)
  30. us->notify_error(us, error, __ustream_ssl_strerror(us->error, buffer, sizeof(buffer)));
  31. }
  32. static void ustream_ssl_check_conn(struct ustream_ssl *us)
  33. {
  34. if (us->connected || us->error)
  35. return;
  36. if (__ustream_ssl_connect(us) == U_SSL_OK) {
  37. /* __ustream_ssl_connect() will also return U_SSL_OK when certificate
  38. * verification failed!
  39. *
  40. * Applications may register a custom .notify_verify_error callback in the
  41. * struct ustream_ssl which is called upon verification failures, but there
  42. * is no straight forward way for the callback to terminate the connection
  43. * initiation right away, e.g. through a true or false return value.
  44. *
  45. * Instead, existing implementations appear to set .eof field of the underlying
  46. * ustream in the hope that this inhibits further operations on the stream.
  47. *
  48. * Declare this informal behaviour "official" and check for the state of the
  49. * .eof member after __ustream_ssl_connect() returned, and do not write the
  50. * pending data if it is set to true.
  51. */
  52. if (us->stream.eof)
  53. return;
  54. us->connected = true;
  55. if (us->notify_connected)
  56. us->notify_connected(us);
  57. ustream_write_pending(&us->stream);
  58. }
  59. }
  60. static bool __ustream_ssl_poll(struct ustream_ssl *us)
  61. {
  62. char *buf;
  63. int len, ret;
  64. bool more = false;
  65. ustream_ssl_check_conn(us);
  66. if (!us->connected || us->error)
  67. return false;
  68. do {
  69. buf = ustream_reserve(&us->stream, 1, &len);
  70. if (!len)
  71. break;
  72. ret = __ustream_ssl_read(us, buf, len);
  73. if (ret == U_SSL_PENDING) {
  74. if (us->conn)
  75. ustream_poll(us->conn);
  76. ret = __ustream_ssl_read(us, buf, len);
  77. }
  78. switch (ret) {
  79. case U_SSL_PENDING:
  80. return more;
  81. case U_SSL_ERROR:
  82. return false;
  83. case 0:
  84. us->stream.eof = true;
  85. ustream_state_change(&us->stream);
  86. return false;
  87. default:
  88. ustream_fill_read(&us->stream, ret);
  89. more = true;
  90. continue;
  91. }
  92. } while (1);
  93. return more;
  94. }
  95. static void ustream_ssl_notify_read(struct ustream *s, int bytes)
  96. {
  97. struct ustream_ssl *us = container_of(s->next, struct ustream_ssl, stream);
  98. __ustream_ssl_poll(us);
  99. }
  100. static void ustream_ssl_notify_write(struct ustream *s, int bytes)
  101. {
  102. struct ustream_ssl *us = container_of(s->next, struct ustream_ssl, stream);
  103. ustream_ssl_check_conn(us);
  104. ustream_write_pending(s->next);
  105. }
  106. static void ustream_ssl_notify_state(struct ustream *s)
  107. {
  108. s->next->write_error = true;
  109. ustream_state_change(s->next);
  110. }
  111. static int ustream_ssl_write(struct ustream *s, const char *buf, int len, bool more)
  112. {
  113. struct ustream_ssl *us = container_of(s, struct ustream_ssl, stream);
  114. if (!us->connected || us->error)
  115. return 0;
  116. if (us->conn && us->conn->w.data_bytes)
  117. return 0;
  118. return __ustream_ssl_write(us, buf, len);
  119. }
  120. static void ustream_ssl_set_read_blocked(struct ustream *s)
  121. {
  122. struct ustream_ssl *us = container_of(s, struct ustream_ssl, stream);
  123. unsigned int ev = ULOOP_WRITE | ULOOP_EDGE_TRIGGER;
  124. if (us->conn) {
  125. ustream_set_read_blocked(us->conn, !!s->read_blocked);
  126. return;
  127. }
  128. if (!s->read_blocked)
  129. ev |= ULOOP_READ;
  130. uloop_fd_add(&us->fd, ev);
  131. }
  132. static void ustream_ssl_free(struct ustream *s)
  133. {
  134. struct ustream_ssl *us = container_of(s, struct ustream_ssl, stream);
  135. if (us->conn) {
  136. us->conn->next = NULL;
  137. us->conn->notify_read = NULL;
  138. us->conn->notify_write = NULL;
  139. us->conn->notify_state = NULL;
  140. } else {
  141. uloop_fd_delete(&us->fd);
  142. }
  143. uloop_timeout_cancel(&us->error_timer);
  144. __ustream_ssl_session_free(us);
  145. free(us->peer_cn);
  146. us->ctx = NULL;
  147. us->ssl = NULL;
  148. us->conn = NULL;
  149. us->peer_cn = NULL;
  150. us->connected = false;
  151. us->error = false;
  152. us->valid_cert = false;
  153. us->valid_cn = false;
  154. }
  155. static bool ustream_ssl_poll(struct ustream *s)
  156. {
  157. struct ustream_ssl *us = container_of(s, struct ustream_ssl, stream);
  158. bool fd_poll = false;
  159. if (us->conn)
  160. fd_poll = ustream_poll(us->conn);
  161. return __ustream_ssl_poll(us) || fd_poll;
  162. }
  163. static void ustream_ssl_fd_cb(struct uloop_fd *fd, unsigned int events)
  164. {
  165. struct ustream_ssl *us = container_of(fd, struct ustream_ssl, fd);
  166. __ustream_ssl_poll(us);
  167. }
  168. static void ustream_ssl_stream_init(struct ustream_ssl *us)
  169. {
  170. struct ustream *conn = us->conn;
  171. struct ustream *s = &us->stream;
  172. if (conn) {
  173. conn->notify_read = ustream_ssl_notify_read;
  174. conn->notify_write = ustream_ssl_notify_write;
  175. conn->notify_state = ustream_ssl_notify_state;
  176. } else {
  177. us->fd.cb = ustream_ssl_fd_cb;
  178. uloop_fd_add(&us->fd, ULOOP_READ | ULOOP_WRITE | ULOOP_EDGE_TRIGGER);
  179. }
  180. s->set_read_blocked = ustream_ssl_set_read_blocked;
  181. s->free = ustream_ssl_free;
  182. s->write = ustream_ssl_write;
  183. s->poll = ustream_ssl_poll;
  184. ustream_init_defaults(s);
  185. }
  186. static int _ustream_ssl_init_common(struct ustream_ssl *us)
  187. {
  188. us->error_timer.cb = ustream_ssl_error_cb;
  189. us->ssl = __ustream_ssl_session_new(us->ctx);
  190. if (!us->ssl)
  191. return -ENOMEM;
  192. ustream_set_io(us);
  193. ustream_ssl_stream_init(us);
  194. if (us->server_name)
  195. __ustream_ssl_set_server_name(us);
  196. ustream_ssl_check_conn(us);
  197. return 0;
  198. }
  199. static int _ustream_ssl_init_fd(struct ustream_ssl *us, int fd, struct ustream_ssl_ctx *ctx, bool server)
  200. {
  201. us->server = server;
  202. us->ctx = ctx;
  203. us->fd.fd = fd;
  204. return _ustream_ssl_init_common(us);
  205. }
  206. static int _ustream_ssl_init(struct ustream_ssl *us, struct ustream *conn, struct ustream_ssl_ctx *ctx, bool server)
  207. {
  208. us->server = server;
  209. us->ctx = ctx;
  210. us->conn = conn;
  211. conn->r.max_buffers = 4;
  212. conn->next = &us->stream;
  213. return _ustream_ssl_init_common(us);
  214. }
  215. static int _ustream_ssl_set_peer_cn(struct ustream_ssl *us, const char *name)
  216. {
  217. us->peer_cn = strdup(name);
  218. __ustream_ssl_update_peer_cn(us);
  219. return 0;
  220. }
  221. const struct ustream_ssl_ops ustream_ssl_ops = {
  222. .context_new = __ustream_ssl_context_new,
  223. .context_set_crt_file = __ustream_ssl_set_crt_file,
  224. .context_set_key_file = __ustream_ssl_set_key_file,
  225. .context_add_ca_crt_file = __ustream_ssl_add_ca_crt_file,
  226. .context_set_ciphers = __ustream_ssl_set_ciphers,
  227. .context_set_require_validation = __ustream_ssl_set_require_validation,
  228. .context_set_debug = __ustream_ssl_set_debug,
  229. .context_free = __ustream_ssl_context_free,
  230. .init = _ustream_ssl_init,
  231. .init_fd = _ustream_ssl_init_fd,
  232. .set_peer_cn = _ustream_ssl_set_peer_cn,
  233. };