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