2 * ustream-ssl - library for SSL over ustream
4 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
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.
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.
22 #include <libubox/ustream.h>
24 #include "ustream-ssl.h"
25 #include "ustream-internal.h"
27 static void ustream_ssl_error_cb(struct uloop_timeout
*t
)
29 struct ustream_ssl
*us
= container_of(t
, struct ustream_ssl
, error_timer
);
30 static char buffer
[128];
31 int error
= us
->error
;
34 us
->notify_error(us
, error
, __ustream_ssl_strerror(us
->error
, buffer
, sizeof(buffer
)));
37 static void ustream_ssl_check_conn(struct ustream_ssl
*us
)
39 if (us
->connected
|| us
->error
)
42 if (__ustream_ssl_connect(us
) == U_SSL_OK
) {
44 /* __ustream_ssl_connect() will also return U_SSL_OK when certificate
45 * verification failed!
47 * Applications may register a custom .notify_verify_error callback in the
48 * struct ustream_ssl which is called upon verification failures, but there
49 * is no straight forward way for the callback to terminate the connection
50 * initiation right away, e.g. through a true or false return value.
52 * Instead, existing implementations appear to set .eof field of the underlying
53 * ustream in the hope that this inhibits further operations on the stream.
55 * Declare this informal behaviour "official" and check for the state of the
56 * .eof member after __ustream_ssl_connect() returned, and do not write the
57 * pending data if it is set to true.
64 if (us
->notify_connected
)
65 us
->notify_connected(us
);
66 ustream_write_pending(&us
->stream
);
70 static bool __ustream_ssl_poll(struct ustream
*s
)
72 struct ustream_ssl
*us
= container_of(s
->next
, struct ustream_ssl
, stream
);
77 ustream_ssl_check_conn(us
);
78 if (!us
->connected
|| us
->error
)
82 buf
= ustream_reserve(&us
->stream
, 1, &len
);
86 ret
= __ustream_ssl_read(us
, buf
, len
);
87 if (ret
== U_SSL_PENDING
) {
88 ustream_poll(us
->conn
);
89 ret
= __ustream_ssl_read(us
, buf
, len
);
98 us
->stream
.eof
= true;
99 ustream_state_change(&us
->stream
);
102 ustream_fill_read(&us
->stream
, ret
);
111 static void ustream_ssl_notify_read(struct ustream
*s
, int bytes
)
113 __ustream_ssl_poll(s
);
116 static void ustream_ssl_notify_write(struct ustream
*s
, int bytes
)
118 struct ustream_ssl
*us
= container_of(s
->next
, struct ustream_ssl
, stream
);
120 ustream_ssl_check_conn(us
);
121 ustream_write_pending(s
->next
);
124 static void ustream_ssl_notify_state(struct ustream
*s
)
126 s
->next
->write_error
= true;
127 ustream_state_change(s
->next
);
130 static int ustream_ssl_write(struct ustream
*s
, const char *buf
, int len
, bool more
)
132 struct ustream_ssl
*us
= container_of(s
, struct ustream_ssl
, stream
);
134 if (!us
->connected
|| us
->error
)
137 if (us
->conn
->w
.data_bytes
)
140 return __ustream_ssl_write(us
, buf
, len
);
143 static void ustream_ssl_set_read_blocked(struct ustream
*s
)
145 struct ustream_ssl
*us
= container_of(s
, struct ustream_ssl
, stream
);
147 ustream_set_read_blocked(us
->conn
, !!s
->read_blocked
);
150 static void ustream_ssl_free(struct ustream
*s
)
152 struct ustream_ssl
*us
= container_of(s
, struct ustream_ssl
, stream
);
155 us
->conn
->next
= NULL
;
156 us
->conn
->notify_read
= NULL
;
157 us
->conn
->notify_write
= NULL
;
158 us
->conn
->notify_state
= NULL
;
161 uloop_timeout_cancel(&us
->error_timer
);
162 __ustream_ssl_session_free(us
->ssl
);
169 us
->connected
= false;
171 us
->valid_cert
= false;
172 us
->valid_cn
= false;
175 static bool ustream_ssl_poll(struct ustream
*s
)
177 struct ustream_ssl
*us
= container_of(s
, struct ustream_ssl
, stream
);
180 fd_poll
= ustream_poll(us
->conn
);
181 return __ustream_ssl_poll(us
->conn
) || fd_poll
;
184 static void ustream_ssl_stream_init(struct ustream_ssl
*us
)
186 struct ustream
*conn
= us
->conn
;
187 struct ustream
*s
= &us
->stream
;
189 conn
->notify_read
= ustream_ssl_notify_read
;
190 conn
->notify_write
= ustream_ssl_notify_write
;
191 conn
->notify_state
= ustream_ssl_notify_state
;
193 s
->free
= ustream_ssl_free
;
194 s
->write
= ustream_ssl_write
;
195 s
->poll
= ustream_ssl_poll
;
196 s
->set_read_blocked
= ustream_ssl_set_read_blocked
;
197 ustream_init_defaults(s
);
200 static int _ustream_ssl_init(struct ustream_ssl
*us
, struct ustream
*conn
, struct ustream_ssl_ctx
*ctx
, bool server
)
202 us
->error_timer
.cb
= ustream_ssl_error_cb
;
207 us
->ssl
= __ustream_ssl_session_new(us
->ctx
);
211 conn
->r
.max_buffers
= 4;
212 conn
->next
= &us
->stream
;
213 ustream_set_io(ctx
, us
->ssl
, conn
);
214 ustream_ssl_stream_init(us
);
217 __ustream_ssl_set_server_name(us
);
219 ustream_ssl_check_conn(us
);
224 static int _ustream_ssl_set_peer_cn(struct ustream_ssl
*us
, const char *name
)
226 us
->peer_cn
= strdup(name
);
227 __ustream_ssl_update_peer_cn(us
);
232 const struct ustream_ssl_ops ustream_ssl_ops
= {
233 .context_new
= __ustream_ssl_context_new
,
234 .context_set_crt_file
= __ustream_ssl_set_crt_file
,
235 .context_set_key_file
= __ustream_ssl_set_key_file
,
236 .context_add_ca_crt_file
= __ustream_ssl_add_ca_crt_file
,
237 .context_set_ciphers
= __ustream_ssl_set_ciphers
,
238 .context_set_require_validation
= __ustream_ssl_set_require_validation
,
239 .context_set_debug
= __ustream_ssl_set_debug
,
240 .context_free
= __ustream_ssl_context_free
,
241 .init
= _ustream_ssl_init
,
242 .set_peer_cn
= _ustream_ssl_set_peer_cn
,