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