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