1 /* $OpenBSD: relay.c,v 1.141 2011/09/04 20:26:58 bluhm Exp $ */ 2 3 /* 4 * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org> 5 * 6 * Permission to use, copy, modify, and 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 <sys/types.h> 20 #include <sys/queue.h> 21 #include <sys/time.h> 22 #include <sys/stat.h> 23 #include <sys/socket.h> 24 #include <sys/un.h> 25 #include <sys/tree.h> 26 #include <sys/hash.h> 27 28 #include <net/if.h> 29 #include <netinet/in_systm.h> 30 #include <netinet/in.h> 31 #include <netinet/ip.h> 32 #include <netinet/tcp.h> 33 #include <arpa/inet.h> 34 35 #include <errno.h> 36 #include <fcntl.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <unistd.h> 40 #include <stdio.h> 41 #include <err.h> 42 #include <pwd.h> 43 #include <event.h> 44 #include <fnmatch.h> 45 46 #include <openssl/ssl.h> 47 48 #include "relayd.h" 49 50 void relay_statistics(int, short, void *); 51 int relay_dispatch_parent(int, struct privsep_proc *, 52 struct imsg *); 53 int relay_dispatch_pfe(int, struct privsep_proc *, 54 struct imsg *); 55 void relay_shutdown(void); 56 57 void relay_nodedebug(const char *, struct protonode *); 58 void relay_protodebug(struct relay *); 59 void relay_init(struct privsep *, struct privsep_proc *p, void *); 60 void relay_launch(void); 61 int relay_socket(struct sockaddr_storage *, in_port_t, 62 struct protocol *, int, int); 63 int relay_socket_listen(struct sockaddr_storage *, in_port_t, 64 struct protocol *); 65 int relay_socket_connect(struct sockaddr_storage *, in_port_t, 66 struct protocol *, int); 67 68 void relay_accept(int, short, void *); 69 void relay_input(struct rsession *); 70 71 int relay_connect(struct rsession *); 72 void relay_connected(int, short, void *); 73 void relay_bindanyreq(struct rsession *, in_port_t, int); 74 void relay_bindany(int, short, void *); 75 76 u_int32_t relay_hash_addr(struct sockaddr_storage *, u_int32_t); 77 78 void relay_write(struct bufferevent *, void *); 79 void relay_read(struct bufferevent *, void *); 80 int relay_splicelen(struct ctl_relay_event *); 81 void relay_error(struct bufferevent *, short, void *); 82 void relay_dump(struct ctl_relay_event *, const void *, size_t); 83 84 int relay_resolve(struct ctl_relay_event *, 85 struct protonode *, struct protonode *); 86 int relay_handle_http(struct ctl_relay_event *, 87 struct protonode *, struct protonode *, 88 struct protonode *, int); 89 int relay_lognode(struct rsession *, 90 struct protonode *, struct protonode *, char *, size_t); 91 void relay_read_http(struct bufferevent *, void *); 92 static int _relay_lookup_url(struct ctl_relay_event *, char *, char *, 93 char *, enum digest_type); 94 int relay_lookup_url(struct ctl_relay_event *, 95 const char *, enum digest_type); 96 int relay_lookup_query(struct ctl_relay_event *); 97 int relay_lookup_cookie(struct ctl_relay_event *, const char *); 98 void relay_read_httpcontent(struct bufferevent *, void *); 99 void relay_read_httpchunks(struct bufferevent *, void *); 100 char *relay_expand_http(struct ctl_relay_event *, char *, 101 char *, size_t); 102 void relay_close_http(struct rsession *, u_int, const char *, 103 u_int16_t); 104 void relay_http_request_close(struct ctl_relay_event *); 105 106 SSL_CTX *relay_ssl_ctx_create(struct relay *); 107 void relay_ssl_transaction(struct rsession *, 108 struct ctl_relay_event *); 109 void relay_ssl_accept(int, short, void *); 110 void relay_ssl_connect(int, short, void *); 111 void relay_ssl_connected(struct ctl_relay_event *); 112 void relay_ssl_readcb(int, short, void *); 113 void relay_ssl_writecb(int, short, void *); 114 115 int relay_bufferevent_add(struct event *, int); 116 #ifdef notyet 117 int relay_bufferevent_printf(struct ctl_relay_event *, 118 const char *, ...); 119 #endif 120 int relay_bufferevent_print(struct ctl_relay_event *, char *); 121 int relay_bufferevent_write_buffer(struct ctl_relay_event *, 122 struct evbuffer *); 123 int relay_bufferevent_write_chunk(struct ctl_relay_event *, 124 struct evbuffer *, size_t); 125 int relay_bufferevent_write(struct ctl_relay_event *, 126 void *, size_t); 127 char *relay_load_file(const char *, off_t *); 128 static __inline int 129 relay_proto_cmp(struct protonode *, struct protonode *); 130 extern void bufferevent_read_pressure_cb(struct evbuffer *, size_t, 131 size_t, void *); 132 133 volatile sig_atomic_t relay_sessions; 134 objid_t relay_conid; 135 136 static struct relayd *env = NULL; 137 int proc_id; 138 139 static struct privsep_proc procs[] = { 140 { "parent", PROC_PARENT, relay_dispatch_parent }, 141 { "pfe", PROC_PFE, relay_dispatch_pfe }, 142 }; 143 144 pid_t 145 relay(struct privsep *ps, struct privsep_proc *p) 146 { 147 env = ps->ps_env; 148 return (proc_run(ps, p, procs, nitems(procs), relay_init, NULL)); 149 } 150 151 void 152 relay_shutdown(void) 153 { 154 config_purge(env, CONFIG_ALL); 155 usleep(200); /* XXX relay needs to shutdown last */ 156 } 157 158 void 159 relay_nodedebug(const char *name, struct protonode *pn) 160 { 161 const char *s; 162 int digest; 163 164 if (pn->action == NODE_ACTION_NONE) 165 return; 166 167 fprintf(stderr, "\t\t"); 168 fprintf(stderr, "%s ", name); 169 170 switch (pn->type) { 171 case NODE_TYPE_HEADER: 172 break; 173 case NODE_TYPE_QUERY: 174 fprintf(stderr, "query "); 175 break; 176 case NODE_TYPE_COOKIE: 177 fprintf(stderr, "cookie "); 178 break; 179 case NODE_TYPE_PATH: 180 fprintf(stderr, "path "); 181 break; 182 case NODE_TYPE_URL: 183 fprintf(stderr, "url "); 184 break; 185 } 186 187 switch (pn->action) { 188 case NODE_ACTION_APPEND: 189 fprintf(stderr, "append \"%s\" to \"%s\"", 190 pn->value, pn->key); 191 break; 192 case NODE_ACTION_CHANGE: 193 fprintf(stderr, "change \"%s\" to \"%s\"", 194 pn->key, pn->value); 195 break; 196 case NODE_ACTION_REMOVE: 197 fprintf(stderr, "remove \"%s\"", 198 pn->key); 199 break; 200 case NODE_ACTION_EXPECT: 201 case NODE_ACTION_FILTER: 202 s = pn->action == NODE_ACTION_EXPECT ? "expect" : "filter"; 203 digest = pn->flags & PNFLAG_LOOKUP_URL_DIGEST; 204 if (strcmp(pn->value, "*") == 0) 205 fprintf(stderr, "%s %s\"%s\"", s, 206 digest ? "digest " : "", pn->key); 207 else 208 fprintf(stderr, "%s \"%s\" from \"%s\"", s, 209 pn->value, pn->key); 210 break; 211 case NODE_ACTION_HASH: 212 fprintf(stderr, "hash \"%s\"", pn->key); 213 break; 214 case NODE_ACTION_LOG: 215 fprintf(stderr, "log \"%s\"", pn->key); 216 break; 217 case NODE_ACTION_MARK: 218 if (strcmp(pn->value, "*") == 0) 219 fprintf(stderr, "mark \"%s\"", pn->key); 220 else 221 fprintf(stderr, "mark \"%s\" from \"%s\"", 222 pn->value, pn->key); 223 break; 224 case NODE_ACTION_NONE: 225 break; 226 } 227 fprintf(stderr, "\n"); 228 } 229 230 void 231 relay_protodebug(struct relay *rlay) 232 { 233 struct protocol *proto = rlay->rl_proto; 234 struct protonode *proot, *pn; 235 struct proto_tree *tree; 236 const char *name; 237 int i; 238 239 fprintf(stderr, "protocol %d: name %s\n", 240 proto->id, proto->name); 241 fprintf(stderr, "\tflags: %s, relay flags: %s\n", 242 printb_flags(proto->flags, F_BITS), 243 printb_flags(rlay->rl_conf.flags, F_BITS)); 244 if (proto->tcpflags) 245 fprintf(stderr, "\ttcp flags: %s\n", 246 printb_flags(proto->tcpflags, TCPFLAG_BITS)); 247 if ((rlay->rl_conf.flags & (F_SSL|F_SSLCLIENT)) && proto->sslflags) 248 fprintf(stderr, "\tssl flags: %s\n", 249 printb_flags(proto->sslflags, SSLFLAG_BITS)); 250 if (proto->cache != -1) 251 fprintf(stderr, "\tssl session cache: %d\n", proto->cache); 252 fprintf(stderr, "\ttype: "); 253 switch (proto->type) { 254 case RELAY_PROTO_TCP: 255 fprintf(stderr, "tcp\n"); 256 break; 257 case RELAY_PROTO_HTTP: 258 fprintf(stderr, "http\n"); 259 break; 260 case RELAY_PROTO_DNS: 261 fprintf(stderr, "dns\n"); 262 break; 263 } 264 265 name = "request"; 266 tree = &proto->request_tree; 267 show: 268 i = 0; 269 RB_FOREACH(proot, proto_tree, tree) { 270 #if DEBUG > 1 271 i = 0; 272 #endif 273 PROTONODE_FOREACH(pn, proot, entry) { 274 #if DEBUG > 1 275 i = 0; 276 #endif 277 if (++i > 100) 278 break; 279 relay_nodedebug(name, pn); 280 } 281 /* Limit the number of displayed lines */ 282 if (++i > 100) { 283 fprintf(stderr, "\t\t...\n"); 284 break; 285 } 286 } 287 if (tree == &proto->request_tree) { 288 name = "response"; 289 tree = &proto->response_tree; 290 goto show; 291 } 292 } 293 294 int 295 relay_privinit(struct relay *rlay) 296 { 297 extern int debug; 298 299 log_debug("%s: adding relay %s", __func__, rlay->rl_conf.name); 300 301 if (debug) 302 relay_protodebug(rlay); 303 304 switch (rlay->rl_proto->type) { 305 case RELAY_PROTO_DNS: 306 relay_udp_privinit(env, rlay); 307 break; 308 case RELAY_PROTO_TCP: 309 case RELAY_PROTO_HTTP: 310 /* Use defaults */ 311 break; 312 } 313 314 if (rlay->rl_conf.flags & F_UDP) 315 rlay->rl_s = relay_udp_bind(&rlay->rl_conf.ss, 316 rlay->rl_conf.port, rlay->rl_proto); 317 else 318 rlay->rl_s = relay_socket_listen(&rlay->rl_conf.ss, 319 rlay->rl_conf.port, rlay->rl_proto); 320 if (rlay->rl_s == -1) 321 return (-1); 322 323 return (0); 324 } 325 326 void 327 relay_init(struct privsep *ps, struct privsep_proc *p, void *arg) 328 { 329 struct timeval tv; 330 331 if (config_init(ps->ps_env) == -1) 332 fatal("failed to initialize configuration"); 333 334 /* We use a custom shutdown callback */ 335 p->p_shutdown = relay_shutdown; 336 337 /* Unlimited file descriptors (use system limits) */ 338 socket_rlimit(-1); 339 340 /* Schedule statistics timer */ 341 evtimer_set(&env->sc_statev, relay_statistics, NULL); 342 bcopy(&env->sc_statinterval, &tv, sizeof(tv)); 343 evtimer_add(&env->sc_statev, &tv); 344 } 345 346 void 347 relay_statistics(int fd, short events, void *arg) 348 { 349 struct relay *rlay; 350 struct ctl_stats crs, *cur; 351 struct timeval tv, tv_now; 352 int resethour = 0, resetday = 0; 353 struct rsession *con, *next_con; 354 355 /* 356 * This is a hack to calculate some average statistics. 357 * It doesn't try to be very accurate, but could be improved... 358 */ 359 360 timerclear(&tv); 361 if (gettimeofday(&tv_now, NULL) == -1) 362 fatal("relay_init: gettimeofday"); 363 364 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) { 365 bzero(&crs, sizeof(crs)); 366 resethour = resetday = 0; 367 368 cur = &rlay->rl_stats[proc_id]; 369 cur->cnt += cur->last; 370 cur->tick++; 371 cur->avg = (cur->last + cur->avg) / 2; 372 cur->last_hour += cur->last; 373 if ((cur->tick % (3600 / env->sc_statinterval.tv_sec)) == 0) { 374 cur->avg_hour = (cur->last_hour + cur->avg_hour) / 2; 375 resethour++; 376 } 377 cur->last_day += cur->last; 378 if ((cur->tick % (86400 / env->sc_statinterval.tv_sec)) == 0) { 379 cur->avg_day = (cur->last_day + cur->avg_day) / 2; 380 resethour++; 381 } 382 bcopy(cur, &crs, sizeof(crs)); 383 384 cur->last = 0; 385 if (resethour) 386 cur->last_hour = 0; 387 if (resetday) 388 cur->last_day = 0; 389 390 crs.id = rlay->rl_conf.id; 391 crs.proc = proc_id; 392 proc_compose_imsg(env->sc_ps, PROC_PFE, -1, IMSG_STATISTICS, -1, 393 &crs, sizeof(crs)); 394 395 for (con = SPLAY_ROOT(&rlay->rl_sessions); 396 con != NULL; con = next_con) { 397 next_con = SPLAY_NEXT(session_tree, 398 &rlay->rl_sessions, con); 399 timersub(&tv_now, &con->se_tv_last, &tv); 400 if (timercmp(&tv, &rlay->rl_conf.timeout, >=)) 401 relay_close(con, "hard timeout"); 402 } 403 } 404 405 /* Schedule statistics timer */ 406 evtimer_set(&env->sc_statev, relay_statistics, NULL); 407 bcopy(&env->sc_statinterval, &tv, sizeof(tv)); 408 evtimer_add(&env->sc_statev, &tv); 409 } 410 411 void 412 relay_launch(void) 413 { 414 void (*callback)(int, short, void *); 415 struct relay *rlay; 416 struct host *host; 417 418 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) { 419 if ((rlay->rl_conf.flags & (F_SSL|F_SSLCLIENT)) && 420 (rlay->rl_ssl_ctx = relay_ssl_ctx_create(rlay)) == NULL) 421 fatal("relay_init: failed to create SSL context"); 422 423 if (rlay->rl_dsttable != NULL) { 424 switch (rlay->rl_conf.dstmode) { 425 case RELAY_DSTMODE_ROUNDROBIN: 426 rlay->rl_dstkey = 0; 427 break; 428 case RELAY_DSTMODE_LOADBALANCE: 429 case RELAY_DSTMODE_HASH: 430 rlay->rl_dstkey = 431 hash32_str(rlay->rl_conf.name, HASHINIT); 432 rlay->rl_dstkey = 433 hash32_str(rlay->rl_dsttable->conf.name, 434 rlay->rl_dstkey); 435 break; 436 } 437 rlay->rl_dstnhosts = 0; 438 TAILQ_FOREACH(host, &rlay->rl_dsttable->hosts, entry) { 439 if (rlay->rl_dstnhosts >= RELAY_MAXHOSTS) 440 fatal("relay_init: " 441 "too many hosts in table"); 442 host->idx = rlay->rl_dstnhosts; 443 rlay->rl_dsthost[rlay->rl_dstnhosts++] = host; 444 } 445 log_info("adding %d hosts from table %s%s", 446 rlay->rl_dstnhosts, rlay->rl_dsttable->conf.name, 447 rlay->rl_dsttable->conf.check ? "" : " (no check)"); 448 } 449 450 switch (rlay->rl_proto->type) { 451 case RELAY_PROTO_DNS: 452 relay_udp_init(rlay); 453 break; 454 case RELAY_PROTO_TCP: 455 case RELAY_PROTO_HTTP: 456 /* Use defaults */ 457 break; 458 } 459 460 log_debug("%s: running relay %s", __func__, 461 rlay->rl_conf.name); 462 463 rlay->rl_up = HOST_UP; 464 465 if (rlay->rl_conf.flags & F_UDP) 466 callback = relay_udp_server; 467 else 468 callback = relay_accept; 469 470 event_set(&rlay->rl_ev, rlay->rl_s, EV_READ|EV_PERSIST, 471 callback, rlay); 472 event_add(&rlay->rl_ev, NULL); 473 } 474 } 475 476 int 477 relay_socket_af(struct sockaddr_storage *ss, in_port_t port) 478 { 479 switch (ss->ss_family) { 480 case AF_INET: 481 ((struct sockaddr_in *)ss)->sin_port = port; 482 ((struct sockaddr_in *)ss)->sin_len = 483 sizeof(struct sockaddr_in); 484 break; 485 case AF_INET6: 486 ((struct sockaddr_in6 *)ss)->sin6_port = port; 487 ((struct sockaddr_in6 *)ss)->sin6_len = 488 sizeof(struct sockaddr_in6); 489 break; 490 default: 491 return (-1); 492 } 493 494 return (0); 495 } 496 497 in_port_t 498 relay_socket_getport(struct sockaddr_storage *ss) 499 { 500 switch (ss->ss_family) { 501 case AF_INET: 502 return (((struct sockaddr_in *)ss)->sin_port); 503 case AF_INET6: 504 return (((struct sockaddr_in6 *)ss)->sin6_port); 505 default: 506 return (0); 507 } 508 509 /* NOTREACHED */ 510 return (0); 511 } 512 513 int 514 relay_socket(struct sockaddr_storage *ss, in_port_t port, 515 struct protocol *proto, int fd, int reuseport) 516 { 517 int s = -1, val; 518 struct linger lng; 519 520 if (relay_socket_af(ss, port) == -1) 521 goto bad; 522 523 s = fd == -1 ? socket(ss->ss_family, SOCK_STREAM, IPPROTO_TCP) : fd; 524 if (s == -1) 525 goto bad; 526 527 /* 528 * Socket options 529 */ 530 bzero(&lng, sizeof(lng)); 531 if (setsockopt(s, SOL_SOCKET, SO_LINGER, &lng, sizeof(lng)) == -1) 532 goto bad; 533 if (reuseport) { 534 val = 1; 535 if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &val, 536 sizeof(int)) == -1) 537 goto bad; 538 } 539 if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) 540 goto bad; 541 if (proto->tcpflags & TCPFLAG_BUFSIZ) { 542 val = proto->tcpbufsiz; 543 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, 544 &val, sizeof(val)) == -1) 545 goto bad; 546 val = proto->tcpbufsiz; 547 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 548 &val, sizeof(val)) == -1) 549 goto bad; 550 } 551 552 /* 553 * IP options 554 */ 555 if (proto->tcpflags & TCPFLAG_IPTTL) { 556 val = (int)proto->tcpipttl; 557 if (setsockopt(s, IPPROTO_IP, IP_TTL, 558 &val, sizeof(val)) == -1) 559 goto bad; 560 } 561 if (proto->tcpflags & TCPFLAG_IPMINTTL) { 562 val = (int)proto->tcpipminttl; 563 if (setsockopt(s, IPPROTO_IP, IP_MINTTL, 564 &val, sizeof(val)) == -1) 565 goto bad; 566 } 567 568 /* 569 * TCP options 570 */ 571 if (proto->tcpflags & (TCPFLAG_NODELAY|TCPFLAG_NNODELAY)) { 572 if (proto->tcpflags & TCPFLAG_NNODELAY) 573 val = 0; 574 else 575 val = 1; 576 if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, 577 &val, sizeof(val)) == -1) 578 goto bad; 579 } 580 if (proto->tcpflags & (TCPFLAG_SACK|TCPFLAG_NSACK)) { 581 if (proto->tcpflags & TCPFLAG_NSACK) 582 val = 0; 583 else 584 val = 1; 585 if (setsockopt(s, IPPROTO_TCP, TCP_SACK_ENABLE, 586 &val, sizeof(val)) == -1) 587 goto bad; 588 } 589 590 return (s); 591 592 bad: 593 if (s != -1) 594 close(s); 595 return (-1); 596 } 597 598 int 599 relay_socket_connect(struct sockaddr_storage *ss, in_port_t port, 600 struct protocol *proto, int fd) 601 { 602 int s; 603 604 if ((s = relay_socket(ss, port, proto, fd, 0)) == -1) 605 return (-1); 606 607 if (connect(s, (struct sockaddr *)ss, ss->ss_len) == -1) { 608 if (errno != EINPROGRESS) 609 goto bad; 610 } 611 612 return (s); 613 614 bad: 615 close(s); 616 return (-1); 617 } 618 619 int 620 relay_socket_listen(struct sockaddr_storage *ss, in_port_t port, 621 struct protocol *proto) 622 { 623 int s; 624 625 if ((s = relay_socket(ss, port, proto, -1, 1)) == -1) 626 return (-1); 627 628 if (bind(s, (struct sockaddr *)ss, ss->ss_len) == -1) 629 goto bad; 630 if (listen(s, proto->tcpbacklog) == -1) 631 goto bad; 632 633 return (s); 634 635 bad: 636 close(s); 637 return (-1); 638 } 639 640 void 641 relay_connected(int fd, short sig, void *arg) 642 { 643 struct rsession *con = (struct rsession *)arg; 644 struct relay *rlay = (struct relay *)con->se_relay; 645 struct protocol *proto = rlay->rl_proto; 646 evbuffercb outrd = relay_read; 647 evbuffercb outwr = relay_write; 648 struct bufferevent *bev; 649 struct ctl_relay_event *out = &con->se_out; 650 651 if (sig == EV_TIMEOUT) { 652 relay_close_http(con, 504, "connect timeout", 0); 653 return; 654 } 655 656 if ((rlay->rl_conf.flags & F_SSLCLIENT) && (out->ssl == NULL)) { 657 relay_ssl_transaction(con, out); 658 return; 659 } 660 661 DPRINTF("%s: session %d: %ssuccessful", __func__, 662 con->se_id, rlay->rl_proto->lateconnect ? "late connect " : ""); 663 664 switch (rlay->rl_proto->type) { 665 case RELAY_PROTO_HTTP: 666 /* Check the servers's HTTP response */ 667 if (!RB_EMPTY(&rlay->rl_proto->response_tree)) { 668 outrd = relay_read_http; 669 if ((con->se_out.nodes = calloc(proto->response_nodes, 670 sizeof(u_int8_t))) == NULL) { 671 relay_close_http(con, 500, 672 "failed to allocate nodes", 0); 673 return; 674 } 675 } 676 break; 677 case RELAY_PROTO_TCP: 678 if ((proto->tcpflags & TCPFLAG_NSPLICE) || 679 (rlay->rl_conf.flags & (F_SSL|F_SSLCLIENT))) 680 break; 681 if (setsockopt(con->se_in.s, SOL_SOCKET, SO_SPLICE, 682 &con->se_out.s, sizeof(int)) == -1) { 683 log_debug("%s: session %d: splice forward failed: %s", 684 __func__, con->se_id, strerror(errno)); 685 return; 686 } 687 con->se_in.splicelen = 0; 688 if (setsockopt(con->se_out.s, SOL_SOCKET, SO_SPLICE, 689 &con->se_in.s, sizeof(int)) == -1) { 690 log_debug("%s: session %d: splice backward failed: %s", 691 __func__, con->se_id, strerror(errno)); 692 return; 693 } 694 con->se_out.splicelen = 0; 695 break; 696 default: 697 fatalx("relay_input: unknown protocol"); 698 } 699 700 /* 701 * Relay <-> Server 702 */ 703 bev = bufferevent_new(fd, outrd, outwr, relay_error, &con->se_out); 704 if (bev == NULL) { 705 relay_close_http(con, 500, 706 "failed to allocate output buffer event", 0); 707 return; 708 } 709 evbuffer_free(bev->output); 710 bev->output = con->se_out.output; 711 if (bev->output == NULL) 712 fatal("relay_connected: invalid output buffer"); 713 con->se_out.bev = bev; 714 715 /* Initialize the SSL wrapper */ 716 if ((rlay->rl_conf.flags & F_SSLCLIENT) && (out->ssl != NULL)) 717 relay_ssl_connected(out); 718 719 bufferevent_settimeout(bev, 720 rlay->rl_conf.timeout.tv_sec, rlay->rl_conf.timeout.tv_sec); 721 bufferevent_enable(bev, EV_READ|EV_WRITE); 722 } 723 724 void 725 relay_input(struct rsession *con) 726 { 727 struct relay *rlay = (struct relay *)con->se_relay; 728 struct protocol *proto = rlay->rl_proto; 729 evbuffercb inrd = relay_read; 730 evbuffercb inwr = relay_write; 731 732 switch (rlay->rl_proto->type) { 733 case RELAY_PROTO_HTTP: 734 /* Check the client's HTTP request */ 735 if (!RB_EMPTY(&rlay->rl_proto->request_tree) || 736 proto->lateconnect) { 737 inrd = relay_read_http; 738 if ((con->se_in.nodes = calloc(proto->request_nodes, 739 sizeof(u_int8_t))) == NULL) { 740 relay_close(con, "failed to allocate nodes"); 741 return; 742 } 743 } 744 break; 745 case RELAY_PROTO_TCP: 746 /* Use defaults */ 747 break; 748 default: 749 fatalx("relay_input: unknown protocol"); 750 } 751 752 /* 753 * Client <-> Relay 754 */ 755 con->se_in.bev = bufferevent_new(con->se_in.s, inrd, inwr, 756 relay_error, &con->se_in); 757 if (con->se_in.bev == NULL) { 758 relay_close(con, "failed to allocate input buffer event"); 759 return; 760 } 761 762 /* Initialize the SSL wrapper */ 763 if ((rlay->rl_conf.flags & F_SSL) && con->se_in.ssl != NULL) 764 relay_ssl_connected(&con->se_in); 765 766 bufferevent_settimeout(con->se_in.bev, 767 rlay->rl_conf.timeout.tv_sec, rlay->rl_conf.timeout.tv_sec); 768 bufferevent_enable(con->se_in.bev, EV_READ|EV_WRITE); 769 } 770 771 void 772 relay_write(struct bufferevent *bev, void *arg) 773 { 774 struct ctl_relay_event *cre = (struct ctl_relay_event *)arg; 775 struct rsession *con = cre->con; 776 if (gettimeofday(&con->se_tv_last, NULL) == -1) 777 con->se_done = 1; 778 if (con->se_done) 779 relay_close(con, "last write (done)"); 780 } 781 782 void 783 relay_dump(struct ctl_relay_event *cre, const void *buf, size_t len) 784 { 785 if (!len) 786 return; 787 788 /* 789 * This function will dump the specified message directly 790 * to the underlying session, without waiting for success 791 * of non-blocking events etc. This is useful to print an 792 * error message before gracefully closing the session. 793 */ 794 if (cre->ssl != NULL) 795 (void)SSL_write(cre->ssl, buf, len); 796 else 797 (void)write(cre->s, buf, len); 798 } 799 800 void 801 relay_read(struct bufferevent *bev, void *arg) 802 { 803 struct ctl_relay_event *cre = (struct ctl_relay_event *)arg; 804 struct rsession *con = cre->con; 805 struct evbuffer *src = EVBUFFER_INPUT(bev); 806 807 if (gettimeofday(&con->se_tv_last, NULL) == -1) 808 goto fail; 809 if (!EVBUFFER_LENGTH(src)) 810 return; 811 if (relay_bufferevent_write_buffer(cre->dst, src) == -1) 812 goto fail; 813 if (con->se_done) 814 goto done; 815 if (cre->dst->bev) 816 bufferevent_enable(cre->dst->bev, EV_READ); 817 return; 818 done: 819 relay_close(con, "last read (done)"); 820 return; 821 fail: 822 relay_close(con, strerror(errno)); 823 } 824 825 int 826 relay_resolve(struct ctl_relay_event *cre, 827 struct protonode *proot, struct protonode *pn) 828 { 829 struct rsession *con = cre->con; 830 char buf[IBUF_READ_SIZE], *ptr; 831 int id; 832 833 if (pn->mark && (pn->mark != con->se_mark)) 834 return (0); 835 836 switch (pn->action) { 837 case NODE_ACTION_FILTER: 838 id = cre->nodes[proot->id]; 839 if (SIMPLEQ_NEXT(pn, entry) == NULL) 840 cre->nodes[proot->id] = 0; 841 if (id <= 1) 842 return (0); 843 break; 844 case NODE_ACTION_EXPECT: 845 id = cre->nodes[proot->id]; 846 if (SIMPLEQ_NEXT(pn, entry) == NULL) 847 cre->nodes[proot->id] = 0; 848 if (id > 1) 849 return (0); 850 break; 851 default: 852 if (cre->nodes[pn->id]) { 853 cre->nodes[pn->id] = 0; 854 return (0); 855 } 856 break; 857 } 858 switch (pn->action) { 859 case NODE_ACTION_APPEND: 860 case NODE_ACTION_CHANGE: 861 ptr = pn->value; 862 if ((pn->flags & PNFLAG_MACRO) && 863 (ptr = relay_expand_http(cre, pn->value, 864 buf, sizeof(buf))) == NULL) 865 break; 866 if (relay_bufferevent_print(cre->dst, pn->key) == -1 || 867 relay_bufferevent_print(cre->dst, ": ") == -1 || 868 relay_bufferevent_print(cre->dst, ptr) == -1 || 869 relay_bufferevent_print(cre->dst, "\r\n") == -1) { 870 relay_close_http(con, 500, 871 "failed to modify header", 0); 872 return (-1); 873 } 874 DPRINTF("%s: add '%s: %s'", __func__, pn->key, ptr); 875 break; 876 case NODE_ACTION_EXPECT: 877 DPRINTF("%s: missing '%s: %s'", __func__, pn->key, pn->value); 878 relay_close_http(con, 403, "incomplete request", pn->label); 879 return (-1); 880 case NODE_ACTION_FILTER: 881 DPRINTF("%s: filtered '%s: %s'", __func__, pn->key, pn->value); 882 relay_close_http(con, 403, "rejecting request", pn->label); 883 return (-1); 884 default: 885 break; 886 } 887 return (0); 888 } 889 890 char * 891 relay_expand_http(struct ctl_relay_event *cre, char *val, char *buf, size_t len) 892 { 893 struct rsession *con = cre->con; 894 struct relay *rlay = (struct relay *)con->se_relay; 895 char ibuf[128]; 896 897 (void)strlcpy(buf, val, len); 898 899 if (strstr(val, "$REMOTE_") != NULL) { 900 if (strstr(val, "$REMOTE_ADDR") != NULL) { 901 if (print_host(&cre->ss, ibuf, sizeof(ibuf)) == NULL) 902 return (NULL); 903 if (expand_string(buf, len, 904 "$REMOTE_ADDR", ibuf) != 0) 905 return (NULL); 906 } 907 if (strstr(val, "$REMOTE_PORT") != NULL) { 908 snprintf(ibuf, sizeof(ibuf), "%u", ntohs(cre->port)); 909 if (expand_string(buf, len, 910 "$REMOTE_PORT", ibuf) != 0) 911 return (NULL); 912 } 913 } 914 if (strstr(val, "$SERVER_") != NULL) { 915 if (strstr(val, "$SERVER_ADDR") != NULL) { 916 if (print_host(&rlay->rl_conf.ss, 917 ibuf, sizeof(ibuf)) == NULL) 918 return (NULL); 919 if (expand_string(buf, len, 920 "$SERVER_ADDR", ibuf) != 0) 921 return (NULL); 922 } 923 if (strstr(val, "$SERVER_PORT") != NULL) { 924 snprintf(ibuf, sizeof(ibuf), "%u", 925 ntohs(rlay->rl_conf.port)); 926 if (expand_string(buf, len, 927 "$SERVER_PORT", ibuf) != 0) 928 return (NULL); 929 } 930 if (strstr(val, "$SERVER_NAME") != NULL) { 931 if (expand_string(buf, len, 932 "$SERVER_NAME", RELAYD_SERVERNAME) != 0) 933 return (NULL); 934 } 935 } 936 if (strstr(val, "$TIMEOUT") != NULL) { 937 snprintf(ibuf, sizeof(ibuf), "%lu", 938 rlay->rl_conf.timeout.tv_sec); 939 if (expand_string(buf, len, "$TIMEOUT", ibuf) != 0) 940 return (NULL); 941 } 942 943 return (buf); 944 } 945 946 int 947 relay_lognode(struct rsession *con, struct protonode *pn, struct protonode *pk, 948 char *buf, size_t len) 949 { 950 const char *label = NULL; 951 952 if ((pn->flags & PNFLAG_LOG) == 0) 953 return (0); 954 bzero(buf, len); 955 if (pn->label != 0) 956 label = pn_id2name(pn->label); 957 if (snprintf(buf, len, " [%s%s%s: %s]", 958 label == NULL ? "" : label, 959 label == NULL ? "" : ", ", 960 pk->key, pk->value) == -1 || 961 evbuffer_add(con->se_log, buf, strlen(buf)) == -1) 962 return (-1); 963 return (0); 964 } 965 966 int 967 relay_handle_http(struct ctl_relay_event *cre, struct protonode *proot, 968 struct protonode *pn, struct protonode *pk, int header) 969 { 970 struct rsession *con = cre->con; 971 char buf[IBUF_READ_SIZE], *ptr; 972 int ret = PN_DROP, mark = 0; 973 struct protonode *next; 974 975 /* Check if this action depends on a marked session */ 976 if (pn->mark != 0) 977 mark = pn->mark == con->se_mark ? 1 : -1; 978 979 switch (pn->action) { 980 case NODE_ACTION_EXPECT: 981 case NODE_ACTION_FILTER: 982 case NODE_ACTION_MARK: 983 break; 984 default: 985 if (mark == -1) 986 return (PN_PASS); 987 break; 988 } 989 990 switch (pn->action) { 991 case NODE_ACTION_APPEND: 992 if (!header) 993 return (PN_PASS); 994 ptr = pn->value; 995 if ((pn->flags & PNFLAG_MACRO) && 996 (ptr = relay_expand_http(cre, pn->value, 997 buf, sizeof(buf))) == NULL) 998 break; 999 if (relay_bufferevent_print(cre->dst, pn->key) == -1 || 1000 relay_bufferevent_print(cre->dst, ": ") == -1 || 1001 relay_bufferevent_print(cre->dst, pk->value) == -1 || 1002 relay_bufferevent_print(cre->dst, ", ") == -1 || 1003 relay_bufferevent_print(cre->dst, ptr) == -1 || 1004 relay_bufferevent_print(cre->dst, "\r\n") == -1) 1005 goto fail; 1006 cre->nodes[pn->id] = 1; 1007 DPRINTF("%s: append '%s: %s, %s'", __func__, 1008 pk->key, pk->value, ptr); 1009 break; 1010 case NODE_ACTION_CHANGE: 1011 case NODE_ACTION_REMOVE: 1012 if (!header) 1013 return (PN_PASS); 1014 DPRINTF("%s: change/remove '%s: %s'", __func__, 1015 pk->key, pk->value); 1016 break; 1017 case NODE_ACTION_EXPECT: 1018 /* 1019 * A client may specify the header line for multiple times 1020 * trying to circumvent the filter. 1021 */ 1022 if (cre->nodes[proot->id] > 1) { 1023 relay_close_http(con, 400, "repeated header line", 0); 1024 return (PN_FAIL); 1025 } 1026 /* FALLTHROUGH */ 1027 case NODE_ACTION_FILTER: 1028 DPRINTF("%s: %s '%s: %s'", __func__, 1029 (pn->action == NODE_ACTION_EXPECT) ? "expect" : "filter", 1030 pn->key, pn->value); 1031 1032 /* Do not drop the entity */ 1033 ret = PN_PASS; 1034 1035 if (mark != -1 && 1036 fnmatch(pn->value, pk->value, FNM_CASEFOLD) == 0) { 1037 cre->nodes[proot->id] = 1; 1038 1039 /* Fail instantly */ 1040 if (pn->action == NODE_ACTION_FILTER) { 1041 (void)relay_lognode(con, pn, pk, 1042 buf, sizeof(buf)); 1043 relay_close_http(con, 403, 1044 "rejecting request", pn->label); 1045 return (PN_FAIL); 1046 } 1047 } 1048 next = SIMPLEQ_NEXT(pn, entry); 1049 if (next == NULL || next->action != pn->action) 1050 cre->nodes[proot->id]++; 1051 break; 1052 case NODE_ACTION_HASH: 1053 DPRINTF("%s: hash '%s: %s'", __func__, 1054 pn->key, pk->value); 1055 con->se_hashkey = hash32_str(pk->value, con->se_hashkey); 1056 ret = PN_PASS; 1057 break; 1058 case NODE_ACTION_LOG: 1059 DPRINTF("%s: log '%s: %s'", __func__, 1060 pn->key, pk->value); 1061 ret = PN_PASS; 1062 break; 1063 case NODE_ACTION_MARK: 1064 DPRINTF("%s: mark '%s: %s'", __func__, 1065 pn->key, pk->value); 1066 if (fnmatch(pn->value, pk->value, FNM_CASEFOLD) == 0) 1067 con->se_mark = pn->mark; 1068 ret = PN_PASS; 1069 break; 1070 case NODE_ACTION_NONE: 1071 return (PN_PASS); 1072 } 1073 if (mark != -1 && relay_lognode(con, pn, pk, buf, sizeof(buf)) == -1) 1074 goto fail; 1075 1076 return (ret); 1077 fail: 1078 relay_close_http(con, 500, strerror(errno), 0); 1079 return (PN_FAIL); 1080 } 1081 1082 void 1083 relay_read_httpcontent(struct bufferevent *bev, void *arg) 1084 { 1085 struct ctl_relay_event *cre = (struct ctl_relay_event *)arg; 1086 struct rsession *con = cre->con; 1087 struct evbuffer *src = EVBUFFER_INPUT(bev); 1088 size_t size; 1089 1090 if (gettimeofday(&con->se_tv_last, NULL) == -1) 1091 goto fail; 1092 size = EVBUFFER_LENGTH(src); 1093 DPRINTF("%s: size %d, to read %d", __func__, 1094 size, cre->toread); 1095 if (!size) 1096 return; 1097 if (relay_bufferevent_write_buffer(cre->dst, src) == -1) 1098 goto fail; 1099 if (size >= cre->toread) 1100 bev->readcb = relay_read_http; 1101 cre->toread -= size; 1102 DPRINTF("%s: done, size %d, to read %d", __func__, 1103 size, cre->toread); 1104 if (con->se_done) 1105 goto done; 1106 if (bev->readcb != relay_read_httpcontent) 1107 bev->readcb(bev, arg); 1108 bufferevent_enable(bev, EV_READ); 1109 return; 1110 done: 1111 relay_close(con, "last http content read"); 1112 return; 1113 fail: 1114 relay_close(con, strerror(errno)); 1115 } 1116 1117 void 1118 relay_read_httpchunks(struct bufferevent *bev, void *arg) 1119 { 1120 struct ctl_relay_event *cre = (struct ctl_relay_event *)arg; 1121 struct rsession *con = cre->con; 1122 struct evbuffer *src = EVBUFFER_INPUT(bev); 1123 char *line; 1124 long lval; 1125 size_t size; 1126 1127 if (gettimeofday(&con->se_tv_last, NULL) == -1) 1128 goto fail; 1129 size = EVBUFFER_LENGTH(src); 1130 DPRINTF("%s: size %d, to read %d", __func__, 1131 size, cre->toread); 1132 if (!size) 1133 return; 1134 1135 if (!cre->toread) { 1136 line = evbuffer_readline(src); 1137 if (line == NULL) { 1138 /* Ignore empty line, continue */ 1139 bufferevent_enable(bev, EV_READ); 1140 return; 1141 } 1142 if (!strlen(line)) { 1143 free(line); 1144 goto next; 1145 } 1146 1147 /* Read prepended chunk size in hex, ingore the trailer */ 1148 if (sscanf(line, "%lx", &lval) != 1) { 1149 free(line); 1150 relay_close(con, "invalid chunk size"); 1151 return; 1152 } 1153 1154 if (relay_bufferevent_print(cre->dst, line) == -1 || 1155 relay_bufferevent_print(cre->dst, "\r\n") == -1) { 1156 free(line); 1157 goto fail; 1158 } 1159 free(line); 1160 1161 /* Last chunk is 0 bytes followed by an empty newline */ 1162 if ((cre->toread = lval) == 0) { 1163 DPRINTF("%s: last chunk", __func__); 1164 1165 line = evbuffer_readline(src); 1166 if (line == NULL) { 1167 relay_close(con, "invalid last chunk"); 1168 return; 1169 } 1170 free(line); 1171 if (relay_bufferevent_print(cre->dst, "\r\n") == -1) 1172 goto fail; 1173 1174 /* Switch to HTTP header mode */ 1175 bev->readcb = relay_read_http; 1176 } 1177 } else { 1178 /* Read chunk data */ 1179 if (size > cre->toread) 1180 size = cre->toread; 1181 if (relay_bufferevent_write_chunk(cre->dst, src, size) == -1) 1182 goto fail; 1183 cre->toread -= size; 1184 DPRINTF("%s: done, size %d, to read %d", __func__, 1185 size, cre->toread); 1186 1187 if (cre->toread == 0) { 1188 /* Chunk is terminated by an empty (empty) newline */ 1189 line = evbuffer_readline(src); 1190 if (line != NULL) 1191 free(line); 1192 if (relay_bufferevent_print(cre->dst, "\r\n\r\n") == -1) 1193 goto fail; 1194 } 1195 } 1196 1197 next: 1198 if (con->se_done) 1199 goto done; 1200 if (EVBUFFER_LENGTH(src)) 1201 bev->readcb(bev, arg); 1202 bufferevent_enable(bev, EV_READ); 1203 return; 1204 1205 done: 1206 relay_close(con, "last http chunk read (done)"); 1207 return; 1208 fail: 1209 relay_close(con, strerror(errno)); 1210 } 1211 1212 void 1213 relay_http_request_close(struct ctl_relay_event *cre) 1214 { 1215 if (cre->path != NULL) { 1216 free(cre->path); 1217 cre->path = NULL; 1218 } 1219 1220 cre->args = NULL; 1221 cre->version = NULL; 1222 1223 if (cre->buf != NULL) { 1224 free(cre->buf); 1225 cre->buf = NULL; 1226 cre->buflen = 0; 1227 } 1228 1229 cre->line = 0; 1230 cre->method = 0; 1231 cre->done = 0; 1232 cre->chunked = 0; 1233 } 1234 1235 void 1236 relay_read_http(struct bufferevent *bev, void *arg) 1237 { 1238 struct ctl_relay_event *cre = (struct ctl_relay_event *)arg; 1239 struct rsession *con = cre->con; 1240 struct relay *rlay = (struct relay *)con->se_relay; 1241 struct protocol *proto = rlay->rl_proto; 1242 struct evbuffer *src = EVBUFFER_INPUT(bev); 1243 struct protonode *pn, pk, *proot, *pnv = NULL, pkv; 1244 char *line; 1245 int header = 0, ret, pass = 0; 1246 const char *errstr; 1247 size_t size; 1248 1249 if (gettimeofday(&con->se_tv_last, NULL) == -1) 1250 goto fail; 1251 size = EVBUFFER_LENGTH(src); 1252 DPRINTF("%s: size %d, to read %d", __func__, size, cre->toread); 1253 if (!size) { 1254 if (cre->dir == RELAY_DIR_RESPONSE) 1255 return; 1256 cre->toread = 0; 1257 goto done; 1258 } 1259 1260 pk.type = NODE_TYPE_HEADER; 1261 1262 while (!cre->done && (line = evbuffer_readline(src)) != NULL) { 1263 /* 1264 * An empty line indicates the end of the request. 1265 * libevent already stripped the \r\n for us. 1266 */ 1267 if (!strlen(line)) { 1268 cre->done = 1; 1269 free(line); 1270 break; 1271 } 1272 pk.key = line; 1273 1274 /* 1275 * The first line is the GET/POST/PUT/... request, 1276 * subsequent lines are HTTP headers. 1277 */ 1278 if (++cre->line == 1) { 1279 pk.value = strchr(pk.key, ' '); 1280 } else 1281 pk.value = strchr(pk.key, ':'); 1282 if (pk.value == NULL || strlen(pk.value) < 3) { 1283 if (cre->line == 1) { 1284 free(line); 1285 relay_close_http(con, 400, "malformed", 0); 1286 return; 1287 } 1288 1289 DPRINTF("%s: request '%s'", __func__, line); 1290 /* Append line to the output buffer */ 1291 if (relay_bufferevent_print(cre->dst, line) == -1 || 1292 relay_bufferevent_print(cre->dst, "\r\n") == -1) { 1293 free(line); 1294 goto fail; 1295 } 1296 free(line); 1297 continue; 1298 } 1299 if (*pk.value == ':') { 1300 *pk.value++ = '\0'; 1301 pk.value += strspn(pk.value, " \t\r\n"); 1302 header = 1; 1303 } else { 1304 *pk.value++ = '\0'; 1305 header = 0; 1306 } 1307 1308 DPRINTF("%s: header '%s: %s'", __func__, pk.key, pk.value); 1309 1310 /* 1311 * Identify and handle specific HTTP request methods 1312 */ 1313 if (cre->line == 1) { 1314 if (cre->dir == RELAY_DIR_RESPONSE) { 1315 cre->method = HTTP_METHOD_RESPONSE; 1316 goto lookup; 1317 } else if (strcmp("HEAD", pk.key) == 0) 1318 cre->method = HTTP_METHOD_HEAD; 1319 else if (strcmp("POST", pk.key) == 0) 1320 cre->method = HTTP_METHOD_POST; 1321 else if (strcmp("PUT", pk.key) == 0) 1322 cre->method = HTTP_METHOD_PUT; 1323 else if (strcmp("DELETE", pk.key) == 0) 1324 cre->method = HTTP_METHOD_DELETE; 1325 else if (strcmp("OPTIONS", pk.key) == 0) 1326 cre->method = HTTP_METHOD_OPTIONS; 1327 else if (strcmp("TRACE", pk.key) == 0) 1328 cre->method = HTTP_METHOD_TRACE; 1329 else if (strcmp("CONNECT", pk.key) == 0) 1330 cre->method = HTTP_METHOD_CONNECT; 1331 else { 1332 /* Use GET method as the default */ 1333 cre->method = HTTP_METHOD_GET; 1334 } 1335 1336 /* 1337 * Decode the path and query 1338 */ 1339 cre->path = strdup(pk.value); 1340 if (cre->path == NULL) { 1341 free(line); 1342 goto fail; 1343 } 1344 cre->version = strchr(cre->path, ' '); 1345 if (cre->version != NULL) 1346 *cre->version++ = '\0'; 1347 cre->args = strchr(cre->path, '?'); 1348 if (cre->args != NULL) 1349 *cre->args++ = '\0'; 1350 #ifdef DEBUG 1351 char buf[BUFSIZ]; 1352 if (snprintf(buf, sizeof(buf), " \"%s\"", 1353 cre->path) == -1 || 1354 evbuffer_add(con->se_log, buf, strlen(buf)) == -1) { 1355 free(line); 1356 goto fail; 1357 } 1358 #endif 1359 1360 /* 1361 * Lookup protocol handlers in the URL path 1362 */ 1363 if ((proto->flags & F_LOOKUP_PATH) == 0) 1364 goto lookup; 1365 1366 pkv.key = cre->path; 1367 pkv.type = NODE_TYPE_PATH; 1368 pkv.value = cre->args == NULL ? "" : cre->args; 1369 1370 DPRINTF("%s: lookup path '%s: %s'", 1371 __func__, pkv.key, pkv.value); 1372 1373 if ((proot = RB_FIND(proto_tree, 1374 cre->tree, &pkv)) == NULL) 1375 goto lookup; 1376 1377 PROTONODE_FOREACH(pnv, proot, entry) { 1378 ret = relay_handle_http(cre, proot, 1379 pnv, &pkv, 0); 1380 if (ret == PN_FAIL) 1381 goto abort; 1382 } 1383 } else if ((cre->method == HTTP_METHOD_POST || 1384 cre->method == HTTP_METHOD_PUT || 1385 cre->method == HTTP_METHOD_RESPONSE) && 1386 strcasecmp("Content-Length", pk.key) == 0) { 1387 /* 1388 * Need to read data from the client after the 1389 * HTTP header. 1390 * XXX What about non-standard clients not using 1391 * the carriage return? And some browsers seem to 1392 * include the line length in the content-length. 1393 */ 1394 cre->toread = strtonum(pk.value, 0, INT_MAX, &errstr); 1395 if (errstr) { 1396 relay_close_http(con, 500, errstr, 0); 1397 goto abort; 1398 } 1399 } 1400 lookup: 1401 if (strcasecmp("Transfer-Encoding", pk.key) == 0 && 1402 strcasecmp("chunked", pk.value) == 0) 1403 cre->chunked = 1; 1404 1405 /* Match the HTTP header */ 1406 if ((pn = RB_FIND(proto_tree, cre->tree, &pk)) == NULL) 1407 goto next; 1408 1409 if (cre->dir == RELAY_DIR_RESPONSE) 1410 goto handle; 1411 1412 if (pn->flags & PNFLAG_LOOKUP_URL) { 1413 /* 1414 * Lookup the URL of type example.com/path?args. 1415 * Either as a plain string or SHA1/MD5 digest. 1416 */ 1417 if ((pn->flags & PNFLAG_LOOKUP_DIGEST(0)) && 1418 relay_lookup_url(cre, pk.value, 1419 DIGEST_NONE) == PN_FAIL) 1420 goto abort; 1421 if ((pn->flags & PNFLAG_LOOKUP_DIGEST(DIGEST_SHA1)) && 1422 relay_lookup_url(cre, pk.value, 1423 DIGEST_SHA1) == PN_FAIL) 1424 goto abort; 1425 if ((pn->flags & PNFLAG_LOOKUP_DIGEST(DIGEST_MD5)) && 1426 relay_lookup_url(cre, pk.value, 1427 DIGEST_MD5) == PN_FAIL) 1428 goto abort; 1429 } else if (pn->flags & PNFLAG_LOOKUP_QUERY) { 1430 /* Lookup the HTTP query arguments */ 1431 if (relay_lookup_query(cre) == PN_FAIL) 1432 goto abort; 1433 } else if (pn->flags & PNFLAG_LOOKUP_COOKIE) { 1434 /* Lookup the HTTP cookie */ 1435 if (relay_lookup_cookie(cre, pk.value) == PN_FAIL) 1436 goto abort; 1437 } 1438 1439 handle: 1440 pass = 0; 1441 PROTONODE_FOREACH(pnv, pn, entry) { 1442 ret = relay_handle_http(cre, pn, pnv, &pk, header); 1443 if (ret == PN_PASS) 1444 pass = 1; 1445 else if (ret == PN_FAIL) 1446 goto abort; 1447 } 1448 1449 if (pass) { 1450 next: 1451 if (relay_bufferevent_print(cre->dst, pk.key) == -1 || 1452 relay_bufferevent_print(cre->dst, 1453 header ? ": " : " ") == -1 || 1454 relay_bufferevent_print(cre->dst, pk.value) == -1 || 1455 relay_bufferevent_print(cre->dst, "\r\n") == -1) { 1456 free(line); 1457 goto fail; 1458 } 1459 } 1460 free(line); 1461 } 1462 if (cre->done) { 1463 RB_FOREACH(proot, proto_tree, cre->tree) { 1464 PROTONODE_FOREACH(pn, proot, entry) 1465 if (relay_resolve(cre, proot, pn) != 0) 1466 return; 1467 } 1468 1469 switch (cre->method) { 1470 case HTTP_METHOD_NONE: 1471 relay_close_http(con, 406, "no method", 0); 1472 return; 1473 case HTTP_METHOD_CONNECT: 1474 /* Data stream */ 1475 bev->readcb = relay_read; 1476 break; 1477 case HTTP_METHOD_POST: 1478 case HTTP_METHOD_PUT: 1479 case HTTP_METHOD_RESPONSE: 1480 /* HTTP request payload */ 1481 if (cre->toread) { 1482 bev->readcb = relay_read_httpcontent; 1483 break; 1484 } 1485 1486 /* Single-pass HTTP response */ 1487 bev->readcb = relay_read; 1488 break; 1489 default: 1490 /* HTTP handler */ 1491 bev->readcb = relay_read_http; 1492 break; 1493 } 1494 if (cre->chunked) { 1495 /* Chunked transfer encoding */ 1496 cre->toread = 0; 1497 bev->readcb = relay_read_httpchunks; 1498 } 1499 1500 /* Write empty newline and switch to relay mode */ 1501 if (relay_bufferevent_print(cre->dst, "\r\n") == -1) 1502 goto fail; 1503 1504 relay_http_request_close(cre); 1505 1506 done: 1507 if (cre->dir == RELAY_DIR_REQUEST && !cre->toread && 1508 proto->lateconnect && cre->dst->bev == NULL) { 1509 if (rlay->rl_conf.fwdmode == FWD_TRANS) { 1510 relay_bindanyreq(con, 0, IPPROTO_TCP); 1511 return; 1512 } 1513 if (relay_connect(con) == -1) 1514 relay_close_http(con, 502, "session failed", 0); 1515 return; 1516 } 1517 } 1518 if (con->se_done) { 1519 relay_close(con, "last http read (done)"); 1520 return; 1521 } 1522 if (EVBUFFER_LENGTH(src) && bev->readcb != relay_read_http) 1523 bev->readcb(bev, arg); 1524 bufferevent_enable(bev, EV_READ); 1525 return; 1526 fail: 1527 relay_close_http(con, 500, strerror(errno), 0); 1528 return; 1529 abort: 1530 free(line); 1531 } 1532 1533 static int 1534 _relay_lookup_url(struct ctl_relay_event *cre, char *host, char *path, 1535 char *query, enum digest_type type) 1536 { 1537 struct rsession *con = cre->con; 1538 struct protonode *proot, *pnv, pkv; 1539 char *val, *md = NULL; 1540 int ret = PN_FAIL; 1541 1542 if (asprintf(&val, "%s%s%s%s", 1543 host, path, 1544 query == NULL ? "" : "?", 1545 query == NULL ? "" : query) == -1) { 1546 relay_close_http(con, 500, "failed to allocate URL", 0); 1547 return (PN_FAIL); 1548 } 1549 1550 DPRINTF("%s: %s", __func__, val); 1551 1552 switch (type) { 1553 case DIGEST_SHA1: 1554 case DIGEST_MD5: 1555 if ((md = digeststr(type, val, strlen(val), NULL)) == NULL) { 1556 relay_close_http(con, 500, 1557 "failed to allocate digest", 0); 1558 goto fail; 1559 } 1560 pkv.key = md; 1561 break; 1562 case DIGEST_NONE: 1563 pkv.key = val; 1564 break; 1565 } 1566 pkv.type = NODE_TYPE_URL; 1567 pkv.value = ""; 1568 1569 if ((proot = RB_FIND(proto_tree, cre->tree, &pkv)) == NULL) 1570 goto done; 1571 1572 PROTONODE_FOREACH(pnv, proot, entry) { 1573 ret = relay_handle_http(cre, proot, pnv, &pkv, 0); 1574 if (ret == PN_FAIL) 1575 goto fail; 1576 } 1577 1578 done: 1579 ret = PN_PASS; 1580 fail: 1581 if (md != NULL) 1582 free(md); 1583 free(val); 1584 return (ret); 1585 } 1586 1587 int 1588 relay_lookup_url(struct ctl_relay_event *cre, const char *str, 1589 enum digest_type type) 1590 { 1591 struct rsession *con = cre->con; 1592 int i, j, dots; 1593 char *hi[RELAY_MAXLOOKUPLEVELS], *p, *pp, *c, ch; 1594 char ph[MAXHOSTNAMELEN]; 1595 int ret; 1596 1597 if (cre->path == NULL) 1598 return (PN_PASS); 1599 1600 /* 1601 * This is an URL lookup algorithm inspired by 1602 * http://code.google.com/apis/safebrowsing/ 1603 * developers_guide.html#PerformingLookups 1604 */ 1605 1606 DPRINTF("%s: host: '%s', path: '%s', query: '%s'", __func__, 1607 str, cre->path, cre->args == NULL ? "" : cre->args); 1608 1609 if (canonicalize_host(str, ph, sizeof(ph)) == NULL) { 1610 relay_close_http(con, 400, "invalid host name", 0); 1611 return (PN_FAIL); 1612 } 1613 1614 bzero(hi, sizeof(hi)); 1615 for (dots = -1, i = strlen(ph) - 1; i > 0; i--) { 1616 if (ph[i] == '.' && ++dots) 1617 hi[dots - 1] = &ph[i + 1]; 1618 if (dots > (RELAY_MAXLOOKUPLEVELS - 2)) 1619 break; 1620 } 1621 if (dots == -1) 1622 dots = 0; 1623 hi[dots] = ph; 1624 1625 if ((pp = strdup(cre->path)) == NULL) { 1626 relay_close_http(con, 500, "failed to allocate path", 0); 1627 return (PN_FAIL); 1628 } 1629 for (i = (RELAY_MAXLOOKUPLEVELS - 1); i >= 0; i--) { 1630 if (hi[i] == NULL) 1631 continue; 1632 1633 /* 1. complete path with query */ 1634 if (cre->args != NULL) 1635 if ((ret = _relay_lookup_url(cre, hi[i], 1636 pp, cre->args, type)) != PN_PASS) 1637 goto done; 1638 1639 /* 2. complete path without query */ 1640 if ((ret = _relay_lookup_url(cre, hi[i], 1641 pp, NULL, type)) != PN_PASS) 1642 goto done; 1643 1644 /* 3. traverse path */ 1645 for (j = 0, p = strchr(pp, '/'); 1646 p != NULL; p = strchr(p, '/'), j++) { 1647 if (j > (RELAY_MAXLOOKUPLEVELS - 2) || ++p == '\0') 1648 break; 1649 c = &pp[p - pp]; 1650 ch = *c; 1651 *c = '\0'; 1652 if ((ret = _relay_lookup_url(cre, hi[i], 1653 pp, NULL, type)) != PN_PASS) 1654 goto done; 1655 *c = ch; 1656 } 1657 } 1658 1659 ret = PN_PASS; 1660 done: 1661 free(pp); 1662 return (ret); 1663 } 1664 1665 int 1666 relay_lookup_query(struct ctl_relay_event *cre) 1667 { 1668 struct rsession *con = cre->con; 1669 struct protonode *proot, *pnv, pkv; 1670 char *val, *ptr; 1671 int ret; 1672 1673 if (cre->path == NULL || cre->args == NULL || strlen(cre->args) < 2) 1674 return (PN_PASS); 1675 if ((val = strdup(cre->args)) == NULL) { 1676 relay_close_http(con, 500, "failed to allocate query", 0); 1677 return (PN_FAIL); 1678 } 1679 1680 ptr = val; 1681 while (ptr != NULL && strlen(ptr)) { 1682 pkv.key = ptr; 1683 pkv.type = NODE_TYPE_QUERY; 1684 if ((ptr = strchr(ptr, '&')) != NULL) 1685 *ptr++ = '\0'; 1686 if ((pkv.value = 1687 strchr(pkv.key, '=')) == NULL || 1688 strlen(pkv.value) < 1) 1689 continue; 1690 *pkv.value++ = '\0'; 1691 1692 if ((proot = RB_FIND(proto_tree, cre->tree, &pkv)) == NULL) 1693 continue; 1694 PROTONODE_FOREACH(pnv, proot, entry) { 1695 ret = relay_handle_http(cre, proot, 1696 pnv, &pkv, 0); 1697 if (ret == PN_FAIL) 1698 goto done; 1699 } 1700 } 1701 1702 ret = PN_PASS; 1703 done: 1704 free(val); 1705 return (ret); 1706 } 1707 1708 int 1709 relay_lookup_cookie(struct ctl_relay_event *cre, const char *str) 1710 { 1711 struct rsession *con = cre->con; 1712 struct protonode *proot, *pnv, pkv; 1713 char *val, *ptr; 1714 int ret; 1715 1716 if ((val = strdup(str)) == NULL) { 1717 relay_close_http(con, 500, "failed to allocate cookie", 0); 1718 return (PN_FAIL); 1719 } 1720 1721 for (ptr = val; ptr != NULL && strlen(ptr);) { 1722 if (*ptr == ' ') 1723 *ptr++ = '\0'; 1724 pkv.key = ptr; 1725 pkv.type = NODE_TYPE_COOKIE; 1726 if ((ptr = strchr(ptr, ';')) != NULL) 1727 *ptr++ = '\0'; 1728 /* 1729 * XXX We do not handle attributes 1730 * ($Path, $Domain, or $Port) 1731 */ 1732 if (*pkv.key == '$') 1733 continue; 1734 1735 if ((pkv.value = 1736 strchr(pkv.key, '=')) == NULL || 1737 strlen(pkv.value) < 1) 1738 continue; 1739 *pkv.value++ = '\0'; 1740 if (*pkv.value == '"') 1741 *pkv.value++ = '\0'; 1742 if (pkv.value[strlen(pkv.value) - 1] == '"') 1743 pkv.value[strlen(pkv.value) - 1] = '\0'; 1744 if ((proot = RB_FIND(proto_tree, cre->tree, &pkv)) == NULL) 1745 continue; 1746 PROTONODE_FOREACH(pnv, proot, entry) { 1747 ret = relay_handle_http(cre, proot, pnv, &pkv, 0); 1748 if (ret == PN_FAIL) 1749 goto done; 1750 } 1751 } 1752 1753 ret = PN_PASS; 1754 done: 1755 free(val); 1756 return (ret); 1757 } 1758 1759 void 1760 relay_close_http(struct rsession *con, u_int code, const char *msg, 1761 u_int16_t labelid) 1762 { 1763 struct relay *rlay = (struct relay *)con->se_relay; 1764 struct bufferevent *bev = con->se_in.bev; 1765 const char *httperr = print_httperror(code), *text = ""; 1766 char *httpmsg; 1767 time_t t; 1768 struct tm *lt; 1769 char tmbuf[32], hbuf[128]; 1770 const char *style, *label = NULL; 1771 1772 /* In some cases this function may be called from generic places */ 1773 if (rlay->rl_proto->type != RELAY_PROTO_HTTP || 1774 (rlay->rl_proto->flags & F_RETURN) == 0) { 1775 relay_close(con, msg); 1776 return; 1777 } 1778 1779 if (bev == NULL) 1780 goto done; 1781 1782 /* Some system information */ 1783 if (print_host(&rlay->rl_conf.ss, hbuf, sizeof(hbuf)) == NULL) 1784 goto done; 1785 1786 /* RFC 2616 "tolerates" asctime() */ 1787 time(&t); 1788 lt = localtime(&t); 1789 tmbuf[0] = '\0'; 1790 if (asctime_r(lt, tmbuf) != NULL) 1791 tmbuf[strlen(tmbuf) - 1] = '\0'; /* skip final '\n' */ 1792 1793 /* Do not send details of the Internal Server Error */ 1794 if (code != 500) 1795 text = msg; 1796 if (labelid != 0) 1797 label = pn_id2name(labelid); 1798 1799 /* A CSS stylesheet allows minimal customization by the user */ 1800 if ((style = rlay->rl_proto->style) == NULL) 1801 style = "body { background-color: #a00000; color: white; }"; 1802 1803 /* Generate simple HTTP+HTML error document */ 1804 if (asprintf(&httpmsg, 1805 "HTTP/1.x %03d %s\r\n" 1806 "Date: %s\r\n" 1807 "Server: %s\r\n" 1808 "Connection: close\r\n" 1809 "Content-Type: text/html\r\n" 1810 "\r\n" 1811 "<!DOCTYPE HTML PUBLIC " 1812 "\"-//W3C//DTD HTML 4.01 Transitional//EN\">\n" 1813 "<html>\n" 1814 "<head>\n" 1815 "<title>%03d %s</title>\n" 1816 "<style type=\"text/css\"><!--\n%s\n--></style>\n" 1817 "</head>\n" 1818 "<body>\n" 1819 "<h1>%s</h1>\n" 1820 "<div id='m'>%s</div>\n" 1821 "<div id='l'>%s</div>\n" 1822 "<hr><address>%s at %s port %d</address>\n" 1823 "</body>\n" 1824 "</html>\n", 1825 code, httperr, tmbuf, RELAYD_SERVERNAME, 1826 code, httperr, style, httperr, text, 1827 label == NULL ? "" : label, 1828 RELAYD_SERVERNAME, hbuf, ntohs(rlay->rl_conf.port)) == -1) 1829 goto done; 1830 1831 /* Dump the message without checking for success */ 1832 relay_dump(&con->se_in, httpmsg, strlen(httpmsg)); 1833 free(httpmsg); 1834 1835 done: 1836 if (asprintf(&httpmsg, "%s (%03d %s)", msg, code, httperr) == -1) 1837 relay_close(con, msg); 1838 else { 1839 relay_close(con, httpmsg); 1840 free(httpmsg); 1841 } 1842 } 1843 1844 int 1845 relay_splicelen(struct ctl_relay_event *cre) 1846 { 1847 struct rsession *con = cre->con; 1848 off_t len; 1849 socklen_t optlen; 1850 1851 optlen = sizeof(len); 1852 if (getsockopt(cre->s, SOL_SOCKET, SO_SPLICE, &len, &optlen) == -1) { 1853 relay_close(con, strerror(errno)); 1854 return (0); 1855 } 1856 if (len > cre->splicelen) { 1857 cre->splicelen = len; 1858 return (1); 1859 } 1860 return (0); 1861 } 1862 1863 void 1864 relay_error(struct bufferevent *bev, short error, void *arg) 1865 { 1866 struct ctl_relay_event *cre = (struct ctl_relay_event *)arg; 1867 struct rsession *con = cre->con; 1868 struct evbuffer *dst; 1869 struct timeval tv, tv_now; 1870 1871 if (error & EVBUFFER_TIMEOUT) { 1872 if (gettimeofday(&tv_now, NULL) == -1) { 1873 relay_close(con, strerror(errno)); 1874 return; 1875 } 1876 if (cre->splicelen >= 0 && relay_splicelen(cre)) 1877 con->se_tv_last = tv_now; 1878 if (cre->dst->splicelen >= 0 && relay_splicelen(cre->dst)) 1879 con->se_tv_last = tv_now; 1880 timersub(&tv_now, &con->se_tv_last, &tv); 1881 if (timercmp(&tv, &con->se_relay->rl_conf.timeout, >=)) 1882 relay_close(con, "buffer event timeout"); 1883 else 1884 bufferevent_enable(cre->bev, EV_READ); 1885 return; 1886 } 1887 if (error & (EVBUFFER_READ|EVBUFFER_WRITE|EVBUFFER_EOF)) { 1888 bufferevent_disable(bev, EV_READ|EV_WRITE); 1889 1890 con->se_done = 1; 1891 if (cre->dst->bev != NULL) { 1892 dst = EVBUFFER_OUTPUT(cre->dst->bev); 1893 if (EVBUFFER_LENGTH(dst)) 1894 return; 1895 } else 1896 return; 1897 1898 relay_close(con, "done"); 1899 return; 1900 } 1901 relay_close(con, "buffer event error"); 1902 } 1903 1904 void 1905 relay_accept(int fd, short sig, void *arg) 1906 { 1907 struct relay *rlay = (struct relay *)arg; 1908 struct protocol *proto = rlay->rl_proto; 1909 struct rsession *con = NULL; 1910 struct ctl_natlook *cnl = NULL; 1911 socklen_t slen; 1912 struct timeval tv; 1913 struct sockaddr_storage ss; 1914 int s = -1; 1915 1916 slen = sizeof(ss); 1917 if ((s = accept(fd, (struct sockaddr *)&ss, (socklen_t *)&slen)) == -1) 1918 return; 1919 1920 if (relay_sessions >= RELAY_MAX_SESSIONS || 1921 rlay->rl_conf.flags & F_DISABLE) 1922 goto err; 1923 1924 if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) 1925 goto err; 1926 1927 if ((con = calloc(1, sizeof(*con))) == NULL) 1928 goto err; 1929 1930 con->se_in.s = s; 1931 con->se_in.ssl = NULL; 1932 con->se_out.s = -1; 1933 con->se_out.ssl = NULL; 1934 con->se_in.dst = &con->se_out; 1935 con->se_out.dst = &con->se_in; 1936 con->se_in.con = con; 1937 con->se_out.con = con; 1938 con->se_in.splicelen = -1; 1939 con->se_out.splicelen = -1; 1940 con->se_relay = rlay; 1941 con->se_id = ++relay_conid; 1942 con->se_relayid = rlay->rl_conf.id; 1943 con->se_pid = getpid(); 1944 con->se_hashkey = rlay->rl_dstkey; 1945 con->se_in.tree = &proto->request_tree; 1946 con->se_out.tree = &proto->response_tree; 1947 con->se_in.dir = RELAY_DIR_REQUEST; 1948 con->se_out.dir = RELAY_DIR_RESPONSE; 1949 con->se_retry = rlay->rl_conf.dstretry; 1950 con->se_bnds = -1; 1951 if (gettimeofday(&con->se_tv_start, NULL) == -1) 1952 goto err; 1953 bcopy(&con->se_tv_start, &con->se_tv_last, sizeof(con->se_tv_last)); 1954 bcopy(&ss, &con->se_in.ss, sizeof(con->se_in.ss)); 1955 con->se_out.port = rlay->rl_conf.dstport; 1956 switch (ss.ss_family) { 1957 case AF_INET: 1958 con->se_in.port = ((struct sockaddr_in *)&ss)->sin_port; 1959 break; 1960 case AF_INET6: 1961 con->se_in.port = ((struct sockaddr_in6 *)&ss)->sin6_port; 1962 break; 1963 } 1964 1965 relay_sessions++; 1966 SPLAY_INSERT(session_tree, &rlay->rl_sessions, con); 1967 1968 /* Increment the per-relay session counter */ 1969 rlay->rl_stats[proc_id].last++; 1970 1971 /* Pre-allocate output buffer */ 1972 con->se_out.output = evbuffer_new(); 1973 if (con->se_out.output == NULL) { 1974 relay_close(con, "failed to allocate output buffer"); 1975 return; 1976 } 1977 1978 /* Pre-allocate log buffer */ 1979 con->se_log = evbuffer_new(); 1980 if (con->se_log == NULL) { 1981 relay_close(con, "failed to allocate log buffer"); 1982 return; 1983 } 1984 1985 if (rlay->rl_conf.flags & F_DIVERT) { 1986 slen = sizeof(con->se_out.ss); 1987 if (getsockname(s, (struct sockaddr *)&con->se_out.ss, 1988 &slen) == -1) { 1989 relay_close(con, "peer lookup failed"); 1990 return; 1991 } 1992 con->se_out.port = relay_socket_getport(&con->se_out.ss); 1993 1994 /* Detect loop and fall back to the alternate forward target */ 1995 if (bcmp(&rlay->rl_conf.ss, &con->se_out.ss, 1996 sizeof(con->se_out.ss)) == 0 && 1997 con->se_out.port == rlay->rl_conf.port) 1998 con->se_out.ss.ss_family = AF_UNSPEC; 1999 } else if (rlay->rl_conf.flags & F_NATLOOK) { 2000 if ((cnl = (struct ctl_natlook *) 2001 calloc(1, sizeof(struct ctl_natlook))) == NULL) { 2002 relay_close(con, "failed to allocate nat lookup"); 2003 return; 2004 } 2005 2006 con->se_cnl = cnl; 2007 bzero(cnl, sizeof(*cnl)); 2008 cnl->in = -1; 2009 cnl->id = con->se_id; 2010 cnl->proc = proc_id; 2011 cnl->proto = IPPROTO_TCP; 2012 2013 bcopy(&con->se_in.ss, &cnl->src, sizeof(cnl->src)); 2014 slen = sizeof(cnl->dst); 2015 if (getsockname(s, 2016 (struct sockaddr *)&cnl->dst, &slen) == -1) { 2017 relay_close(con, "failed to get local address"); 2018 return; 2019 } 2020 2021 proc_compose_imsg(env->sc_ps, PROC_PFE, -1, IMSG_NATLOOK, -1, 2022 cnl, sizeof(*cnl)); 2023 2024 /* Schedule timeout */ 2025 evtimer_set(&con->se_ev, relay_natlook, con); 2026 bcopy(&rlay->rl_conf.timeout, &tv, sizeof(tv)); 2027 evtimer_add(&con->se_ev, &tv); 2028 return; 2029 } 2030 2031 relay_session(con); 2032 return; 2033 err: 2034 if (s != -1) { 2035 close(s); 2036 if (con != NULL) 2037 free(con); 2038 } 2039 } 2040 2041 u_int32_t 2042 relay_hash_addr(struct sockaddr_storage *ss, u_int32_t p) 2043 { 2044 struct sockaddr_in *sin4; 2045 struct sockaddr_in6 *sin6; 2046 2047 if (ss->ss_family == AF_INET) { 2048 sin4 = (struct sockaddr_in *)ss; 2049 p = hash32_buf(&sin4->sin_addr, 2050 sizeof(struct in_addr), p); 2051 } else { 2052 sin6 = (struct sockaddr_in6 *)ss; 2053 p = hash32_buf(&sin6->sin6_addr, 2054 sizeof(struct in6_addr), p); 2055 } 2056 2057 return (p); 2058 } 2059 2060 int 2061 relay_from_table(struct rsession *con) 2062 { 2063 struct relay *rlay = (struct relay *)con->se_relay; 2064 struct host *host; 2065 struct table *table = rlay->rl_dsttable; 2066 u_int32_t p = con->se_hashkey; 2067 int idx = 0; 2068 2069 if (table->conf.check && !table->up && !rlay->rl_backuptable->up) { 2070 log_debug("%s: no active hosts", __func__); 2071 return (-1); 2072 } else if (!table->up && rlay->rl_backuptable->up) { 2073 table = rlay->rl_backuptable; 2074 } 2075 2076 switch (rlay->rl_conf.dstmode) { 2077 case RELAY_DSTMODE_ROUNDROBIN: 2078 if ((int)rlay->rl_dstkey >= rlay->rl_dstnhosts) 2079 rlay->rl_dstkey = 0; 2080 idx = (int)rlay->rl_dstkey; 2081 break; 2082 case RELAY_DSTMODE_LOADBALANCE: 2083 p = relay_hash_addr(&con->se_in.ss, p); 2084 /* FALLTHROUGH */ 2085 case RELAY_DSTMODE_HASH: 2086 p = relay_hash_addr(&rlay->rl_conf.ss, p); 2087 p = hash32_buf(&rlay->rl_conf.port, 2088 sizeof(rlay->rl_conf.port), p); 2089 if ((idx = p % rlay->rl_dstnhosts) >= RELAY_MAXHOSTS) 2090 return (-1); 2091 } 2092 host = rlay->rl_dsthost[idx]; 2093 DPRINTF("%s: host %s, p 0x%08x, idx %d", __func__, 2094 host->conf.name, p, idx); 2095 while (host != NULL) { 2096 DPRINTF("%s: host %s", __func__, host->conf.name); 2097 if (!table->conf.check || host->up == HOST_UP) 2098 goto found; 2099 host = TAILQ_NEXT(host, entry); 2100 } 2101 TAILQ_FOREACH(host, &table->hosts, entry) { 2102 DPRINTF("%s: next host %s", __func__, host->conf.name); 2103 if (!table->conf.check || host->up == HOST_UP) 2104 goto found; 2105 } 2106 2107 /* Should not happen */ 2108 fatalx("relay_from_table: no active hosts, desynchronized"); 2109 2110 found: 2111 if (rlay->rl_conf.dstmode == RELAY_DSTMODE_ROUNDROBIN) 2112 rlay->rl_dstkey = host->idx + 1; 2113 con->se_retry = host->conf.retry; 2114 con->se_out.port = table->conf.port; 2115 bcopy(&host->conf.ss, &con->se_out.ss, sizeof(con->se_out.ss)); 2116 2117 return (0); 2118 } 2119 2120 void 2121 relay_natlook(int fd, short event, void *arg) 2122 { 2123 struct rsession *con = (struct rsession *)arg; 2124 struct relay *rlay = (struct relay *)con->se_relay; 2125 struct ctl_natlook *cnl = con->se_cnl; 2126 2127 if (cnl == NULL) 2128 fatalx("invalid NAT lookup"); 2129 2130 if (con->se_out.ss.ss_family == AF_UNSPEC && cnl->in == -1 && 2131 rlay->rl_conf.dstss.ss_family == AF_UNSPEC && 2132 rlay->rl_dsttable == NULL) { 2133 relay_close(con, "session NAT lookup failed"); 2134 return; 2135 } 2136 if (cnl->in != -1) { 2137 bcopy(&cnl->rdst, &con->se_out.ss, sizeof(con->se_out.ss)); 2138 con->se_out.port = cnl->rdport; 2139 } 2140 free(con->se_cnl); 2141 con->se_cnl = NULL; 2142 2143 relay_session(con); 2144 } 2145 2146 void 2147 relay_session(struct rsession *con) 2148 { 2149 struct relay *rlay = (struct relay *)con->se_relay; 2150 struct ctl_relay_event *in = &con->se_in, *out = &con->se_out; 2151 2152 if (bcmp(&rlay->rl_conf.ss, &out->ss, sizeof(out->ss)) == 0 && 2153 out->port == rlay->rl_conf.port) { 2154 log_debug("%s: session %d: looping", __func__, con->se_id); 2155 relay_close(con, "session aborted"); 2156 return; 2157 } 2158 2159 if (rlay->rl_conf.flags & F_UDP) { 2160 /* 2161 * Call the UDP protocol-specific handler 2162 */ 2163 if (rlay->rl_proto->request == NULL) 2164 fatalx("invalide UDP session"); 2165 if ((*rlay->rl_proto->request)(con) == -1) 2166 relay_close(con, "session failed"); 2167 return; 2168 } 2169 2170 if ((rlay->rl_conf.flags & F_SSL) && (in->ssl == NULL)) { 2171 relay_ssl_transaction(con, in); 2172 return; 2173 } 2174 2175 if (!rlay->rl_proto->lateconnect) { 2176 if (rlay->rl_conf.fwdmode == FWD_TRANS) 2177 relay_bindanyreq(con, 0, IPPROTO_TCP); 2178 else if (relay_connect(con) == -1) { 2179 relay_close(con, "session failed"); 2180 return; 2181 } 2182 } 2183 2184 relay_input(con); 2185 } 2186 2187 void 2188 relay_bindanyreq(struct rsession *con, in_port_t port, int proto) 2189 { 2190 struct relay *rlay = (struct relay *)con->se_relay; 2191 struct ctl_bindany bnd; 2192 struct timeval tv; 2193 2194 bzero(&bnd, sizeof(bnd)); 2195 bnd.bnd_id = con->se_id; 2196 bnd.bnd_proc = proc_id; 2197 bnd.bnd_port = port; 2198 bnd.bnd_proto = proto; 2199 bcopy(&con->se_in.ss, &bnd.bnd_ss, sizeof(bnd.bnd_ss)); 2200 proc_compose_imsg(env->sc_ps, PROC_PARENT, -1, IMSG_BINDANY, 2201 -1, &bnd, sizeof(bnd)); 2202 2203 /* Schedule timeout */ 2204 evtimer_set(&con->se_ev, relay_bindany, con); 2205 bcopy(&rlay->rl_conf.timeout, &tv, sizeof(tv)); 2206 evtimer_add(&con->se_ev, &tv); 2207 } 2208 2209 void 2210 relay_bindany(int fd, short event, void *arg) 2211 { 2212 struct rsession *con = (struct rsession *)arg; 2213 2214 if (con->se_bnds == -1) { 2215 relay_close(con, "bindany failed, invalid socket"); 2216 return; 2217 } 2218 2219 if (relay_connect(con) == -1) 2220 relay_close(con, "session failed"); 2221 } 2222 2223 int 2224 relay_connect(struct rsession *con) 2225 { 2226 struct relay *rlay = (struct relay *)con->se_relay; 2227 int bnds = -1, ret; 2228 2229 if (gettimeofday(&con->se_tv_start, NULL) == -1) 2230 return (-1); 2231 2232 if (rlay->rl_dsttable != NULL) { 2233 if (relay_from_table(con) != 0) 2234 return (-1); 2235 } else if (con->se_out.ss.ss_family == AF_UNSPEC) { 2236 bcopy(&rlay->rl_conf.dstss, &con->se_out.ss, 2237 sizeof(con->se_out.ss)); 2238 con->se_out.port = rlay->rl_conf.dstport; 2239 } 2240 2241 if (rlay->rl_conf.fwdmode == FWD_TRANS) { 2242 if (con->se_bnds == -1) { 2243 log_debug("%s: could not bind any sock", __func__); 2244 return (-1); 2245 } 2246 bnds = con->se_bnds; 2247 } 2248 2249 /* Do the IPv4-to-IPv6 or IPv6-to-IPv4 translation if requested */ 2250 if (rlay->rl_conf.dstaf.ss_family != AF_UNSPEC) { 2251 if (con->se_out.ss.ss_family == AF_INET && 2252 rlay->rl_conf.dstaf.ss_family == AF_INET6) 2253 ret = map4to6(&con->se_out.ss, &rlay->rl_conf.dstaf); 2254 else if (con->se_out.ss.ss_family == AF_INET6 && 2255 rlay->rl_conf.dstaf.ss_family == AF_INET) 2256 ret = map6to4(&con->se_out.ss); 2257 else 2258 ret = 0; 2259 if (ret != 0) { 2260 log_debug("%s: mapped to invalid address", __func__); 2261 return (-1); 2262 } 2263 } 2264 2265 retry: 2266 if ((con->se_out.s = relay_socket_connect(&con->se_out.ss, 2267 con->se_out.port, rlay->rl_proto, bnds)) == -1) { 2268 if (con->se_retry) { 2269 con->se_retry--; 2270 log_debug("%s: session %d: " 2271 "forward failed: %s, %s", __func__, 2272 con->se_id, strerror(errno), 2273 con->se_retry ? "next retry" : "last retry"); 2274 goto retry; 2275 } 2276 log_debug("%s: session %d: forward failed: %s", __func__, 2277 con->se_id, strerror(errno)); 2278 return (-1); 2279 } 2280 2281 if (errno == EINPROGRESS) 2282 event_again(&con->se_ev, con->se_out.s, EV_WRITE|EV_TIMEOUT, 2283 relay_connected, &con->se_tv_start, &rlay->rl_conf.timeout, 2284 con); 2285 else 2286 relay_connected(con->se_out.s, EV_WRITE, con); 2287 2288 return (0); 2289 } 2290 2291 void 2292 relay_close(struct rsession *con, const char *msg) 2293 { 2294 struct relay *rlay = (struct relay *)con->se_relay; 2295 char ibuf[128], obuf[128], *ptr = NULL; 2296 2297 SPLAY_REMOVE(session_tree, &rlay->rl_sessions, con); 2298 2299 event_del(&con->se_ev); 2300 if (con->se_in.bev != NULL) 2301 bufferevent_disable(con->se_in.bev, EV_READ|EV_WRITE); 2302 if (con->se_out.bev != NULL) 2303 bufferevent_disable(con->se_out.bev, EV_READ|EV_WRITE); 2304 2305 if ((env->sc_opts & RELAYD_OPT_LOGUPDATE) && msg != NULL) { 2306 bzero(&ibuf, sizeof(ibuf)); 2307 bzero(&obuf, sizeof(obuf)); 2308 (void)print_host(&con->se_in.ss, ibuf, sizeof(ibuf)); 2309 (void)print_host(&con->se_out.ss, obuf, sizeof(obuf)); 2310 if (EVBUFFER_LENGTH(con->se_log) && 2311 evbuffer_add_printf(con->se_log, "\r\n") != -1) 2312 ptr = evbuffer_readline(con->se_log); 2313 log_info("relay %s, " 2314 "session %d (%d active), %d, %s -> %s:%d, " 2315 "%s%s%s", rlay->rl_conf.name, con->se_id, relay_sessions, 2316 con->se_mark, ibuf, obuf, ntohs(con->se_out.port), msg, 2317 ptr == NULL ? "" : ",", ptr == NULL ? "" : ptr); 2318 if (ptr != NULL) 2319 free(ptr); 2320 } 2321 2322 if (con->se_priv != NULL) 2323 free(con->se_priv); 2324 if (con->se_in.bev != NULL) 2325 bufferevent_free(con->se_in.bev); 2326 else if (con->se_in.output != NULL) 2327 evbuffer_free(con->se_in.output); 2328 if (con->se_in.ssl != NULL) { 2329 /* XXX handle non-blocking shutdown */ 2330 if (SSL_shutdown(con->se_in.ssl) == 0) 2331 SSL_shutdown(con->se_in.ssl); 2332 SSL_free(con->se_in.ssl); 2333 } 2334 if (con->se_in.s != -1) 2335 close(con->se_in.s); 2336 if (con->se_in.path != NULL) 2337 free(con->se_in.path); 2338 if (con->se_in.buf != NULL) 2339 free(con->se_in.buf); 2340 if (con->se_in.nodes != NULL) 2341 free(con->se_in.nodes); 2342 2343 if (con->se_out.bev != NULL) 2344 bufferevent_free(con->se_out.bev); 2345 else if (con->se_out.output != NULL) 2346 evbuffer_free(con->se_out.output); 2347 if (con->se_out.ssl != NULL) { 2348 /* XXX handle non-blocking shutdown */ 2349 if (SSL_shutdown(con->se_out.ssl) == 0) 2350 SSL_shutdown(con->se_out.ssl); 2351 SSL_free(con->se_out.ssl); 2352 } 2353 if (con->se_out.s != -1) 2354 close(con->se_out.s); 2355 if (con->se_out.path != NULL) 2356 free(con->se_out.path); 2357 if (con->se_out.buf != NULL) 2358 free(con->se_out.buf); 2359 if (con->se_out.nodes != NULL) 2360 free(con->se_out.nodes); 2361 2362 if (con->se_log != NULL) 2363 evbuffer_free(con->se_log); 2364 2365 if (con->se_cnl != NULL) { 2366 #if 0 2367 proc_compose_imsg(env->sc_ps, PROC_PFE, -1, IMSG_KILLSTATES, -1, 2368 cnl, sizeof(*cnl)); 2369 #endif 2370 free(con->se_cnl); 2371 } 2372 2373 free(con); 2374 relay_sessions--; 2375 } 2376 2377 int 2378 relay_dispatch_pfe(int fd, struct privsep_proc *p, struct imsg *imsg) 2379 { 2380 struct relay *rlay; 2381 struct rsession *con, se; 2382 struct ctl_natlook cnl; 2383 struct timeval tv; 2384 struct host *host; 2385 struct table *table; 2386 struct ctl_status st; 2387 objid_t id; 2388 int cid; 2389 2390 switch (imsg->hdr.type) { 2391 case IMSG_HOST_DISABLE: 2392 memcpy(&id, imsg->data, sizeof(id)); 2393 if ((host = host_find(env, id)) == NULL) 2394 fatalx("relay_dispatch_pfe: desynchronized"); 2395 if ((table = table_find(env, host->conf.tableid)) == 2396 NULL) 2397 fatalx("relay_dispatch_pfe: invalid table id"); 2398 if (host->up == HOST_UP) 2399 table->up--; 2400 host->flags |= F_DISABLE; 2401 host->up = HOST_UNKNOWN; 2402 break; 2403 case IMSG_HOST_ENABLE: 2404 memcpy(&id, imsg->data, sizeof(id)); 2405 if ((host = host_find(env, id)) == NULL) 2406 fatalx("relay_dispatch_pfe: desynchronized"); 2407 host->flags &= ~(F_DISABLE); 2408 host->up = HOST_UNKNOWN; 2409 break; 2410 case IMSG_TABLE_DISABLE: 2411 memcpy(&id, imsg->data, sizeof(id)); 2412 if ((table = table_find(env, id)) == NULL) 2413 fatalx("relay_dispatch_pfe: desynchronized"); 2414 table->conf.flags |= F_DISABLE; 2415 table->up = 0; 2416 TAILQ_FOREACH(host, &table->hosts, entry) 2417 host->up = HOST_UNKNOWN; 2418 break; 2419 case IMSG_TABLE_ENABLE: 2420 memcpy(&id, imsg->data, sizeof(id)); 2421 if ((table = table_find(env, id)) == NULL) 2422 fatalx("relay_dispatch_pfe: desynchronized"); 2423 table->conf.flags &= ~(F_DISABLE); 2424 table->up = 0; 2425 TAILQ_FOREACH(host, &table->hosts, entry) 2426 host->up = HOST_UNKNOWN; 2427 break; 2428 case IMSG_HOST_STATUS: 2429 IMSG_SIZE_CHECK(imsg, &st); 2430 memcpy(&st, imsg->data, sizeof(st)); 2431 if ((host = host_find(env, st.id)) == NULL) 2432 fatalx("relay_dispatch_pfe: invalid host id"); 2433 if (host->flags & F_DISABLE) 2434 break; 2435 if (host->up == st.up) { 2436 log_debug("%s: host %d => %d", __func__, 2437 host->conf.id, host->up); 2438 fatalx("relay_dispatch_pfe: desynchronized"); 2439 } 2440 2441 if ((table = table_find(env, host->conf.tableid)) 2442 == NULL) 2443 fatalx("relay_dispatch_pfe: invalid table id"); 2444 2445 DPRINTF("%s: [%d] state %d for " 2446 "host %u %s", __func__, proc_id, st.up, 2447 host->conf.id, host->conf.name); 2448 2449 if ((st.up == HOST_UNKNOWN && host->up == HOST_DOWN) || 2450 (st.up == HOST_DOWN && host->up == HOST_UNKNOWN)) { 2451 host->up = st.up; 2452 break; 2453 } 2454 if (st.up == HOST_UP) 2455 table->up++; 2456 else 2457 table->up--; 2458 host->up = st.up; 2459 break; 2460 case IMSG_NATLOOK: 2461 bcopy(imsg->data, &cnl, sizeof(cnl)); 2462 if ((con = session_find(env, cnl.id)) == NULL || 2463 con->se_cnl == NULL) { 2464 log_debug("%s: session %d: expired", 2465 __func__, cnl.id); 2466 break; 2467 } 2468 bcopy(&cnl, con->se_cnl, sizeof(*con->se_cnl)); 2469 evtimer_del(&con->se_ev); 2470 evtimer_set(&con->se_ev, relay_natlook, con); 2471 bzero(&tv, sizeof(tv)); 2472 evtimer_add(&con->se_ev, &tv); 2473 break; 2474 case IMSG_CTL_SESSION: 2475 IMSG_SIZE_CHECK(imsg, &cid); 2476 memcpy(&cid, imsg->data, sizeof(cid)); 2477 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) { 2478 SPLAY_FOREACH(con, session_tree, 2479 &rlay->rl_sessions) { 2480 memcpy(&se, con, sizeof(se)); 2481 se.se_cid = cid; 2482 proc_compose_imsg(env->sc_ps, p->p_id, -1, 2483 IMSG_CTL_SESSION, 2484 -1, &se, sizeof(se)); 2485 } 2486 } 2487 proc_compose_imsg(env->sc_ps, p->p_id, -1, IMSG_CTL_END, 2488 -1, &cid, sizeof(cid)); 2489 break; 2490 default: 2491 return (-1); 2492 } 2493 2494 return (0); 2495 } 2496 2497 int 2498 relay_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg) 2499 { 2500 struct rsession *con; 2501 struct timeval tv; 2502 objid_t id; 2503 2504 switch (imsg->hdr.type) { 2505 case IMSG_BINDANY: 2506 bcopy(imsg->data, &id, sizeof(id)); 2507 if ((con = session_find(env, id)) == NULL) { 2508 log_debug("%s: session %d: expired", 2509 __func__, id); 2510 break; 2511 } 2512 2513 /* Will validate the result later */ 2514 con->se_bnds = imsg->fd; 2515 2516 evtimer_del(&con->se_ev); 2517 evtimer_set(&con->se_ev, relay_bindany, con); 2518 bzero(&tv, sizeof(tv)); 2519 evtimer_add(&con->se_ev, &tv); 2520 break; 2521 case IMSG_CFG_TABLE: 2522 config_gettable(env, imsg); 2523 break; 2524 case IMSG_CFG_HOST: 2525 config_gethost(env, imsg); 2526 break; 2527 case IMSG_CFG_PROTO: 2528 config_getproto(env, imsg); 2529 break; 2530 case IMSG_CFG_PROTONODE: 2531 return (config_getprotonode(env, imsg)); 2532 case IMSG_CFG_RELAY: 2533 config_getrelay(env, imsg); 2534 break; 2535 case IMSG_CFG_DONE: 2536 config_getcfg(env, imsg); 2537 relay_launch(); 2538 break; 2539 case IMSG_CTL_RESET: 2540 config_getreset(env, imsg); 2541 break; 2542 default: 2543 return (-1); 2544 } 2545 2546 return (0); 2547 } 2548 2549 SSL_CTX * 2550 relay_ssl_ctx_create(struct relay *rlay) 2551 { 2552 struct protocol *proto = rlay->rl_proto; 2553 SSL_CTX *ctx; 2554 2555 ctx = SSL_CTX_new(SSLv23_method()); 2556 if (ctx == NULL) 2557 goto err; 2558 2559 /* Modify session timeout and cache size*/ 2560 SSL_CTX_set_timeout(ctx, rlay->rl_conf.timeout.tv_sec); 2561 if (proto->cache < -1) { 2562 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); 2563 } else if (proto->cache >= -1) { 2564 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER); 2565 if (proto->cache >= 0) 2566 SSL_CTX_sess_set_cache_size(ctx, proto->cache); 2567 } 2568 2569 /* Enable all workarounds and set SSL options */ 2570 SSL_CTX_set_options(ctx, SSL_OP_ALL); 2571 SSL_CTX_set_options(ctx, 2572 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); 2573 2574 /* Set the allowed SSL protocols */ 2575 if ((proto->sslflags & SSLFLAG_SSLV2) == 0) 2576 SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2); 2577 if ((proto->sslflags & SSLFLAG_SSLV3) == 0) 2578 SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3); 2579 if ((proto->sslflags & SSLFLAG_TLSV1) == 0) 2580 SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1); 2581 2582 if (!SSL_CTX_set_cipher_list(ctx, proto->sslciphers)) 2583 goto err; 2584 2585 /* Verify the server certificate if we have a CA chain */ 2586 if ((rlay->rl_conf.flags & F_SSLCLIENT) && 2587 (rlay->rl_ssl_ca != NULL)) { 2588 if (!ssl_ctx_load_verify_memory(ctx, 2589 rlay->rl_ssl_ca, rlay->rl_conf.ssl_ca_len)) 2590 goto err; 2591 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 2592 } 2593 2594 if ((rlay->rl_conf.flags & F_SSL) == 0) 2595 return (ctx); 2596 2597 log_debug("%s: loading certificate", __func__); 2598 if (!ssl_ctx_use_certificate_chain(ctx, 2599 rlay->rl_ssl_cert, rlay->rl_conf.ssl_cert_len)) 2600 goto err; 2601 2602 log_debug("%s: loading private key", __func__); 2603 if (!ssl_ctx_use_private_key(ctx, rlay->rl_ssl_key, 2604 rlay->rl_conf.ssl_key_len)) 2605 goto err; 2606 if (!SSL_CTX_check_private_key(ctx)) 2607 goto err; 2608 2609 /* Set session context to the local relay name */ 2610 if (!SSL_CTX_set_session_id_context(ctx, rlay->rl_conf.name, 2611 strlen(rlay->rl_conf.name))) 2612 goto err; 2613 2614 return (ctx); 2615 2616 err: 2617 if (ctx != NULL) 2618 SSL_CTX_free(ctx); 2619 ssl_error(rlay->rl_conf.name, "relay_ssl_ctx_create"); 2620 return (NULL); 2621 } 2622 2623 void 2624 relay_ssl_transaction(struct rsession *con, struct ctl_relay_event *cre) 2625 { 2626 struct relay *rlay = (struct relay *)con->se_relay; 2627 SSL *ssl; 2628 const SSL_METHOD *method; 2629 void (*cb)(int, short, void *); 2630 u_int flag; 2631 2632 ssl = SSL_new(rlay->rl_ssl_ctx); 2633 if (ssl == NULL) 2634 goto err; 2635 2636 if (cre->dir == RELAY_DIR_REQUEST) { 2637 cb = relay_ssl_accept; 2638 method = SSLv23_server_method(); 2639 flag = EV_READ; 2640 } else { 2641 cb = relay_ssl_connect; 2642 method = SSLv23_client_method(); 2643 flag = EV_WRITE; 2644 } 2645 2646 if (!SSL_set_ssl_method(ssl, method)) 2647 goto err; 2648 if (!SSL_set_fd(ssl, cre->s)) 2649 goto err; 2650 2651 if (cre->dir == RELAY_DIR_REQUEST) 2652 SSL_set_accept_state(ssl); 2653 else 2654 SSL_set_connect_state(ssl); 2655 2656 cre->ssl = ssl; 2657 2658 DPRINTF("%s: session %d: scheduling on %s", __func__, con->se_id, 2659 (flag == EV_READ) ? "EV_READ" : "EV_WRITE"); 2660 event_again(&con->se_ev, cre->s, EV_TIMEOUT|flag, cb, 2661 &con->se_tv_start, &rlay->rl_conf.timeout, con); 2662 return; 2663 2664 err: 2665 if (ssl != NULL) 2666 SSL_free(ssl); 2667 ssl_error(rlay->rl_conf.name, "relay_ssl_transaction"); 2668 relay_close(con, "session ssl failed"); 2669 } 2670 2671 void 2672 relay_ssl_accept(int fd, short event, void *arg) 2673 { 2674 struct rsession *con = (struct rsession *)arg; 2675 struct relay *rlay = (struct relay *)con->se_relay; 2676 int ret; 2677 int ssl_err; 2678 int retry_flag; 2679 2680 if (event == EV_TIMEOUT) { 2681 relay_close(con, "SSL accept timeout"); 2682 return; 2683 } 2684 2685 retry_flag = ssl_err = 0; 2686 2687 ret = SSL_accept(con->se_in.ssl); 2688 if (ret <= 0) { 2689 ssl_err = SSL_get_error(con->se_in.ssl, ret); 2690 2691 switch (ssl_err) { 2692 case SSL_ERROR_WANT_READ: 2693 retry_flag = EV_READ; 2694 goto retry; 2695 case SSL_ERROR_WANT_WRITE: 2696 retry_flag = EV_WRITE; 2697 goto retry; 2698 case SSL_ERROR_ZERO_RETURN: 2699 case SSL_ERROR_SYSCALL: 2700 if (ret == 0) { 2701 relay_close(con, "closed"); 2702 return; 2703 } 2704 /* FALLTHROUGH */ 2705 default: 2706 ssl_error(rlay->rl_conf.name, "relay_ssl_accept"); 2707 relay_close(con, "SSL accept error"); 2708 return; 2709 } 2710 } 2711 2712 2713 #ifdef DEBUG 2714 log_info( 2715 #else 2716 log_debug( 2717 #endif 2718 "relay %s, session %d established (%d active)", 2719 rlay->rl_conf.name, con->se_id, relay_sessions); 2720 2721 relay_session(con); 2722 return; 2723 2724 retry: 2725 DPRINTF("%s: session %d: scheduling on %s", __func__, con->se_id, 2726 (retry_flag == EV_READ) ? "EV_READ" : "EV_WRITE"); 2727 event_again(&con->se_ev, fd, EV_TIMEOUT|retry_flag, relay_ssl_accept, 2728 &con->se_tv_start, &rlay->rl_conf.timeout, con); 2729 } 2730 2731 void 2732 relay_ssl_connect(int fd, short event, void *arg) 2733 { 2734 struct rsession *con = (struct rsession *)arg; 2735 struct relay *rlay = (struct relay *)con->se_relay; 2736 int ret; 2737 int ssl_err; 2738 int retry_flag; 2739 2740 if (event == EV_TIMEOUT) { 2741 relay_close(con, "SSL connect timeout"); 2742 return; 2743 } 2744 2745 retry_flag = ssl_err = 0; 2746 2747 ret = SSL_connect(con->se_out.ssl); 2748 if (ret <= 0) { 2749 ssl_err = SSL_get_error(con->se_out.ssl, ret); 2750 2751 switch (ssl_err) { 2752 case SSL_ERROR_WANT_READ: 2753 retry_flag = EV_READ; 2754 goto retry; 2755 case SSL_ERROR_WANT_WRITE: 2756 retry_flag = EV_WRITE; 2757 goto retry; 2758 case SSL_ERROR_ZERO_RETURN: 2759 case SSL_ERROR_SYSCALL: 2760 if (ret == 0) { 2761 relay_close(con, "closed"); 2762 return; 2763 } 2764 /* FALLTHROUGH */ 2765 default: 2766 ssl_error(rlay->rl_conf.name, "relay_ssl_connect"); 2767 relay_close(con, "SSL connect error"); 2768 return; 2769 } 2770 } 2771 2772 #ifdef DEBUG 2773 log_info( 2774 #else 2775 log_debug( 2776 #endif 2777 "relay %s, session %d connected (%d active)", 2778 rlay->rl_conf.name, con->se_id, relay_sessions); 2779 2780 relay_connected(fd, EV_WRITE, con); 2781 return; 2782 2783 retry: 2784 DPRINTF("%s: session %d: scheduling on %s", __func__, con->se_id, 2785 (retry_flag == EV_READ) ? "EV_READ" : "EV_WRITE"); 2786 event_again(&con->se_ev, fd, EV_TIMEOUT|retry_flag, relay_ssl_connect, 2787 &con->se_tv_start, &rlay->rl_conf.timeout, con); 2788 } 2789 2790 void 2791 relay_ssl_connected(struct ctl_relay_event *cre) 2792 { 2793 /* 2794 * Hack libevent - we overwrite the internal bufferevent I/O 2795 * functions to handle the SSL abstraction. 2796 */ 2797 event_set(&cre->bev->ev_read, cre->s, EV_READ, 2798 relay_ssl_readcb, cre->bev); 2799 event_set(&cre->bev->ev_write, cre->s, EV_WRITE, 2800 relay_ssl_writecb, cre->bev); 2801 } 2802 2803 void 2804 relay_ssl_readcb(int fd, short event, void *arg) 2805 { 2806 struct bufferevent *bufev = arg; 2807 struct ctl_relay_event *cre = (struct ctl_relay_event *)bufev->cbarg; 2808 struct rsession *con = cre->con; 2809 struct relay *rlay = (struct relay *)con->se_relay; 2810 int ret = 0, ssl_err = 0; 2811 short what = EVBUFFER_READ; 2812 size_t len; 2813 char rbuf[IBUF_READ_SIZE]; 2814 int howmuch = IBUF_READ_SIZE; 2815 2816 if (event == EV_TIMEOUT) { 2817 what |= EVBUFFER_TIMEOUT; 2818 goto err; 2819 } 2820 2821 if (bufev->wm_read.high != 0) 2822 howmuch = MIN(sizeof(rbuf), bufev->wm_read.high); 2823 2824 ret = SSL_read(cre->ssl, rbuf, howmuch); 2825 if (ret <= 0) { 2826 ssl_err = SSL_get_error(cre->ssl, ret); 2827 2828 switch (ssl_err) { 2829 case SSL_ERROR_WANT_READ: 2830 DPRINTF("%s: session %d: want read", 2831 __func__, con->se_id); 2832 goto retry; 2833 case SSL_ERROR_WANT_WRITE: 2834 DPRINTF("%s: session %d: want write", 2835 __func__, con->se_id); 2836 goto retry; 2837 default: 2838 if (ret == 0) 2839 what |= EVBUFFER_EOF; 2840 else { 2841 ssl_error(rlay->rl_conf.name, 2842 "relay_ssl_readcb"); 2843 what |= EVBUFFER_ERROR; 2844 } 2845 goto err; 2846 } 2847 } 2848 2849 if (evbuffer_add(bufev->input, rbuf, ret) == -1) { 2850 what |= EVBUFFER_ERROR; 2851 goto err; 2852 } 2853 2854 relay_bufferevent_add(&bufev->ev_read, bufev->timeout_read); 2855 2856 len = EVBUFFER_LENGTH(bufev->input); 2857 if (bufev->wm_read.low != 0 && len < bufev->wm_read.low) 2858 return; 2859 if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) { 2860 struct evbuffer *buf = bufev->input; 2861 event_del(&bufev->ev_read); 2862 evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); 2863 return; 2864 } 2865 2866 if (bufev->readcb != NULL) 2867 (*bufev->readcb)(bufev, bufev->cbarg); 2868 return; 2869 2870 retry: 2871 relay_bufferevent_add(&bufev->ev_read, bufev->timeout_read); 2872 return; 2873 2874 err: 2875 (*bufev->errorcb)(bufev, what, bufev->cbarg); 2876 } 2877 2878 void 2879 relay_ssl_writecb(int fd, short event, void *arg) 2880 { 2881 struct bufferevent *bufev = arg; 2882 struct ctl_relay_event *cre = (struct ctl_relay_event *)bufev->cbarg; 2883 struct rsession *con = cre->con; 2884 struct relay *rlay = (struct relay *)con->se_relay; 2885 int ret = 0, ssl_err; 2886 short what = EVBUFFER_WRITE; 2887 2888 if (event == EV_TIMEOUT) { 2889 what |= EVBUFFER_TIMEOUT; 2890 goto err; 2891 } 2892 2893 if (EVBUFFER_LENGTH(bufev->output)) { 2894 if (cre->buf == NULL) { 2895 cre->buflen = EVBUFFER_LENGTH(bufev->output); 2896 if ((cre->buf = malloc(cre->buflen)) == NULL) { 2897 what |= EVBUFFER_ERROR; 2898 goto err; 2899 } 2900 bcopy(EVBUFFER_DATA(bufev->output), 2901 cre->buf, cre->buflen); 2902 } 2903 2904 ret = SSL_write(cre->ssl, cre->buf, cre->buflen); 2905 if (ret <= 0) { 2906 ssl_err = SSL_get_error(cre->ssl, ret); 2907 2908 switch (ssl_err) { 2909 case SSL_ERROR_WANT_READ: 2910 DPRINTF("%s: session %d: want read", 2911 __func__, con->se_id); 2912 goto retry; 2913 case SSL_ERROR_WANT_WRITE: 2914 DPRINTF("%s: session %d: want write", 2915 __func__, con->se_id); 2916 goto retry; 2917 default: 2918 if (ret == 0) 2919 what |= EVBUFFER_EOF; 2920 else { 2921 ssl_error(rlay->rl_conf.name, 2922 "relay_ssl_writecb"); 2923 what |= EVBUFFER_ERROR; 2924 } 2925 goto err; 2926 } 2927 } 2928 evbuffer_drain(bufev->output, ret); 2929 } 2930 if (cre->buf != NULL) { 2931 free(cre->buf); 2932 cre->buf = NULL; 2933 cre->buflen = 0; 2934 } 2935 2936 if (EVBUFFER_LENGTH(bufev->output) != 0) 2937 relay_bufferevent_add(&bufev->ev_write, bufev->timeout_write); 2938 2939 if (bufev->writecb != NULL && 2940 EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low) 2941 (*bufev->writecb)(bufev, bufev->cbarg); 2942 return; 2943 2944 retry: 2945 if (cre->buflen != 0) 2946 relay_bufferevent_add(&bufev->ev_write, bufev->timeout_write); 2947 return; 2948 2949 err: 2950 if (cre->buf != NULL) { 2951 free(cre->buf); 2952 cre->buf = NULL; 2953 cre->buflen = 0; 2954 } 2955 (*bufev->errorcb)(bufev, what, bufev->cbarg); 2956 } 2957 2958 int 2959 relay_bufferevent_add(struct event *ev, int timeout) 2960 { 2961 struct timeval tv, *ptv = NULL; 2962 2963 if (timeout) { 2964 timerclear(&tv); 2965 tv.tv_sec = timeout; 2966 ptv = &tv; 2967 } 2968 2969 return (event_add(ev, ptv)); 2970 } 2971 2972 #ifdef notyet 2973 int 2974 relay_bufferevent_printf(struct ctl_relay_event *cre, const char *fmt, ...) 2975 { 2976 int ret; 2977 va_list ap; 2978 2979 va_start(ap, fmt); 2980 ret = evbuffer_add_vprintf(cre->output, fmt, ap); 2981 va_end(ap); 2982 2983 if (cre->bev != NULL && 2984 ret != -1 && EVBUFFER_LENGTH(cre->output) > 0 && 2985 (cre->bev->enabled & EV_WRITE)) 2986 bufferevent_enable(cre->bev, EV_WRITE); 2987 2988 return (ret); 2989 } 2990 #endif 2991 2992 int 2993 relay_bufferevent_print(struct ctl_relay_event *cre, char *str) 2994 { 2995 if (cre->bev == NULL) 2996 return (evbuffer_add(cre->output, str, strlen(str))); 2997 return (bufferevent_write(cre->bev, str, strlen(str))); 2998 } 2999 3000 int 3001 relay_bufferevent_write_buffer(struct ctl_relay_event *cre, 3002 struct evbuffer *buf) 3003 { 3004 if (cre->bev == NULL) 3005 return (evbuffer_add_buffer(cre->output, buf)); 3006 return (bufferevent_write_buffer(cre->bev, buf)); 3007 } 3008 3009 int 3010 relay_bufferevent_write_chunk(struct ctl_relay_event *cre, 3011 struct evbuffer *buf, size_t size) 3012 { 3013 int ret; 3014 ret = relay_bufferevent_write(cre, buf->buffer, size); 3015 if (ret != -1) 3016 evbuffer_drain(buf, size); 3017 return (ret); 3018 } 3019 3020 int 3021 relay_bufferevent_write(struct ctl_relay_event *cre, void *data, size_t size) 3022 { 3023 if (cre->bev == NULL) 3024 return (evbuffer_add(cre->output, data, size)); 3025 return (bufferevent_write(cre->bev, data, size)); 3026 } 3027 3028 int 3029 relay_cmp_af(struct sockaddr_storage *a, struct sockaddr_storage *b) 3030 { 3031 int ret = -1; 3032 struct sockaddr_in ia, ib; 3033 struct sockaddr_in6 ia6, ib6; 3034 3035 switch (a->ss_family) { 3036 case AF_INET: 3037 bcopy(a, &ia, sizeof(struct sockaddr_in)); 3038 bcopy(b, &ib, sizeof(struct sockaddr_in)); 3039 3040 ret = memcmp(&ia.sin_addr, &ib.sin_addr, 3041 sizeof(ia.sin_addr)); 3042 if (ret == 0) 3043 ret = memcmp(&ia.sin_port, &ib.sin_port, 3044 sizeof(ia.sin_port)); 3045 break; 3046 case AF_INET6: 3047 bcopy(a, &ia6, sizeof(struct sockaddr_in6)); 3048 bcopy(b, &ib6, sizeof(struct sockaddr_in6)); 3049 3050 ret = memcmp(&ia6.sin6_addr, &ib6.sin6_addr, 3051 sizeof(ia6.sin6_addr)); 3052 if (ret == 0) 3053 ret = memcmp(&ia6.sin6_port, &ib6.sin6_port, 3054 sizeof(ia6.sin6_port)); 3055 break; 3056 default: 3057 break; 3058 } 3059 3060 return (ret); 3061 } 3062 3063 char * 3064 relay_load_file(const char *name, off_t *len) 3065 { 3066 struct stat st; 3067 off_t size; 3068 u_int8_t *buf = NULL; 3069 int fd; 3070 3071 if ((fd = open(name, O_RDONLY)) == -1) 3072 return (NULL); 3073 if (fstat(fd, &st) != 0) 3074 goto fail; 3075 size = st.st_size; 3076 if ((buf = (char *)calloc(1, size + 1)) == NULL) 3077 goto fail; 3078 if (read(fd, buf, size) != size) 3079 goto fail; 3080 3081 close(fd); 3082 3083 *len = size; 3084 return (buf); 3085 3086 fail: 3087 if (buf != NULL) 3088 free(buf); 3089 close(fd); 3090 return (NULL); 3091 } 3092 3093 int 3094 relay_load_certfiles(struct relay *rlay) 3095 { 3096 struct protocol *proto = rlay->rl_proto; 3097 char certfile[PATH_MAX]; 3098 char hbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; 3099 3100 if ((rlay->rl_conf.flags & F_SSLCLIENT) && strlen(proto->sslca)) { 3101 if ((rlay->rl_ssl_ca = relay_load_file(proto->sslca, 3102 &rlay->rl_conf.ssl_ca_len)) == NULL) 3103 return (-1); 3104 log_debug("%s: using ca %s", __func__, proto->sslca); 3105 } 3106 3107 if ((rlay->rl_conf.flags & F_SSL) == 0) 3108 return (0); 3109 3110 if (print_host(&rlay->rl_conf.ss, hbuf, sizeof(hbuf)) == NULL) 3111 return (-1); 3112 3113 if (snprintf(certfile, sizeof(certfile), 3114 "/etc/ssl/%s.crt", hbuf) == -1) 3115 return (-1); 3116 if ((rlay->rl_ssl_cert = relay_load_file(certfile, 3117 &rlay->rl_conf.ssl_cert_len)) == NULL) 3118 return (-1); 3119 log_debug("%s: using certificate %s", __func__, certfile); 3120 3121 if (snprintf(certfile, sizeof(certfile), 3122 "/etc/ssl/private/%s.key", hbuf) == -1) 3123 return -1; 3124 if ((rlay->rl_ssl_key = relay_load_file(certfile, 3125 &rlay->rl_conf.ssl_key_len)) == NULL) 3126 return (-1); 3127 log_debug("%s: using private key %s", __func__, certfile); 3128 3129 return (0); 3130 } 3131 3132 static __inline int 3133 relay_proto_cmp(struct protonode *a, struct protonode *b) 3134 { 3135 int ret; 3136 ret = strcasecmp(a->key, b->key); 3137 if (ret == 0) 3138 ret = (int)a->type - b->type; 3139 return (ret); 3140 } 3141 3142 RB_GENERATE(proto_tree, protonode, nodes, relay_proto_cmp); 3143 3144 int 3145 relay_session_cmp(struct rsession *a, struct rsession *b) 3146 { 3147 struct relay *rlay = (struct relay *)b->se_relay; 3148 struct protocol *proto = rlay->rl_proto; 3149 3150 if (proto != NULL && proto->cmp != NULL) 3151 return ((*proto->cmp)(a, b)); 3152 3153 return ((int)a->se_id - b->se_id); 3154 } 3155 3156 SPLAY_GENERATE(session_tree, rsession, se_nodes, relay_session_cmp); 3157