1 /* $OpenBSD: evbuffer_tls.c,v 1.9 2015/10/09 16:58:25 bluhm Exp $ */ 2 3 /* 4 * Copyright (c) 2002-2004 Niels Provos <provos@citi.umich.edu> 5 * Copyright (c) 2014-2015 Alexander Bluhm <bluhm@openbsd.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/types.h> 32 #include <sys/time.h> 33 #include <sys/ioctl.h> 34 35 #include <errno.h> 36 #include <event.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <tls.h> 41 42 #include "evbuffer_tls.h" 43 44 /* prototypes */ 45 46 void bufferevent_read_pressure_cb(struct evbuffer *, size_t, size_t, void *); 47 static void buffertls_readcb(int, short, void *); 48 static void buffertls_writecb(int, short, void *); 49 static void buffertls_handshakecb(int, short, void *); 50 int evtls_read(struct evbuffer *, int, int, struct tls *); 51 int evtls_write(struct evbuffer *, int, struct tls *); 52 53 static int 54 bufferevent_add(struct event *ev, int timeout) 55 { 56 struct timeval tv, *ptv = NULL; 57 58 if (timeout) { 59 timerclear(&tv); 60 tv.tv_sec = timeout; 61 ptv = &tv; 62 } 63 64 return (event_add(ev, ptv)); 65 } 66 67 static void 68 buffertls_readcb(int fd, short event, void *arg) 69 { 70 struct buffertls *buftls = arg; 71 struct bufferevent *bufev = buftls->bt_bufev; 72 struct tls *ctx = buftls->bt_ctx; 73 int res = 0; 74 short what = EVBUFFER_READ; 75 size_t len; 76 int howmuch = -1; 77 78 if (event == EV_TIMEOUT) { 79 what |= EVBUFFER_TIMEOUT; 80 goto error; 81 } 82 83 /* 84 * If we have a high watermark configured then we don't want to 85 * read more data than would make us reach the watermark. 86 */ 87 if (bufev->wm_read.high != 0) { 88 howmuch = bufev->wm_read.high - EVBUFFER_LENGTH(bufev->input); 89 /* we might have lowered the watermark, stop reading */ 90 if (howmuch <= 0) { 91 struct evbuffer *buf = bufev->input; 92 event_del(&bufev->ev_read); 93 evbuffer_setcb(buf, 94 bufferevent_read_pressure_cb, bufev); 95 return; 96 } 97 } 98 99 res = evtls_read(bufev->input, fd, howmuch, ctx); 100 switch (res) { 101 case TLS_WANT_POLLIN: 102 bufferevent_add(&bufev->ev_read, bufev->timeout_read); 103 return; 104 case TLS_WANT_POLLOUT: 105 event_del(&bufev->ev_write); 106 event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_readcb, 107 buftls); 108 bufferevent_add(&bufev->ev_write, bufev->timeout_write); 109 return; 110 case -1: 111 what |= EVBUFFER_ERROR; 112 break; 113 case 0: 114 what |= EVBUFFER_EOF; 115 break; 116 } 117 if (res <= 0) 118 goto error; 119 120 event_del(&bufev->ev_write); 121 event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb, buftls); 122 if (bufev->enabled & EV_READ) 123 bufferevent_add(&bufev->ev_read, bufev->timeout_read); 124 if (EVBUFFER_LENGTH(bufev->output) != 0 && bufev->enabled & EV_WRITE) 125 bufferevent_add(&bufev->ev_write, bufev->timeout_write); 126 127 /* See if this callbacks meets the water marks */ 128 len = EVBUFFER_LENGTH(bufev->input); 129 if (bufev->wm_read.low != 0 && len < bufev->wm_read.low) 130 return; 131 if (bufev->wm_read.high != 0 && len >= bufev->wm_read.high) { 132 struct evbuffer *buf = bufev->input; 133 event_del(&bufev->ev_read); 134 135 /* Now schedule a callback for us when the buffer changes */ 136 evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); 137 } 138 139 /* Invoke the user callback - must always be called last */ 140 if (bufev->readcb != NULL) 141 (*bufev->readcb)(bufev, bufev->cbarg); 142 return; 143 144 error: 145 (*bufev->errorcb)(bufev, what, bufev->cbarg); 146 } 147 148 static void 149 buffertls_writecb(int fd, short event, void *arg) 150 { 151 struct buffertls *buftls = arg; 152 struct bufferevent *bufev = buftls->bt_bufev; 153 struct tls *ctx = buftls->bt_ctx; 154 int res = 0; 155 short what = EVBUFFER_WRITE; 156 157 if (event == EV_TIMEOUT) { 158 what |= EVBUFFER_TIMEOUT; 159 goto error; 160 } 161 162 if (EVBUFFER_LENGTH(bufev->output) != 0) { 163 res = evtls_write(bufev->output, fd, ctx); 164 switch (res) { 165 case TLS_WANT_POLLIN: 166 event_del(&bufev->ev_read); 167 event_set(&bufev->ev_read, fd, EV_READ, 168 buffertls_writecb, buftls); 169 bufferevent_add(&bufev->ev_read, bufev->timeout_read); 170 return; 171 case TLS_WANT_POLLOUT: 172 bufferevent_add(&bufev->ev_write, bufev->timeout_write); 173 return; 174 case -1: 175 what |= EVBUFFER_ERROR; 176 break; 177 case 0: 178 what |= EVBUFFER_EOF; 179 break; 180 } 181 if (res <= 0) 182 goto error; 183 } 184 185 event_del(&bufev->ev_read); 186 event_set(&bufev->ev_read, fd, EV_READ, buffertls_readcb, buftls); 187 if (bufev->enabled & EV_READ) 188 bufferevent_add(&bufev->ev_read, bufev->timeout_read); 189 if (EVBUFFER_LENGTH(bufev->output) != 0 && bufev->enabled & EV_WRITE) 190 bufferevent_add(&bufev->ev_write, bufev->timeout_write); 191 192 /* 193 * Invoke the user callback if our buffer is drained or below the 194 * low watermark. 195 */ 196 if (bufev->writecb != NULL && 197 EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low) 198 (*bufev->writecb)(bufev, bufev->cbarg); 199 200 return; 201 202 error: 203 (*bufev->errorcb)(bufev, what, bufev->cbarg); 204 } 205 206 static void 207 buffertls_handshakecb(int fd, short event, void *arg) 208 { 209 struct buffertls *buftls = arg; 210 struct bufferevent *bufev = buftls->bt_bufev; 211 struct tls *ctx = buftls->bt_ctx; 212 int res = 0; 213 short what = EVBUFFER_HANDSHAKE; 214 215 if (event == EV_TIMEOUT) { 216 what |= EVBUFFER_TIMEOUT; 217 goto error; 218 } 219 220 res = tls_handshake(ctx); 221 switch (res) { 222 case TLS_WANT_POLLIN: 223 bufferevent_add(&bufev->ev_read, bufev->timeout_read); 224 return; 225 case TLS_WANT_POLLOUT: 226 bufferevent_add(&bufev->ev_write, bufev->timeout_write); 227 return; 228 case -1: 229 what |= EVBUFFER_ERROR; 230 break; 231 } 232 if (res < 0) 233 goto error; 234 235 /* Handshake was successful, change to read and write callback. */ 236 event_del(&bufev->ev_read); 237 event_del(&bufev->ev_write); 238 event_set(&bufev->ev_read, fd, EV_READ, buffertls_readcb, buftls); 239 event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb, buftls); 240 if (bufev->enabled & EV_READ) 241 bufferevent_add(&bufev->ev_read, bufev->timeout_read); 242 if (EVBUFFER_LENGTH(bufev->output) != 0 && bufev->enabled & EV_WRITE) 243 bufferevent_add(&bufev->ev_write, bufev->timeout_write); 244 245 return; 246 247 error: 248 (*bufev->errorcb)(bufev, what, bufev->cbarg); 249 } 250 251 void 252 buffertls_set(struct buffertls *buftls, struct bufferevent *bufev, 253 struct tls *ctx, int fd) 254 { 255 bufferevent_setfd(bufev, fd); 256 event_set(&bufev->ev_read, fd, EV_READ, buffertls_readcb, buftls); 257 event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_writecb, buftls); 258 buftls->bt_bufev = bufev; 259 buftls->bt_ctx = ctx; 260 } 261 262 void 263 buffertls_accept(struct buffertls *buftls, int fd) 264 { 265 struct bufferevent *bufev = buftls->bt_bufev; 266 267 event_del(&bufev->ev_read); 268 event_del(&bufev->ev_write); 269 event_set(&bufev->ev_read, fd, EV_READ, buffertls_handshakecb, buftls); 270 event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_handshakecb, 271 buftls); 272 bufferevent_add(&bufev->ev_read, bufev->timeout_read); 273 } 274 275 void 276 buffertls_connect(struct buffertls *buftls, int fd) 277 { 278 struct bufferevent *bufev = buftls->bt_bufev; 279 280 event_del(&bufev->ev_read); 281 event_del(&bufev->ev_write); 282 event_set(&bufev->ev_read, fd, EV_READ, buffertls_handshakecb, buftls); 283 event_set(&bufev->ev_write, fd, EV_WRITE, buffertls_handshakecb, 284 buftls); 285 bufferevent_add(&bufev->ev_write, bufev->timeout_write); 286 } 287 288 /* 289 * Reads data from a file descriptor into a buffer. 290 */ 291 292 #define EVBUFFER_MAX_READ 4096 293 294 int 295 evtls_read(struct evbuffer *buf, int fd, int howmuch, struct tls *ctx) 296 { 297 u_char *p; 298 size_t oldoff = buf->off; 299 int n = EVBUFFER_MAX_READ; 300 301 if (ioctl(fd, FIONREAD, &n) == -1 || n <= 0) { 302 n = EVBUFFER_MAX_READ; 303 } else if (n > EVBUFFER_MAX_READ && n > howmuch) { 304 /* 305 * It's possible that a lot of data is available for 306 * reading. We do not want to exhaust resources 307 * before the reader has a chance to do something 308 * about it. If the reader does not tell us how much 309 * data we should read, we artifically limit it. 310 */ 311 if ((size_t)n > buf->totallen << 2) 312 n = buf->totallen << 2; 313 if (n < EVBUFFER_MAX_READ) 314 n = EVBUFFER_MAX_READ; 315 } 316 if (howmuch < 0 || howmuch > n) 317 howmuch = n; 318 319 /* If we don't have FIONREAD, we might waste some space here */ 320 if (evbuffer_expand(buf, howmuch) == -1) 321 return (-1); 322 323 /* We can append new data at this point */ 324 p = buf->buffer + buf->off; 325 326 n = tls_read(ctx, p, howmuch); 327 if (n <= 0) 328 return (n); 329 330 buf->off += n; 331 332 /* Tell someone about changes in this buffer */ 333 if (buf->off != oldoff && buf->cb != NULL) 334 (*buf->cb)(buf, oldoff, buf->off, buf->cbarg); 335 336 return (n); 337 } 338 339 int 340 evtls_write(struct evbuffer *buffer, int fd, struct tls *ctx) 341 { 342 int n; 343 344 n = tls_write(ctx, buffer->buffer, buffer->off); 345 if (n <= 0) 346 return (n); 347 evbuffer_drain(buffer, n); 348 349 return (n); 350 } 351