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 19 #include <errno.h> 20 #include <stdlib.h> 21 #include <string.h> 22 #include <libubox/ustream.h> 23 24 #include "ustream-ssl.h" 25 #include "ustream-internal.h" 26 27 static void ustream_ssl_error_cb(struct uloop_timeout *t) 28 { 29 struct ustream_ssl *us = container_of(t, struct ustream_ssl, error_timer); 30 static char buffer[128]; 31 int error = us->error; 32 33 if (us->notify_error) 34 us->notify_error(us, error, __ustream_ssl_strerror(us->error, buffer, sizeof(buffer))); 35 } 36 37 static void ustream_ssl_check_conn(struct ustream_ssl *us) 38 { 39 struct ustream *s = &us->stream; 40 struct ustream_free_guard guard; 41 bool connected; 42 43 if (us->connected || us->error || us->stream.eof) 44 return; 45 46 /* the handshake may invoke notify_verify_error */ 47 ustream_free_guard_set(s, &guard); 48 connected = __ustream_ssl_connect(us) == U_SSL_OK; 49 if (ustream_free_guard_check(s, &guard)) 50 return; 51 52 if (!connected) 53 return; 54 55 /* __ustream_ssl_connect() will also return U_SSL_OK when certificate 56 * verification failed! 57 * 58 * Applications may register a custom .notify_verify_error callback in the 59 * struct ustream_ssl which is called upon verification failures, but there 60 * is no straight forward way for the callback to terminate the connection 61 * initiation right away, e.g. through a true or false return value. 62 * 63 * Instead, existing implementations appear to set .eof field of the underlying 64 * ustream in the hope that this inhibits further operations on the stream. 65 * 66 * Declare this informal behaviour "official" and check for the state of the 67 * .eof member after __ustream_ssl_connect() returned, and do not write the 68 * pending data if it is set to true. 69 */ 70 71 if (us->stream.eof) 72 return; 73 74 us->connected = true; 75 if (us->notify_connected) { 76 ustream_free_guard_set(s, &guard); 77 us->notify_connected(us); 78 if (ustream_free_guard_check(s, &guard)) 79 return; 80 } 81 82 ustream_write_pending(s); 83 } 84 85 static bool __ustream_ssl_poll(struct ustream_ssl *us) 86 { 87 struct ustream *s = &us->stream; 88 struct ustream_free_guard guard; 89 char *buf; 90 int len, ret; 91 bool more = false; 92 93 ustream_free_guard_set(s, &guard); 94 ustream_ssl_check_conn(us); 95 if (ustream_free_guard_check(s, &guard)) 96 return false; 97 98 if (!us->connected || us->error) 99 return false; 100 101 do { 102 buf = ustream_reserve(s, 1, &len); 103 if (!len) 104 break; 105 106 ret = __ustream_ssl_read(us, buf, len); 107 if (ret == U_SSL_PENDING) { 108 if (us->conn) { 109 ustream_free_guard_set(s, &guard); 110 ustream_poll(us->conn); 111 if (ustream_free_guard_check(s, &guard)) 112 return more; 113 } 114 ret = __ustream_ssl_read(us, buf, len); 115 } 116 117 switch (ret) { 118 case U_SSL_PENDING: 119 return more; 120 case U_SSL_ERROR: 121 return false; 122 case 0: 123 s->eof = true; 124 ustream_state_change(s); 125 return false; 126 default: 127 ustream_free_guard_set(s, &guard); 128 ustream_fill_read(s, ret); 129 if (ustream_free_guard_check(s, &guard)) 130 return more; 131 132 more = true; 133 continue; 134 } 135 } while (1); 136 137 return more; 138 } 139 140 static void ustream_ssl_notify_read(struct ustream *s, int bytes) 141 { 142 struct ustream_ssl *us = container_of(s->next, struct ustream_ssl, stream); 143 144 __ustream_ssl_poll(us); 145 } 146 147 static void ustream_ssl_notify_write(struct ustream *s, int bytes) 148 { 149 struct ustream_ssl *us = container_of(s->next, struct ustream_ssl, stream); 150 struct ustream_free_guard guard; 151 152 ustream_free_guard_set(&us->stream, &guard); 153 ustream_ssl_check_conn(us); 154 if (ustream_free_guard_check(&us->stream, &guard)) 155 return; 156 157 ustream_write_pending(s->next); 158 } 159 160 static void ustream_ssl_notify_state(struct ustream *s) 161 { 162 s->next->write_error = true; 163 ustream_state_change(s->next); 164 } 165 166 static int ustream_ssl_write(struct ustream *s, const char *buf, int len, bool more) 167 { 168 struct ustream_ssl *us = container_of(s, struct ustream_ssl, stream); 169 int ret; 170 171 if (!us->connected || us->error) 172 return 0; 173 174 if (us->conn && us->conn->w.data_bytes) 175 return 0; 176 177 /* Data that the SSL library did not accept is buffered by the ustream 178 * core and retried from the buffers, i.e. with a different address and 179 * typically a different length. SSL write retry semantics require the 180 * retry to cover exactly the data of the failed call: with a shorter 181 * retry OpenSSL fails ("bad write retry"), while mbedTLS reports the 182 * retried length as written even though only the previously packaged 183 * record is sent, corrupting the stream. Cap the retry length to the 184 * length of the failed call to keep both libraries consistent. 185 */ 186 if (us->pending_write > 0 && len > us->pending_write) 187 len = us->pending_write; 188 189 ret = __ustream_ssl_write(us, buf, len); 190 if (ret < 0) { 191 us->pending_write = 0; 192 return ret; 193 } 194 195 us->pending_write = len - ret; 196 197 return ret; 198 } 199 200 static void ustream_ssl_set_read_blocked(struct ustream *s) 201 { 202 struct ustream_ssl *us = container_of(s, struct ustream_ssl, stream); 203 unsigned int ev = ULOOP_WRITE | ULOOP_EDGE_TRIGGER; 204 205 if (us->conn) { 206 ustream_set_read_blocked(us->conn, !!s->read_blocked); 207 return; 208 } 209 210 if (!s->read_blocked) 211 ev |= ULOOP_READ; 212 213 uloop_fd_add(&us->fd, ev); 214 } 215 216 static void ustream_ssl_free(struct ustream *s) 217 { 218 struct ustream_ssl *us = container_of(s, struct ustream_ssl, stream); 219 220 if (us->conn) { 221 us->conn->next = NULL; 222 us->conn->notify_read = NULL; 223 us->conn->notify_write = NULL; 224 us->conn->notify_state = NULL; 225 } else { 226 uloop_fd_delete(&us->fd); 227 } 228 229 uloop_timeout_cancel(&us->error_timer); 230 __ustream_ssl_session_free(us); 231 free(us->peer_cn); 232 233 us->ctx = NULL; 234 us->ssl = NULL; 235 us->conn = NULL; 236 us->peer_cn = NULL; 237 us->connected = false; 238 us->error = false; 239 us->pending_write = 0; 240 us->valid_cert = false; 241 us->valid_cn = false; 242 } 243 244 static bool ustream_ssl_poll(struct ustream *s) 245 { 246 struct ustream_ssl *us = container_of(s, struct ustream_ssl, stream); 247 struct ustream_free_guard guard; 248 bool fd_poll = false; 249 250 if (us->conn) { 251 ustream_free_guard_set(s, &guard); 252 fd_poll = ustream_poll(us->conn); 253 if (ustream_free_guard_check(s, &guard)) 254 return fd_poll; 255 } 256 257 return __ustream_ssl_poll(us) || fd_poll; 258 } 259 260 static void ustream_ssl_fd_cb(struct uloop_fd *fd, unsigned int events) 261 { 262 struct ustream_ssl *us = container_of(fd, struct ustream_ssl, fd); 263 264 __ustream_ssl_poll(us); 265 266 if (!(events & ULOOP_WRITE)) 267 return; 268 269 if (us->connected && !us->error && us->stream.w.data_bytes) 270 ustream_write_pending(&us->stream); 271 } 272 273 static void ustream_ssl_stream_init(struct ustream_ssl *us) 274 { 275 struct ustream *conn = us->conn; 276 struct ustream *s = &us->stream; 277 278 if (conn) { 279 conn->notify_read = ustream_ssl_notify_read; 280 conn->notify_write = ustream_ssl_notify_write; 281 conn->notify_state = ustream_ssl_notify_state; 282 } else { 283 us->fd.cb = ustream_ssl_fd_cb; 284 uloop_fd_add(&us->fd, ULOOP_READ | ULOOP_WRITE | ULOOP_EDGE_TRIGGER); 285 } 286 287 s->set_read_blocked = ustream_ssl_set_read_blocked; 288 s->free = ustream_ssl_free; 289 s->write = ustream_ssl_write; 290 s->poll = ustream_ssl_poll; 291 ustream_init_defaults(s); 292 } 293 294 static int _ustream_ssl_init_common(struct ustream_ssl *us) 295 { 296 us->error_timer.cb = ustream_ssl_error_cb; 297 298 us->ssl = __ustream_ssl_session_new(us->ctx); 299 if (!us->ssl) 300 return -ENOMEM; 301 302 ustream_set_io(us); 303 ustream_ssl_stream_init(us); 304 305 if (us->server_name) 306 __ustream_ssl_set_server_name(us); 307 308 if (us->peer_cn && __ustream_ssl_update_peer_cn(us)) 309 return -ENOMEM; 310 311 ustream_ssl_check_conn(us); 312 313 return 0; 314 } 315 316 static int _ustream_ssl_init_fd(struct ustream_ssl *us, int fd, struct ustream_ssl_ctx *ctx, bool server) 317 { 318 us->server = server; 319 us->ctx = ctx; 320 us->fd.fd = fd; 321 322 /* Writes can block on the socket, so blocked data is buffered and 323 * retried one buffer chunk at a time. The first retried chunk must 324 * cover the record pending inside the SSL library, so it has to hold 325 * at least the maximum TLS plaintext fragment size. 326 */ 327 if (!us->stream.w.buffer_len) 328 us->stream.w.buffer_len = 16384; 329 330 return _ustream_ssl_init_common(us); 331 } 332 333 static int _ustream_ssl_init(struct ustream_ssl *us, struct ustream *conn, struct ustream_ssl_ctx *ctx, bool server) 334 { 335 int ret; 336 337 us->server = server; 338 us->ctx = ctx; 339 340 us->conn = conn; 341 conn->r.max_buffers = 4; 342 conn->next = &us->stream; 343 344 ret = _ustream_ssl_init_common(us); 345 if (ret) { 346 conn->next = NULL; 347 us->conn = NULL; 348 } 349 350 return ret; 351 } 352 353 static int _ustream_ssl_set_peer_cn(struct ustream_ssl *us, const char *name) 354 { 355 char *peer_cn = strdup(name); 356 357 if (!peer_cn) 358 return -ENOMEM; 359 360 free(us->peer_cn); 361 us->peer_cn = peer_cn; 362 363 if (us->ssl) 364 return __ustream_ssl_update_peer_cn(us); 365 366 return 0; 367 } 368 369 const struct ustream_ssl_ops ustream_ssl_ops = { 370 .context_new = __ustream_ssl_context_new, 371 .context_set_crt_file = __ustream_ssl_set_crt_file, 372 .context_set_key_file = __ustream_ssl_set_key_file, 373 .context_add_ca_crt_file = __ustream_ssl_add_ca_crt_file, 374 .context_set_ciphers = __ustream_ssl_set_ciphers, 375 .context_set_require_validation = __ustream_ssl_set_require_validation, 376 .context_set_debug = __ustream_ssl_set_debug, 377 .context_free = __ustream_ssl_context_free, 378 .init = _ustream_ssl_init, 379 .init_fd = _ustream_ssl_init_fd, 380 .set_peer_cn = _ustream_ssl_set_peer_cn, 381 }; 382
This page was automatically generated by LXR 0.3.1. • OpenWrt