tls.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /*
  2. * uhttpd - Tiny single-threaded httpd
  3. *
  4. * Copyright (C) 2010-2013 Jo-Philipp Wich <xm@subsignal.org>
  5. * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
  6. *
  7. * Permission to use, copy, modify, and/or distribute this software for any
  8. * purpose with or without fee is hereby granted, provided that the above
  9. * copyright notice and this permission notice appear in all copies.
  10. *
  11. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  12. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  13. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  14. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  15. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  16. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  17. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  18. */
  19. #include <dlfcn.h>
  20. #include "uhttpd.h"
  21. #include "tls.h"
  22. #ifdef __APPLE__
  23. #define LIB_EXT "dylib"
  24. #else
  25. #define LIB_EXT "so"
  26. #endif
  27. static struct ustream_ssl_ops *ops;
  28. static void *dlh;
  29. static void *ctx;
  30. int uh_tls_init(const char *key, const char *crt, const char *ciphers)
  31. {
  32. static bool _init = false;
  33. if (_init)
  34. return 0;
  35. _init = true;
  36. dlh = dlopen("libustream-ssl." LIB_EXT, RTLD_LAZY | RTLD_LOCAL);
  37. if (!dlh) {
  38. fprintf(stderr, "Failed to load ustream-ssl library: %s\n", dlerror());
  39. return -ENOENT;
  40. }
  41. ops = dlsym(dlh, "ustream_ssl_ops");
  42. if (!ops) {
  43. fprintf(stderr, "Could not find required symbol 'ustream_ssl_ops' in ustream-ssl library\n");
  44. return -ENOENT;
  45. }
  46. ctx = ops->context_new(true);
  47. if (!ctx) {
  48. fprintf(stderr, "Failed to initialize ustream-ssl\n");
  49. return -EINVAL;
  50. }
  51. if (ops->context_set_crt_file(ctx, crt) ||
  52. ops->context_set_key_file(ctx, key)) {
  53. fprintf(stderr, "Failed to load certificate/key files\n");
  54. return -EINVAL;
  55. }
  56. if (ciphers && ops->context_set_ciphers(ctx, ciphers)) {
  57. fprintf(stderr, "No recognized ciphers in cipher list\n");
  58. return -EINVAL;
  59. }
  60. return 0;
  61. }
  62. static void tls_ustream_read_cb(struct ustream *s, int bytes)
  63. {
  64. struct client *cl = container_of(s, struct client, ssl.stream);
  65. uh_client_read_cb(cl);
  66. }
  67. static void tls_ustream_write_cb(struct ustream *s, int bytes)
  68. {
  69. struct client *cl = container_of(s, struct client, ssl.stream);
  70. if (cl->dispatch.write_cb)
  71. cl->dispatch.write_cb(cl);
  72. }
  73. static void tls_notify_state(struct ustream *s)
  74. {
  75. struct client *cl = container_of(s, struct client, ssl.stream);
  76. uh_client_notify_state(cl);
  77. }
  78. void uh_tls_client_attach(struct client *cl)
  79. {
  80. cl->us = &cl->ssl.stream;
  81. ops->init(&cl->ssl, &cl->sfd.stream, ctx, true);
  82. cl->us->notify_read = tls_ustream_read_cb;
  83. cl->us->notify_write = tls_ustream_write_cb;
  84. cl->us->notify_state = tls_notify_state;
  85. }
  86. void uh_tls_client_detach(struct client *cl)
  87. {
  88. ustream_free(&cl->ssl.stream);
  89. }