ustream-io-openssl.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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 <string.h>
  19. #include <libubox/ustream.h>
  20. #include "ustream-ssl.h"
  21. #include "openssl_bio_compat.h"
  22. #include "ustream-internal.h"
  23. static int
  24. s_ustream_new(BIO *b)
  25. {
  26. BIO_set_init(b, 1);
  27. BIO_set_data(b, NULL);
  28. BIO_clear_flags(b, ~0);
  29. return 1;
  30. }
  31. static int
  32. s_ustream_free(BIO *b)
  33. {
  34. if (!b)
  35. return 0;
  36. BIO_set_data(b, NULL);
  37. BIO_set_init(b, 0);
  38. BIO_clear_flags(b, ~0);
  39. return 1;
  40. }
  41. static int
  42. s_ustream_read(BIO *b, char *buf, int len)
  43. {
  44. struct bio_ctx *ctx;
  45. char *sbuf;
  46. int slen;
  47. if (!buf || len <= 0)
  48. return 0;
  49. ctx = (struct bio_ctx *)BIO_get_data(b);
  50. if (!ctx || !ctx->stream)
  51. return 0;
  52. sbuf = ustream_get_read_buf(ctx->stream, &slen);
  53. BIO_clear_retry_flags(b);
  54. if (!slen) {
  55. BIO_set_retry_read(b);
  56. return -1;
  57. }
  58. if (slen > len)
  59. slen = len;
  60. memcpy(buf, sbuf, slen);
  61. ustream_consume(ctx->stream, slen);
  62. return slen;
  63. }
  64. static int
  65. s_ustream_write(BIO *b, const char *buf, int len)
  66. {
  67. struct bio_ctx *ctx;
  68. if (!buf || len <= 0)
  69. return 0;
  70. ctx = (struct bio_ctx *)BIO_get_data(b);
  71. if (!ctx || !ctx->stream)
  72. return 0;
  73. if (ctx->stream->write_error)
  74. return len;
  75. return ustream_write(ctx->stream, buf, len, false);
  76. }
  77. static int
  78. s_ustream_gets(BIO *b, char *buf, int len)
  79. {
  80. return -1;
  81. }
  82. static int
  83. s_ustream_puts(BIO *b, const char *str)
  84. {
  85. return s_ustream_write(b, str, strlen(str));
  86. }
  87. static long s_ustream_ctrl(BIO *b, int cmd, long num, void *ptr)
  88. {
  89. switch (cmd) {
  90. case BIO_CTRL_FLUSH:
  91. return 1;
  92. default:
  93. return 0;
  94. };
  95. }
  96. static BIO *ustream_bio_new(struct ustream *s)
  97. {
  98. BIO *bio;
  99. struct bio_ctx *ctx = calloc(1, sizeof(struct bio_ctx));
  100. ctx->stream = s;
  101. ctx->meth = BIO_meth_new(100 | BIO_TYPE_SOURCE_SINK, "ustream");
  102. BIO_meth_set_write(ctx->meth, s_ustream_write);
  103. BIO_meth_set_read(ctx->meth, s_ustream_read);
  104. BIO_meth_set_puts(ctx->meth, s_ustream_puts);
  105. BIO_meth_set_gets(ctx->meth, s_ustream_gets);
  106. BIO_meth_set_ctrl(ctx->meth, s_ustream_ctrl);
  107. BIO_meth_set_create(ctx->meth, s_ustream_new);
  108. BIO_meth_set_destroy(ctx->meth, s_ustream_free);
  109. bio = BIO_new(ctx->meth);
  110. BIO_set_data(bio, ctx);
  111. return bio;
  112. }
  113. static BIO *fd_bio_new(int fd)
  114. {
  115. BIO *bio = BIO_new(BIO_s_socket());
  116. BIO_set_fd(bio, fd, BIO_NOCLOSE);
  117. return bio;
  118. }
  119. __hidden void ustream_set_io(struct ustream_ssl *us)
  120. {
  121. BIO *bio;
  122. if (us->conn)
  123. bio = ustream_bio_new(us->conn);
  124. else
  125. bio = fd_bio_new(us->fd.fd);
  126. SSL_set_bio(us->ssl, bio, bio);
  127. }