3 #include <openssl/ssl.h>
4 #include <openssl/err.h>
6 #include <libubox/ustream.h>
7 #include "ustream-io.h"
8 #include "ustream-ssl.h"
10 static void ssl_init(void)
12 static bool _init = false;
17 SSL_load_error_strings();
23 static void ustream_ssl_error_cb(struct uloop_timeout *t)
25 struct ustream_ssl *us = container_of(t, struct ustream_ssl, error_timer);
26 static char buffer[128];
27 int error = us->error;
30 us->notify_error(us, error, ERR_error_string(us->error, buffer));
33 static void ustream_ssl_error(struct ustream_ssl *us, int error)
36 uloop_timeout_set(&us->error_timer, 0);
39 static void ustream_ssl_check_conn(struct ustream_ssl *us)
43 if (us->connected || us->error)
47 ret = SSL_accept(us->ssl);
49 ret = SSL_connect(us->ssl);
53 if (us->notify_connected)
54 us->notify_connected(us);
58 ret = SSL_get_error(us->ssl, ret);
59 if (ret == SSL_ERROR_WANT_READ || ret == SSL_ERROR_WANT_WRITE)
62 ustream_ssl_error(us, ret);
65 static void ustream_ssl_notify_read(struct ustream *s, int bytes)
67 struct ustream_ssl *us = container_of(s->next, struct ustream_ssl, stream);
71 ustream_ssl_check_conn(us);
72 if (!us->connected || us->error)
75 buf = ustream_reserve(&us->stream, 1, &len);
80 ret = SSL_read(us->ssl, buf, len);
82 ret = SSL_get_error(us->ssl, ret);
84 if (ret == SSL_ERROR_WANT_READ)
87 ustream_ssl_error(us, ret);
91 us->stream.eof = true;
92 ustream_state_change(&us->stream);
102 ustream_fill_read(&us->stream, wr);
105 static void ustream_ssl_notify_write(struct ustream *s, int bytes)
107 struct ustream_ssl *us = container_of(s->next, struct ustream_ssl, stream);
109 ustream_ssl_check_conn(us);
110 ustream_write_pending(s->next);
113 static void ustream_ssl_notify_state(struct ustream *s)
115 s->next->write_error = true;
116 ustream_state_change(s->next);
119 static int ustream_ssl_write(struct ustream *s, const char *buf, int len, bool more)
121 struct ustream_ssl *us = container_of(s, struct ustream_ssl, stream);
124 if (!us->connected || us->error)
127 if (us->conn->w.data_bytes)
130 ret = SSL_write(us->ssl, buf, len);
132 int err = SSL_get_error(us->ssl, ret);
133 if (err == SSL_ERROR_WANT_WRITE)
140 static void ustream_ssl_set_read_blocked(struct ustream *s)
142 struct ustream_ssl *us = container_of(s, struct ustream_ssl, stream);
144 ustream_set_read_blocked(us->conn, !!s->read_blocked);
147 static void ustream_ssl_free(struct ustream *s)
149 struct ustream_ssl *us = container_of(s, struct ustream_ssl, stream);
152 us->conn->next = NULL;
153 us->conn->notify_read = NULL;
154 us->conn->notify_write = NULL;
155 us->conn->notify_state = NULL;
158 uloop_timeout_cancel(&us->error_timer);
159 SSL_shutdown(us->ssl);
164 us->connected = false;
168 static void ustream_ssl_stream_init(struct ustream_ssl *us)
170 struct ustream *conn = us->conn;
171 struct ustream *s = &us->stream;
173 conn->notify_read = ustream_ssl_notify_read;
174 conn->notify_write = ustream_ssl_notify_write;
175 conn->notify_state = ustream_ssl_notify_state;
177 s->free = ustream_ssl_free;
178 s->write = ustream_ssl_write;
179 s->set_read_blocked = ustream_ssl_set_read_blocked;
180 ustream_init_defaults(s);
183 static void *_ustream_ssl_context_new(bool server)
190 #ifdef CYASSL_OPENSSL_H_
192 m = SSLv23_server_method();
194 m = SSLv23_client_method();
197 m = TLSv1_server_method();
199 m = TLSv1_client_method();
202 c = SSL_CTX_new((void *) m);
207 SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL);
212 static int _ustream_ssl_context_set_crt_file(void *ctx, const char *file)
216 ret = SSL_CTX_use_certificate_file(ctx, file, SSL_FILETYPE_PEM);
218 ret = SSL_CTX_use_certificate_file(ctx, file, SSL_FILETYPE_ASN1);
226 static int _ustream_ssl_context_set_key_file(void *ctx, const char *file)
230 ret = SSL_CTX_use_PrivateKey_file(ctx, file, SSL_FILETYPE_PEM);
232 ret = SSL_CTX_use_PrivateKey_file(ctx, file, SSL_FILETYPE_ASN1);
240 static void _ustream_ssl_context_free(void *ctx)
245 static int _ustream_ssl_init(struct ustream_ssl *us, struct ustream *conn, void *ctx, bool server)
247 us->error_timer.cb = ustream_ssl_error_cb;
252 us->ssl = SSL_new(us->ctx);
256 conn->next = &us->stream;
257 ustream_set_io(ctx, us->ssl, conn);
258 ustream_ssl_stream_init(us);
263 const struct ustream_ssl_ops ustream_ssl_ops = {
264 .context_new = _ustream_ssl_context_new,
265 .context_set_crt_file = _ustream_ssl_context_set_crt_file,
266 .context_set_key_file = _ustream_ssl_context_set_key_file,
267 .context_free = _ustream_ssl_context_free,
268 .init = _ustream_ssl_init,