1 /* $NetBSD: proxy2.c,v 1.2 2025/01/26 16:25:38 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #include <isc/proxy2.h> 17 18 enum isc_proxy2_states { 19 ISC_PROXY2_STATE_WAITING_SIGNATURE, 20 ISC_PROXY2_STATE_WAITING_HEADER, 21 ISC_PROXY2_STATE_WAITING_PAYLOAD, /* Addresses and TLVs */ 22 ISC_PROXY2_STATE_END 23 }; 24 25 static inline void 26 isc__proxy2_handler_init_direct(isc_proxy2_handler_t *restrict handler, 27 const uint16_t max_size, 28 const isc_region_t *restrict data, 29 isc_proxy2_handler_cb_t cb, void *cbarg) { 30 *handler = (isc_proxy2_handler_t){ .result = ISC_R_UNSET, 31 .max_size = max_size }; 32 isc_proxy2_handler_setcb(handler, cb, cbarg); 33 34 if (data == NULL) { 35 isc_buffer_init(&handler->hdrbuf, handler->buf, 36 sizeof(handler->buf)); 37 } else { 38 isc_buffer_init(&handler->hdrbuf, data->base, data->length); 39 isc_buffer_add(&handler->hdrbuf, data->length); 40 } 41 } 42 43 void 44 isc_proxy2_handler_init(isc_proxy2_handler_t *restrict handler, isc_mem_t *mctx, 45 const uint16_t max_size, isc_proxy2_handler_cb_t cb, 46 void *cbarg) { 47 REQUIRE(handler != NULL); 48 REQUIRE(mctx != NULL); 49 REQUIRE(max_size == 0 || max_size >= ISC_PROXY2_HEADER_SIZE); 50 REQUIRE(cb != NULL); 51 52 isc__proxy2_handler_init_direct(handler, max_size, NULL, cb, cbarg); 53 54 isc_mem_attach(mctx, &handler->mctx); 55 isc_buffer_setmctx(&handler->hdrbuf, handler->mctx); 56 } 57 58 void 59 isc_proxy2_handler_uninit(isc_proxy2_handler_t *restrict handler) { 60 REQUIRE(handler != NULL); 61 62 /* 63 * Uninitialising the object from withing the callback does not 64 * make any sense. 65 */ 66 INSIST(handler->calling_cb == false); 67 if (handler->mctx != NULL) { 68 isc_buffer_clearmctx(&handler->hdrbuf); 69 isc_mem_detach(&handler->mctx); 70 } 71 isc_buffer_invalidate(&handler->hdrbuf); 72 } 73 74 void 75 isc_proxy2_handler_clear(isc_proxy2_handler_t *restrict handler) { 76 REQUIRE(handler != NULL); 77 78 *handler = (isc_proxy2_handler_t){ .result = ISC_R_UNSET, 79 .mctx = handler->mctx, 80 .cb = handler->cb, 81 .cbarg = handler->cbarg, 82 .hdrbuf = handler->hdrbuf, 83 .max_size = handler->max_size }; 84 85 isc_buffer_clear(&handler->hdrbuf); 86 isc_buffer_trycompact(&handler->hdrbuf); 87 } 88 89 isc_proxy2_handler_t * 90 isc_proxy2_handler_new(isc_mem_t *mctx, const uint16_t max_size, 91 isc_proxy2_handler_cb_t cb, void *cbarg) { 92 isc_proxy2_handler_t *newhandler; 93 94 REQUIRE(mctx != NULL); 95 REQUIRE(cb != NULL); 96 97 newhandler = isc_mem_get(mctx, sizeof(*newhandler)); 98 isc_proxy2_handler_init(newhandler, mctx, max_size, cb, cbarg); 99 100 return newhandler; 101 } 102 103 void 104 isc_proxy2_handler_free(isc_proxy2_handler_t **restrict phandler) { 105 isc_proxy2_handler_t *restrict handler = NULL; 106 isc_mem_t *mctx = NULL; 107 REQUIRE(phandler != NULL && *phandler != NULL); 108 109 handler = *phandler; 110 111 isc_mem_attach(handler->mctx, &mctx); 112 isc_proxy2_handler_uninit(handler); 113 isc_mem_putanddetach(&mctx, handler, sizeof(*handler)); 114 115 *phandler = NULL; 116 } 117 118 void 119 isc_proxy2_handler_setcb(isc_proxy2_handler_t *restrict handler, 120 isc_proxy2_handler_cb_t cb, void *cbarg) { 121 REQUIRE(handler != NULL); 122 REQUIRE(cb != NULL); 123 handler->cb = cb; 124 handler->cbarg = cbarg; 125 } 126 127 static inline int 128 proxy2_socktype_to_socktype(const isc_proxy2_socktype_t proxy_socktype) { 129 int socktype = 0; 130 131 switch (proxy_socktype) { 132 case ISC_PROXY2_SOCK_UNSPEC: 133 socktype = 0; 134 break; 135 case ISC_PROXY2_SOCK_STREAM: 136 socktype = SOCK_STREAM; 137 break; 138 case ISC_PROXY2_SOCK_DGRAM: 139 socktype = SOCK_DGRAM; 140 break; 141 default: 142 ISC_UNREACHABLE(); 143 }; 144 145 return socktype; 146 } 147 148 static inline void 149 isc__proxy2_handler_callcb(isc_proxy2_handler_t *restrict handler, 150 const isc_result_t result, 151 const isc_proxy2_command_t cmd, 152 const isc_proxy2_socktype_t proxy_socktype, 153 const isc_sockaddr_t *src_addr, 154 const isc_sockaddr_t *dst_addr, 155 const isc_region_t *restrict tlv_data, 156 const isc_region_t *restrict extra_data) { 157 int socktype = 0; 158 159 handler->result = result; 160 handler->calling_cb = true; 161 162 if (result != ISC_R_SUCCESS) { 163 handler->cb(result, cmd, -1, NULL, NULL, NULL, NULL, 164 handler->cbarg); 165 } else { 166 socktype = proxy2_socktype_to_socktype(proxy_socktype); 167 handler->cb(result, cmd, socktype, 168 proxy_socktype == ISC_PROXY2_SOCK_UNSPEC ? NULL 169 : src_addr, 170 proxy_socktype == ISC_PROXY2_SOCK_UNSPEC ? NULL 171 : dst_addr, 172 tlv_data->length == 0 ? NULL : tlv_data, 173 extra_data->length == 0 ? NULL : extra_data, 174 handler->cbarg); 175 } 176 177 handler->calling_cb = false; 178 } 179 180 static inline void 181 isc__proxy2_handler_error(isc_proxy2_handler_t *restrict handler, 182 const isc_result_t result) { 183 INSIST(result != ISC_R_SUCCESS); 184 isc__proxy2_handler_callcb(handler, result, ISC_PROXY2_CMD_ILLEGAL, 185 ISC_PROXY2_SOCK_ILLEGAL, NULL, NULL, NULL, 186 NULL); 187 if (result != ISC_R_NOMORE) { 188 handler->state = ISC_PROXY2_STATE_END; 189 } 190 } 191 192 static inline bool 193 isc__proxy2_handler_handle_signature(isc_proxy2_handler_t *restrict handler) { 194 isc_region_t remaining = { 0, 0 }; 195 size_t len; 196 197 isc_buffer_remainingregion(&handler->hdrbuf, &remaining); 198 len = ISC_MIN(remaining.length, ISC_PROXY2_HEADER_SIGNATURE_SIZE); 199 200 if (memcmp(ISC_PROXY2_HEADER_SIGNATURE, remaining.base, len) != 0) { 201 isc__proxy2_handler_error(handler, ISC_R_UNEXPECTED); 202 return false; 203 } else if (len == ISC_PROXY2_HEADER_SIGNATURE_SIZE) { 204 isc_buffer_forward(&handler->hdrbuf, 205 ISC_PROXY2_HEADER_SIGNATURE_SIZE); 206 handler->expect_data = ISC_PROXY2_HEADER_SIZE - 207 ISC_PROXY2_HEADER_SIGNATURE_SIZE; 208 handler->state++; 209 } else { 210 INSIST(len < ISC_PROXY2_HEADER_SIGNATURE_SIZE); 211 isc__proxy2_handler_error(handler, ISC_R_NOMORE); 212 return false; 213 } 214 return true; 215 } 216 217 static inline bool 218 isc__proxy2_handler_handle_header(isc_proxy2_handler_t *restrict handler) { 219 /* 220 * The PROXYv2 header can be described as (signature 'sig' has been 221 * processed and verified already as a separate step): 222 * 223 * struct proxy_hdr_v2 { 224 * uint8_t sig[12]; // hex 0D 0A 0D 0A 00 0D 0A 51 55 49 54 0A 225 * uint8_t ver_cmd; // protocol version and command 226 * uint8_t fam; // protocol family and address 227 * uint16_t len; // number of following bytes part of the header 228 * }; 229 */ 230 uint8_t ver_cmd = 0; 231 uint8_t cmd = 0; 232 uint8_t fam = 0; 233 uint16_t len = 0; 234 int addrfamily = 0; 235 int socktype = 0; 236 size_t min_addr_payload_size = 0; 237 238 ver_cmd = isc_buffer_getuint8(&handler->hdrbuf); 239 240 /* extract version and check it */ 241 if ((ver_cmd & 0xF0U) >> 4 != 2) { 242 /* only support for version 2 is implemented */ 243 isc__proxy2_handler_error(handler, ISC_R_NOTIMPLEMENTED); 244 return false; 245 } 246 247 /* extract command */ 248 cmd = ver_cmd & 0xFU; 249 250 fam = isc_buffer_getuint8(&handler->hdrbuf); 251 len = isc_buffer_getuint16(&handler->hdrbuf); 252 253 if (handler->max_size > 0 && 254 (len + ISC_PROXY2_HEADER_SIZE) > handler->max_size) 255 { 256 goto error_range; 257 } 258 259 handler->expect_data = len; 260 261 /* extract address family and socket type */ 262 addrfamily = (fam & 0xF0U) >> 4; 263 socktype = fam & 0xFU; 264 265 /* dispatch on the command value */ 266 switch (cmd) { 267 case ISC_PROXY2_CMD_LOCAL: 268 /* LOCAL implies "unspec" mode */ 269 handler->cmd = ISC_PROXY2_CMD_LOCAL; 270 if (addrfamily != ISC_PROXY2_AF_UNSPEC || 271 socktype != ISC_PROXY2_SOCK_UNSPEC) 272 { 273 goto error_unexpected; 274 } 275 handler->proxy_addr_family = ISC_PROXY2_AF_UNSPEC; 276 handler->proxy_socktype = ISC_PROXY2_SOCK_UNSPEC; 277 break; 278 case ISC_PROXY2_CMD_PROXY: 279 handler->cmd = ISC_PROXY2_CMD_PROXY; 280 switch (addrfamily) { 281 case ISC_PROXY2_AF_UNSPEC: 282 if (socktype != ISC_PROXY2_SOCK_UNSPEC) { 283 goto error_unexpected; 284 } 285 handler->proxy_addr_family = ISC_PROXY2_AF_UNSPEC; 286 handler->proxy_socktype = ISC_PROXY2_SOCK_UNSPEC; 287 break; 288 case ISC_PROXY2_AF_INET: 289 case ISC_PROXY2_AF_INET6: 290 case ISC_PROXY2_AF_UNIX: 291 handler->proxy_addr_family = 292 (isc_proxy2_addrfamily_t)addrfamily; 293 switch (socktype) { 294 case ISC_PROXY2_SOCK_DGRAM: 295 case ISC_PROXY2_SOCK_STREAM: 296 handler->proxy_socktype = 297 (isc_proxy2_socktype_t)socktype; 298 break; 299 default: 300 goto error_unexpected; 301 } 302 break; 303 default: 304 goto error_unexpected; 305 } 306 break; 307 default: 308 goto error_unexpected; 309 }; 310 311 /* verify if enough data will be available in the payload */ 312 switch (handler->proxy_addr_family) { 313 case ISC_PROXY2_AF_INET: 314 min_addr_payload_size = ISC_PROXY2_MIN_AF_INET_SIZE - 315 ISC_PROXY2_HEADER_SIZE; 316 break; 317 case ISC_PROXY2_AF_INET6: 318 min_addr_payload_size = ISC_PROXY2_MIN_AF_INET6_SIZE - 319 ISC_PROXY2_HEADER_SIZE; 320 break; 321 case ISC_PROXY2_AF_UNIX: 322 min_addr_payload_size = ISC_PROXY2_MIN_AF_UNIX_SIZE - 323 ISC_PROXY2_HEADER_SIZE; 324 break; 325 default: 326 break; 327 } 328 329 if (min_addr_payload_size > 0) { 330 if (len < min_addr_payload_size) { 331 goto error_range; 332 } 333 handler->tlv_data_size = len - min_addr_payload_size; 334 } 335 336 if (handler->tlv_data_size > 0 && 337 handler->tlv_data_size < ISC_PROXY2_TLV_HEADER_SIZE) 338 { 339 goto error_range; 340 } 341 342 handler->header_size = ISC_PROXY2_HEADER_SIZE + len; 343 344 handler->state++; 345 346 return true; 347 348 error_unexpected: 349 isc__proxy2_handler_error(handler, ISC_R_UNEXPECTED); 350 return false; 351 error_range: 352 isc__proxy2_handler_error(handler, ISC_R_RANGE); 353 return false; 354 } 355 356 static inline isc_result_t 357 isc__proxy2_handler_get_addresses(isc_proxy2_handler_t *restrict handler, 358 isc_buffer_t *restrict hdrbuf, 359 isc_sockaddr_t *restrict src_addr, 360 isc_sockaddr_t *restrict dst_addr) { 361 size_t addr_size = 0; 362 void *psrc_addr = NULL, *pdst_addr = NULL; 363 uint16_t src_port = 0, dst_port = 0; 364 365 switch (handler->proxy_addr_family) { 366 case ISC_PROXY2_AF_UNSPEC: 367 /* in this case we are instructed to skip over the data */ 368 INSIST(handler->tlv_data_size == 0); 369 isc_buffer_forward(hdrbuf, handler->expect_data); 370 break; 371 case ISC_PROXY2_AF_INET: 372 addr_size = sizeof(src_addr->type.sin.sin_addr.s_addr); 373 /* 374 * IPv4 source and destination endpoint addresses can be 375 * described as follows: 376 * 377 * struct { // for TCP/UDP over IPv4, len = 12 378 * uint32_t src_addr; 379 * uint32_t dst_addr; 380 * uint16_t src_port; 381 * uint16_t dst_port; 382 * } ipv4_addr; 383 */ 384 psrc_addr = isc_buffer_current(hdrbuf); 385 isc_buffer_forward(hdrbuf, addr_size); 386 387 pdst_addr = isc_buffer_current(hdrbuf); 388 isc_buffer_forward(hdrbuf, addr_size); 389 390 src_port = isc_buffer_getuint16(hdrbuf); 391 dst_port = isc_buffer_getuint16(hdrbuf); 392 393 if (src_addr != NULL) { 394 isc_sockaddr_fromin(src_addr, psrc_addr, src_port); 395 } 396 if (dst_addr != NULL) { 397 isc_sockaddr_fromin(dst_addr, pdst_addr, dst_port); 398 } 399 break; 400 case ISC_PROXY2_AF_INET6: 401 addr_size = sizeof(src_addr->type.sin6.sin6_addr); 402 /* 403 * IPv4 source and destination endpoint addresses can be 404 * described as follows: 405 * 406 * struct { // for TCP/UDP over IPv6, len = 36 407 * uint8_t src_addr[16]; 408 * uint8_t dst_addr[16]; 409 * uint16_t src_port; 410 * uint16_t dst_port; 411 * } ipv6_addr; 412 */ 413 psrc_addr = isc_buffer_current(hdrbuf); 414 isc_buffer_forward(hdrbuf, addr_size); 415 416 pdst_addr = isc_buffer_current(hdrbuf); 417 isc_buffer_forward(hdrbuf, addr_size); 418 419 src_port = isc_buffer_getuint16(hdrbuf); 420 dst_port = isc_buffer_getuint16(hdrbuf); 421 422 if (src_addr != NULL) { 423 isc_sockaddr_fromin6(src_addr, psrc_addr, src_port); 424 } 425 426 if (dst_addr != NULL) { 427 isc_sockaddr_fromin6(dst_addr, pdst_addr, dst_port); 428 } 429 break; 430 case ISC_PROXY2_AF_UNIX: { 431 /* 432 * UNIX domain sockets source and destination endpoint 433 * addresses can be described as follows: 434 * 435 * struct { // for AF_UNIX sockets, len = 216 436 * uint8_t src_addr[108]; 437 * uint8_t dst_addr[108]; 438 * } unix_addr; 439 * 440 * We currently have no use for this address type, but we can 441 * validate the data. 442 */ 443 unsigned char *ret = NULL; 444 445 addr_size = ISC_PROXY2_AF_UNIX_MAX_PATH_LEN; 446 447 ret = memchr(isc_buffer_current(hdrbuf), '\0', addr_size); 448 if (ret == NULL) { 449 /* 450 * Someone has attempted to send us a path string 451 * without a terminating '\0' byte - not a friend 452 * knocking at the door. 453 */ 454 return ISC_R_RANGE; 455 } 456 isc_buffer_forward(hdrbuf, addr_size); 457 458 ret = memchr(isc_buffer_current(hdrbuf), '\0', addr_size); 459 if (ret == NULL) { 460 return ISC_R_RANGE; 461 } 462 isc_buffer_forward(hdrbuf, addr_size); 463 } break; 464 default: 465 UNREACHABLE(); 466 } 467 468 return ISC_R_SUCCESS; 469 } 470 471 static inline void 472 isc__proxy2_handler_handle_payload(isc_proxy2_handler_t *restrict handler) { 473 isc_result_t result; 474 isc_sockaddr_t src_addr = { 0 }, dst_addr = { 0 }; 475 476 result = isc__proxy2_handler_get_addresses(handler, &handler->hdrbuf, 477 &src_addr, &dst_addr); 478 479 if (result != ISC_R_SUCCESS) { 480 isc__proxy2_handler_error(handler, result); 481 return; 482 } 483 484 if (handler->tlv_data_size > 0) { 485 isc_buffer_remainingregion(&handler->hdrbuf, 486 &handler->tlv_data); 487 handler->tlv_data.length = handler->tlv_data_size; 488 isc_buffer_forward(&handler->hdrbuf, handler->tlv_data_size); 489 result = isc_proxy2_tlv_data_verify(&handler->tlv_data); 490 if (result != ISC_R_SUCCESS) { 491 isc__proxy2_handler_error(handler, result); 492 return; 493 } 494 } 495 496 isc_buffer_remainingregion(&handler->hdrbuf, &handler->extra_data); 497 handler->expect_data = 0; 498 499 handler->state++; 500 501 /* 502 * Treat AF_UNIX as AF_UNSPEC as we have no use for it, although 503 * at this point we have fully verified the header. 504 */ 505 if (handler->proxy_addr_family == ISC_PROXY2_AF_UNIX) { 506 handler->proxy_addr_family = ISC_PROXY2_AF_UNSPEC; 507 handler->proxy_socktype = ISC_PROXY2_SOCK_UNSPEC; 508 handler->tlv_data = (isc_region_t){ 0 }; 509 } 510 511 isc__proxy2_handler_callcb( 512 handler, ISC_R_SUCCESS, handler->cmd, handler->proxy_socktype, 513 &src_addr, &dst_addr, &handler->tlv_data, &handler->extra_data); 514 515 return; 516 } 517 518 static inline bool 519 isc__proxy2_handler_handle_data(isc_proxy2_handler_t *restrict handler) { 520 if (isc_buffer_remaininglength(&handler->hdrbuf) < handler->expect_data) 521 { 522 isc__proxy2_handler_error(handler, ISC_R_NOMORE); 523 return false; 524 } 525 526 switch (handler->state) { 527 case ISC_PROXY2_STATE_WAITING_SIGNATURE: 528 /* 529 * We check for signature no matter how many bytes of it we 530 * have received. The idea is to not wait for the whole 531 * signature to verify it at once, but to detect, e.g. port 532 * scanners as early as possible. Should we receive data byte 533 * by byte, we would detect the problem when processing the 534 * first unexpected byte. 535 */ 536 return isc__proxy2_handler_handle_signature(handler); 537 case ISC_PROXY2_STATE_WAITING_HEADER: 538 /* 539 * Handle the rest of the header (except signature which we 540 * heave verified by now). 541 */ 542 return isc__proxy2_handler_handle_header(handler); 543 case ISC_PROXY2_STATE_WAITING_PAYLOAD: 544 /* 545 * Handle the PROXYv2 header payload - addresses and TLVs. 546 */ 547 isc__proxy2_handler_handle_payload(handler); 548 break; 549 default: 550 UNREACHABLE(); 551 break; 552 }; 553 554 return false; 555 } 556 557 static inline isc_result_t 558 isc__proxy2_handler_process_data(isc_proxy2_handler_t *restrict handler) { 559 while (isc__proxy2_handler_handle_data(handler)) { 560 if (handler->state == ISC_PROXY2_STATE_END) { 561 break; 562 } 563 } 564 565 return handler->result; 566 } 567 568 isc_result_t 569 isc_proxy2_handler_push_data(isc_proxy2_handler_t *restrict handler, 570 const void *restrict buf, 571 const unsigned int buf_size) { 572 isc_result_t result; 573 574 REQUIRE(handler != NULL); 575 REQUIRE(buf != NULL && buf_size != 0); 576 577 INSIST(!handler->calling_cb); 578 579 if (handler->state == ISC_PROXY2_STATE_END) { 580 isc_proxy2_handler_clear(handler); 581 } 582 583 isc_buffer_putmem(&handler->hdrbuf, buf, buf_size); 584 585 result = isc__proxy2_handler_process_data(handler); 586 587 return result; 588 } 589 590 isc_result_t 591 isc_proxy2_handler_push(isc_proxy2_handler_t *restrict handler, 592 const isc_region_t *restrict region) { 593 isc_result_t result; 594 595 REQUIRE(handler != NULL); 596 REQUIRE(region != NULL); 597 598 result = isc_proxy2_handler_push_data(handler, region->base, 599 region->length); 600 601 return result; 602 } 603 604 static inline bool 605 proxy2_payload_is_processed(const isc_proxy2_handler_t *restrict handler) { 606 if (handler->state < ISC_PROXY2_STATE_END || 607 handler->result != ISC_R_SUCCESS) 608 { 609 return false; 610 } 611 612 return true; 613 } 614 615 size_t 616 isc_proxy2_handler_header(const isc_proxy2_handler_t *restrict handler, 617 isc_region_t *restrict region) { 618 REQUIRE(handler != NULL); 619 REQUIRE(region == NULL || 620 (region->base == NULL && region->length == 0)); 621 622 if (!proxy2_payload_is_processed(handler)) { 623 return 0; 624 } 625 626 if (region != NULL) { 627 region->base = isc_buffer_base(&handler->hdrbuf); 628 region->length = handler->header_size; 629 } 630 631 return handler->header_size; 632 } 633 634 size_t 635 isc_proxy2_handler_tlvs(const isc_proxy2_handler_t *restrict handler, 636 isc_region_t *restrict region) { 637 REQUIRE(handler != NULL); 638 REQUIRE(region == NULL || 639 (region->base == NULL && region->length == 0)); 640 641 if (!proxy2_payload_is_processed(handler)) { 642 return 0; 643 } 644 645 SET_IF_NOT_NULL(region, handler->tlv_data); 646 647 return handler->tlv_data.length; 648 } 649 650 size_t 651 isc_proxy2_handler_extra(const isc_proxy2_handler_t *restrict handler, 652 isc_region_t *restrict region) { 653 REQUIRE(handler != NULL); 654 REQUIRE(region == NULL || 655 (region->base == NULL && region->length == 0)); 656 657 if (!proxy2_payload_is_processed(handler)) { 658 return 0; 659 } 660 661 SET_IF_NOT_NULL(region, handler->extra_data); 662 663 return handler->extra_data.length; 664 } 665 666 isc_result_t 667 isc_proxy2_handler_result(const isc_proxy2_handler_t *restrict handler) { 668 REQUIRE(handler != NULL); 669 670 return handler->result; 671 } 672 673 isc_result_t 674 isc_proxy2_handler_addresses(const isc_proxy2_handler_t *restrict handler, 675 int *restrict psocktype, 676 isc_sockaddr_t *restrict psrc_addr, 677 isc_sockaddr_t *restrict pdst_addr) { 678 isc_result_t result; 679 size_t ret; 680 isc_region_t header_region = { 0 }; 681 isc_buffer_t buf = { 0 }; 682 683 REQUIRE(handler != NULL); 684 685 if (!proxy2_payload_is_processed(handler)) { 686 return ISC_R_UNEXPECTED; 687 } 688 689 ret = isc_proxy2_handler_header(handler, &header_region); 690 RUNTIME_CHECK(ret > 0); 691 692 isc_buffer_init(&buf, header_region.base, header_region.length); 693 isc_buffer_add(&buf, header_region.length); 694 isc_buffer_forward(&buf, ISC_PROXY2_HEADER_SIZE); 695 696 INSIST(handler->expect_data == 0); 697 698 result = isc__proxy2_handler_get_addresses( 699 (isc_proxy2_handler_t *)handler, &buf, psrc_addr, pdst_addr); 700 701 if (result != ISC_R_SUCCESS) { 702 return result; 703 } 704 705 SET_IF_NOT_NULL(psocktype, 706 proxy2_socktype_to_socktype(handler->proxy_socktype)); 707 708 return ISC_R_SUCCESS; 709 } 710 711 isc_result_t 712 isc_proxy2_tlv_iterate(const isc_region_t *restrict tlv_data, 713 const isc_proxy2_tlv_cb_t cb, void *cbarg) { 714 isc_result_t result = ISC_R_SUCCESS; 715 isc_buffer_t tlvs = { 0 }; 716 size_t remaining; 717 718 /* 719 * TLV header can be described as follows: 720 * 721 * struct { 722 * uint8_t type; 723 * uint8_t length_hi; 724 * uint8_t length_lo; 725 * }; 726 * 727 */ 728 729 REQUIRE(tlv_data != NULL); 730 REQUIRE(cb != NULL); 731 732 isc_buffer_init(&tlvs, tlv_data->base, tlv_data->length); 733 isc_buffer_add(&tlvs, tlv_data->length); 734 735 while ((remaining = isc_buffer_remaininglength(&tlvs)) > 0) { 736 uint8_t type = 0; 737 uint16_t len = 0; 738 isc_region_t current_tlv_data = { 0 }; 739 bool ret = false; 740 741 /* not enough data for a TLV header */ 742 if (remaining < ISC_PROXY2_TLV_HEADER_SIZE) { 743 result = ISC_R_RANGE; 744 break; 745 } 746 747 type = isc_buffer_getuint8(&tlvs); 748 len = isc_buffer_getuint16(&tlvs); 749 750 if ((remaining - ISC_PROXY2_TLV_HEADER_SIZE) < len) { 751 result = ISC_R_RANGE; 752 break; 753 } 754 755 current_tlv_data.base = isc_buffer_current(&tlvs); 756 current_tlv_data.length = len; 757 isc_buffer_forward(&tlvs, len); 758 759 ret = cb((isc_proxy2_tlv_type_t)type, ¤t_tlv_data, cbarg); 760 if (!ret) { 761 break; 762 } 763 } 764 765 return result; 766 } 767 768 typedef struct proxy2_tls_cbarg { 769 uint8_t client; 770 bool client_cert_verified; 771 isc_proxy2_tls_subtlv_cb_t cb; 772 void *cbarg; 773 } tls_cbarg_t; 774 775 static bool 776 proxy2_tls_iter_cb(const isc_proxy2_tlv_type_t tlv_type, 777 const isc_region_t *restrict data, void *cbarg) { 778 bool ret = false; 779 tls_cbarg_t *tls_cbarg = (tls_cbarg_t *)cbarg; 780 781 ret = tls_cbarg->cb(tls_cbarg->client, tls_cbarg->client_cert_verified, 782 (isc_proxy2_tlv_subtype_tls_t)tlv_type, data, 783 tls_cbarg->cbarg); 784 785 return ret; 786 } 787 788 isc_result_t 789 isc_proxy2_subtlv_tls_header_data(const isc_region_t *restrict tls_tlv_data, 790 uint8_t *restrict pclient_flags, 791 bool *restrict pclient_cert_verified) { 792 /* 793 * SSL/TLS TLV header can be described as follows: 794 * 795 * struct { 796 * uint8_t client_flags; 797 * uint32_t client_cert_not_verified; 798 * } 799 */ 800 uint8_t *p = NULL; 801 uint8_t client_flags = 0; 802 bool client_cert_verified = false; 803 uint32_t client_cert_verified_data = 0; 804 805 REQUIRE(tls_tlv_data != NULL); 806 REQUIRE(pclient_flags == NULL || *pclient_flags == 0); 807 REQUIRE(pclient_cert_verified == NULL || 808 *pclient_cert_verified == false); 809 810 if (tls_tlv_data->length < ISC_PROXY2_TLS_SUBHEADER_MIN_SIZE) { 811 return ISC_R_RANGE; 812 } 813 814 p = tls_tlv_data->base; 815 816 client_flags = *p; 817 p++; 818 /* We need this to avoid ASAN complain about unaligned access */ 819 memmove(&client_cert_verified_data, p, sizeof(uint32_t)); 820 client_cert_verified = ntohl(client_cert_verified_data) == 0; 821 822 SET_IF_NOT_NULL(pclient_flags, client_flags); 823 SET_IF_NOT_NULL(pclient_cert_verified, client_cert_verified); 824 825 return ISC_R_SUCCESS; 826 } 827 828 isc_result_t 829 isc_proxy2_subtlv_tls_iterate(const isc_region_t *restrict tls_tlv_data, 830 const isc_proxy2_tls_subtlv_cb_t cb, 831 void *cbarg) { 832 tls_cbarg_t tls_cbarg; 833 isc_result_t result = ISC_R_SUCCESS; 834 uint8_t *p = NULL; 835 uint8_t client_flags = 0; 836 bool client_cert_verified = false; 837 838 REQUIRE(tls_tlv_data != NULL); 839 REQUIRE(cb != NULL); 840 841 if (tls_tlv_data->length < ISC_PROXY2_TLS_SUBHEADER_MIN_SIZE) { 842 return ISC_R_RANGE; 843 } 844 845 result = isc_proxy2_subtlv_tls_header_data(tls_tlv_data, &client_flags, 846 &client_cert_verified); 847 848 if (result != ISC_R_SUCCESS) { 849 return result; 850 } 851 852 p = tls_tlv_data->base; 853 p += ISC_PROXY2_TLS_SUBHEADER_MIN_SIZE; 854 855 if (cb != NULL) { 856 isc_region_t data = { 857 .base = p, 858 .length = tls_tlv_data->length - 859 ISC_PROXY2_TLS_SUBHEADER_MIN_SIZE 860 }; 861 tls_cbarg = (tls_cbarg_t){ .client = client_flags, 862 .client_cert_verified = 863 client_cert_verified, 864 .cb = cb, 865 .cbarg = cbarg }; 866 result = isc_proxy2_tlv_iterate(&data, proxy2_tls_iter_cb, 867 &tls_cbarg); 868 } 869 870 return result; 871 } 872 873 typedef struct tls_subtlv_verify_cbarg { 874 uint16_t *count; 875 isc_result_t verif_result; 876 } tls_subtlv_verify_cbarg_t; 877 878 static bool 879 proxy2_subtlv_verify_iter_cb(const uint8_t client, 880 const bool client_cert_verified, 881 const isc_proxy2_tlv_subtype_tls_t tls_subtlv_type, 882 const isc_region_t *restrict data, void *cbarg) { 883 bool verify_count = false; 884 tls_subtlv_verify_cbarg_t *restrict arg = 885 (tls_subtlv_verify_cbarg_t *)cbarg; 886 uint8_t type = tls_subtlv_type; 887 888 UNUSED(client); 889 UNUSED(client_cert_verified); 890 891 if (type <= ISC_PROXY2_TLV_TYPE_TLS || 892 type == ISC_PROXY2_TLV_TYPE_NETNS) 893 { 894 arg->verif_result = ISC_R_UNEXPECTED; 895 return false; 896 } 897 898 switch (tls_subtlv_type) { 899 case ISC_PROXY2_TLV_SUBTYPE_TLS_VERSION: 900 case ISC_PROXY2_TLV_SUBTYPE_TLS_CN: 901 case ISC_PROXY2_TLV_SUBTYPE_TLS_SIG_ALG: 902 case ISC_PROXY2_TLV_SUBTYPE_TLS_KEY_ALG: 903 if (data->length == 0) { 904 arg->verif_result = ISC_R_RANGE; 905 return false; 906 } 907 arg->count[tls_subtlv_type]++; 908 verify_count = true; 909 break; 910 default: 911 break; 912 }; 913 914 if (verify_count && arg->count[tls_subtlv_type] > 1) { 915 arg->verif_result = ISC_R_UNEXPECTED; 916 return false; 917 } 918 919 return true; 920 } 921 922 typedef struct tlv_verify_cbarg { 923 uint16_t count[256]; 924 isc_result_t verify_result; 925 } tlv_verify_cbarg_t; 926 927 static bool 928 isc_proxy2_tlv_verify_cb(const isc_proxy2_tlv_type_t tlv_type, 929 const isc_region_t *restrict data, void *cbarg) { 930 bool verify_count = false; 931 uint8_t client = 0; 932 tlv_verify_cbarg_t *arg = (tlv_verify_cbarg_t *)cbarg; 933 934 if (tlv_type == 0) { 935 /* the TLV values start from 1 */ 936 goto error_unexpected; 937 } 938 939 switch (tlv_type) { 940 case ISC_PROXY2_TLV_TYPE_ALPN: 941 case ISC_PROXY2_TLV_TYPE_AUTHORITY: 942 case ISC_PROXY2_TLV_TYPE_NETNS: 943 /* these values need to be more than 0 bytes long */ 944 if (data->length == 0) { 945 goto error_range; 946 } 947 arg->count[tlv_type]++; 948 verify_count = true; 949 break; 950 case ISC_PROXY2_TLV_TYPE_CRC32C: 951 if (data->length != sizeof(uint32_t)) { 952 goto error_range; 953 } 954 arg->count[tlv_type]++; 955 verify_count = true; 956 break; 957 case ISC_PROXY2_TLV_TYPE_UNIQUE_ID: 958 if (data->length > 128) { 959 goto error_range; 960 } 961 arg->count[tlv_type]++; 962 verify_count = true; 963 break; 964 case ISC_PROXY2_TLV_TYPE_TLS: { 965 tls_subtlv_verify_cbarg_t tls_cbarg = { 966 .verif_result = ISC_R_SUCCESS, .count = arg->count 967 }; 968 size_t tls_version_count, tls_cn_count; 969 970 arg->verify_result = 971 isc_proxy2_subtlv_tls_header_data(data, &client, NULL); 972 973 if (arg->verify_result != ISC_R_SUCCESS) { 974 return false; 975 } 976 977 arg->verify_result = isc_proxy2_subtlv_tls_iterate( 978 data, proxy2_subtlv_verify_iter_cb, &tls_cbarg); 979 980 if (arg->verify_result != ISC_R_SUCCESS) { 981 return false; 982 } else if (tls_cbarg.verif_result != ISC_R_SUCCESS) { 983 arg->verify_result = tls_cbarg.verif_result; 984 return false; 985 } 986 987 /* 988 * if CLIENT_TLS flag is set - TLS version TLV must be present 989 */ 990 tls_version_count = 991 arg->count[ISC_PROXY2_TLV_SUBTYPE_TLS_VERSION]; 992 993 if ((client & ISC_PROXY2_CLIENT_TLS) != 0) { 994 if (tls_version_count != 1) { 995 goto error_unexpected; 996 } 997 } else if (tls_version_count > 0) { 998 /* unexpected TLS version TLV */ 999 goto error_unexpected; 1000 } 1001 1002 /* 1003 * If client cert was submitted, CLIENT_CERT_CONN or 1004 * CLIENT_CERT_SESS flags must be present alongside the 1005 * CLIENT_TLS flag. 1006 */ 1007 tls_cn_count = arg->count[ISC_PROXY2_TLV_SUBTYPE_TLS_CN]; 1008 1009 if ((client & (ISC_PROXY2_CLIENT_CERT_CONN | 1010 ISC_PROXY2_CLIENT_CERT_SESS)) != 0) 1011 { 1012 if (tls_cn_count != 1 || 1013 (client & ISC_PROXY2_CLIENT_TLS) == 0) 1014 { 1015 goto error_unexpected; 1016 } 1017 } else if (tls_cn_count > 0) { 1018 /* unexpected Common Name TLV */ 1019 goto error_unexpected; 1020 } 1021 1022 arg->count[tlv_type]++; 1023 verify_count = true; 1024 } break; 1025 default: 1026 break; 1027 }; 1028 1029 if (verify_count && arg->count[tlv_type] > 1) { 1030 goto error_unexpected; 1031 } 1032 1033 return true; 1034 1035 error_unexpected: 1036 arg->verify_result = ISC_R_UNEXPECTED; 1037 return false; 1038 1039 error_range: 1040 arg->verify_result = ISC_R_RANGE; 1041 return false; 1042 } 1043 1044 isc_result_t 1045 isc_proxy2_tlv_data_verify(const isc_region_t *restrict tlv_data) { 1046 isc_result_t result; 1047 tlv_verify_cbarg_t cbarg = { .verify_result = ISC_R_SUCCESS }; 1048 1049 result = isc_proxy2_tlv_iterate(tlv_data, isc_proxy2_tlv_verify_cb, 1050 &cbarg); 1051 if (result != ISC_R_SUCCESS) { 1052 return result; 1053 } 1054 1055 return cbarg.verify_result; 1056 } 1057 1058 isc_result_t 1059 isc_proxy2_header_handle_directly(const isc_region_t *restrict header_data, 1060 const isc_proxy2_handler_cb_t cb, 1061 void *cbarg) { 1062 isc_result_t result; 1063 isc_proxy2_handler_t handler = { 0 }; 1064 1065 REQUIRE(header_data != NULL); 1066 REQUIRE(cb != NULL); 1067 1068 isc__proxy2_handler_init_direct(&handler, 0, header_data, cb, cbarg); 1069 1070 result = isc__proxy2_handler_process_data(&handler); 1071 1072 return result; 1073 } 1074 1075 isc_result_t 1076 isc_proxy2_make_header(isc_buffer_t *restrict outbuf, 1077 const isc_proxy2_command_t cmd, const int socktype, 1078 const isc_sockaddr_t *restrict src_addr, 1079 const isc_sockaddr_t *restrict dst_addr, 1080 const isc_region_t *restrict tlv_data) { 1081 size_t total_size = ISC_PROXY2_HEADER_SIZE; 1082 uint8_t family = ISC_PROXY2_AF_UNSPEC; 1083 isc_proxy2_socktype_t proxy_socktype = ISC_PROXY2_SOCK_UNSPEC; 1084 1085 uint8_t ver_cmd = 0; 1086 uint8_t fam_socktype = 0; 1087 uint16_t len = 0; 1088 1089 size_t addr_size = 0; 1090 void *psrc_addr = NULL, *pdst_addr = NULL; 1091 /* 1092 * The complete PROXYv2 header can be described as follows: 1093 * 1094 * 1. Header: 1095 * 1096 * struct proxy_hdr_v2 { 1097 * uint8_t sig[12]; // hex 0D 0A 0D 0A 00 0D 0A 51 55 49 54 0A 1098 * uint8_t ver_cmd; // protocol version and command 1099 * uint8_t fam_socktype; // protocol family and socket type 1100 * uint16_t len; // number of following bytes 1101 * }; 1102 * 1103 * 2. Addresses: 1104 * 1105 * union proxy_addr { 1106 * struct { // for TCP/UDP over IPv4, len = 12 1107 * uint32_t src_addr; 1108 * uint32_t dst_addr; 1109 * uint16_t src_port; 1110 * uint16_t dst_port; 1111 * } ipv4_addr; 1112 * struct { // for TCP/UDP over IPv6, len = 36 1113 * uint8_t src_addr[16]; 1114 * uint8_t dst_addr[16]; 1115 * uint16_t src_port; 1116 * uint16_t dst_port; 1117 * } ipv6_addr; 1118 * struct { // for AF_UNIX sockets, len = 216 1119 * uint8_t src_addr[108]; 1120 * uint8_t dst_addr[108]; 1121 * } unix_addr; 1122 * }; 1123 * 1124 * 3. TLVs (optional) 1125 */ 1126 1127 REQUIRE(outbuf != NULL); 1128 REQUIRE(cmd == ISC_PROXY2_CMD_PROXY || socktype == 0); 1129 REQUIRE((src_addr == NULL && dst_addr == NULL) || 1130 (src_addr != NULL && dst_addr != NULL)); 1131 REQUIRE(src_addr == NULL || 1132 (isc_sockaddr_pf(src_addr) == isc_sockaddr_pf(dst_addr))); 1133 1134 switch (cmd) { 1135 case ISC_PROXY2_CMD_LOCAL: 1136 family = ISC_PROXY2_AF_UNSPEC; 1137 break; 1138 case ISC_PROXY2_CMD_PROXY: 1139 if (socktype == 0) { 1140 family = ISC_PROXY2_AF_UNSPEC; 1141 } else { 1142 switch (isc_sockaddr_pf(src_addr)) { 1143 case AF_INET: 1144 family = ISC_PROXY2_AF_INET; 1145 addr_size = sizeof(src_addr->type.sin.sin_addr); 1146 total_size += addr_size * 2 + 1147 sizeof(uint16_t) * 2; 1148 psrc_addr = (void *)&src_addr->type.sin.sin_addr 1149 .s_addr; 1150 pdst_addr = (void *)&dst_addr->type.sin.sin_addr 1151 .s_addr; 1152 break; 1153 case AF_INET6: 1154 family = ISC_PROXY2_AF_INET6; 1155 addr_size = 1156 sizeof(src_addr->type.sin6.sin6_addr); 1157 total_size += addr_size * 2 + 1158 sizeof(uint16_t) * 2; 1159 psrc_addr = 1160 (void *)&src_addr->type.sin6.sin6_addr; 1161 pdst_addr = 1162 (void *)&dst_addr->type.sin6.sin6_addr; 1163 break; 1164 default: 1165 return ISC_R_UNEXPECTED; 1166 } 1167 } 1168 break; 1169 default: 1170 return ISC_R_UNEXPECTED; 1171 } 1172 1173 switch (socktype) { 1174 case 0: 1175 proxy_socktype = ISC_PROXY2_SOCK_UNSPEC; 1176 break; 1177 case SOCK_STREAM: 1178 proxy_socktype = ISC_PROXY2_SOCK_STREAM; 1179 break; 1180 case SOCK_DGRAM: 1181 proxy_socktype = ISC_PROXY2_SOCK_DGRAM; 1182 break; 1183 default: 1184 return ISC_R_UNEXPECTED; 1185 } 1186 1187 if (tlv_data != NULL) { 1188 if (tlv_data->length > UINT16_MAX) { 1189 return ISC_R_RANGE; 1190 } 1191 total_size += tlv_data->length; 1192 } 1193 1194 if (isc_buffer_availablelength(outbuf) < total_size) { 1195 return ISC_R_NOSPACE; 1196 } else if (total_size > UINT16_MAX) { 1197 return ISC_R_RANGE; 1198 } 1199 1200 /* 1201 * Combine version 2 (highest four bits) and command (lowest four 1202 * bits). 1203 */ 1204 ver_cmd = (((2 << 4) & 0xF0U) | cmd); 1205 1206 /* 1207 * Combine address family (highest four bits) and socket type 1208 * (lowest four bits). 1209 */ 1210 fam_socktype = (((family << 4) & 0xF0U) | proxy_socktype); 1211 1212 len = (uint16_t)(total_size - ISC_PROXY2_HEADER_SIZE); 1213 1214 /* Write signature */ 1215 isc_buffer_putmem(outbuf, (uint8_t *)ISC_PROXY2_HEADER_SIGNATURE, 1216 ISC_PROXY2_HEADER_SIGNATURE_SIZE); 1217 /* Write version and command */ 1218 isc_buffer_putuint8(outbuf, ver_cmd); 1219 /* Write address family and socket type */ 1220 isc_buffer_putuint8(outbuf, fam_socktype); 1221 /* Write header payload size (addresses + TLVs) */ 1222 isc_buffer_putuint16(outbuf, len); 1223 1224 /* Write source and destination addresses (if we should) */ 1225 if (psrc_addr != NULL) { 1226 isc_buffer_putmem(outbuf, psrc_addr, addr_size); 1227 } 1228 1229 if (pdst_addr != NULL) { 1230 isc_buffer_putmem(outbuf, pdst_addr, addr_size); 1231 } 1232 1233 /* Write source and destination ports (if we should) */ 1234 if (family == ISC_PROXY2_AF_INET || family == ISC_PROXY2_AF_INET6) { 1235 isc_buffer_putuint16(outbuf, isc_sockaddr_getport(src_addr)); 1236 isc_buffer_putuint16(outbuf, isc_sockaddr_getport(dst_addr)); 1237 } 1238 1239 if (tlv_data != NULL) { 1240 isc_buffer_putmem(outbuf, tlv_data->base, tlv_data->length); 1241 } 1242 1243 return ISC_R_SUCCESS; 1244 } 1245 1246 isc_result_t 1247 isc_proxy2_header_append(isc_buffer_t *restrict outbuf, 1248 const isc_region_t *restrict data) { 1249 const size_t len_offset = ISC_PROXY2_HEADER_SIZE - sizeof(uint16_t); 1250 isc_region_t header_data = { 0 }; 1251 uint16_t new_len = 0; 1252 1253 REQUIRE(outbuf != NULL); 1254 1255 isc_buffer_usedregion(outbuf, &header_data); 1256 1257 REQUIRE(header_data.length >= ISC_PROXY2_HEADER_SIZE); 1258 REQUIRE(data != NULL); 1259 1260 if (isc_buffer_availablelength(outbuf) < data->length) { 1261 return ISC_R_NOSPACE; 1262 } else if ((data->length + header_data.length) > UINT16_MAX) { 1263 return ISC_R_RANGE; 1264 } 1265 1266 INSIST(memcmp(header_data.base, ISC_PROXY2_HEADER_SIGNATURE, 1267 ISC_PROXY2_HEADER_SIGNATURE_SIZE) == 0); 1268 1269 /* fixup length of the header payload */ 1270 /* load */ 1271 memmove(&new_len, &header_data.base[len_offset], sizeof(new_len)); 1272 new_len = ntohs(new_len); 1273 /* check */ 1274 if ((data->length + new_len) > UINT16_MAX) { 1275 return ISC_R_RANGE; 1276 } 1277 /* update */ 1278 new_len += (uint16_t)data->length; 1279 /* store */ 1280 new_len = htons(new_len); 1281 memmove(&header_data.base[len_offset], &new_len, sizeof(new_len)); 1282 1283 isc_buffer_putmem(outbuf, data->base, data->length); 1284 1285 return ISC_R_SUCCESS; 1286 } 1287 1288 static inline void 1289 append_type_and_length(isc_buffer_t *restrict outbuf, const uint8_t type, 1290 const uint16_t tlv_length, const bool update_header) { 1291 uint16_t length; 1292 isc_region_t type_region = { 0 }, length_region = { 0 }; 1293 1294 type_region = (isc_region_t){ .base = (uint8_t *)&type, 1295 .length = sizeof(type) }; 1296 length = htons(tlv_length); 1297 length_region = (isc_region_t){ .base = (uint8_t *)&length, 1298 .length = sizeof(length) }; 1299 1300 if (update_header) { 1301 isc_result_t result = isc_proxy2_header_append(outbuf, 1302 &type_region); 1303 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1304 result = isc_proxy2_header_append(outbuf, &length_region); 1305 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1306 } else { 1307 isc_buffer_putmem(outbuf, type_region.base, type_region.length); 1308 isc_buffer_putmem(outbuf, length_region.base, 1309 length_region.length); 1310 } 1311 } 1312 1313 isc_result_t 1314 isc_proxy2_header_append_tlv(isc_buffer_t *restrict outbuf, 1315 const isc_proxy2_tlv_type_t tlv_type, 1316 const isc_region_t *restrict tlv_data) { 1317 size_t new_data_len = 0; 1318 REQUIRE(outbuf != NULL); 1319 REQUIRE(tlv_data != NULL); 1320 1321 /* 1322 * TLV header can be described as follows: 1323 * 1324 * struct { 1325 * uint8_t type; 1326 * uint8_t length_hi; 1327 * uint8_t length_lo; 1328 * }; 1329 * 1330 */ 1331 new_data_len = tlv_data->length + 3; 1332 1333 if (isc_buffer_availablelength(outbuf) < (new_data_len)) { 1334 return ISC_R_NOSPACE; 1335 } else if ((isc_buffer_usedlength(outbuf) + new_data_len) > UINT16_MAX) 1336 { 1337 return ISC_R_RANGE; 1338 } 1339 1340 append_type_and_length(outbuf, (uint8_t)tlv_type, 1341 ((uint16_t)tlv_data->length), true); 1342 1343 if (tlv_data->length > 0) { 1344 isc_result_t result = isc_proxy2_header_append(outbuf, 1345 tlv_data); 1346 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1347 } 1348 1349 return ISC_R_SUCCESS; 1350 } 1351 1352 isc_result_t 1353 isc_proxy2_header_append_tlv_string(isc_buffer_t *restrict outbuf, 1354 const isc_proxy2_tlv_type_t tlv_type, 1355 const char *restrict str) { 1356 isc_result_t result; 1357 isc_region_t region = { 0 }; 1358 1359 REQUIRE(str != NULL && *str != '\0'); 1360 1361 region.base = (uint8_t *)str; 1362 region.length = strlen(str); 1363 1364 result = isc_proxy2_header_append_tlv(outbuf, tlv_type, ®ion); 1365 1366 return result; 1367 } 1368 1369 isc_result_t 1370 isc_proxy2_make_tls_subheader(isc_buffer_t *restrict outbuf, 1371 const uint8_t client_flags, 1372 const bool client_cert_verified, 1373 const isc_region_t *restrict tls_subtlvs_data) { 1374 size_t total_size = ISC_PROXY2_TLS_SUBHEADER_MIN_SIZE; 1375 uint32_t client_cert_not_verified = 1; 1376 REQUIRE(outbuf != NULL); 1377 1378 if (tls_subtlvs_data != NULL) { 1379 total_size += tls_subtlvs_data->length; 1380 } 1381 1382 if (isc_buffer_availablelength(outbuf) < total_size) { 1383 return ISC_R_NOSPACE; 1384 } else if (total_size > UINT16_MAX) { 1385 return ISC_R_RANGE; 1386 } 1387 1388 isc_buffer_putuint8(outbuf, client_flags); 1389 client_cert_not_verified = htonl(!client_cert_verified); 1390 isc_buffer_putmem(outbuf, (uint8_t *)&client_cert_not_verified, 1391 sizeof(client_cert_not_verified)); 1392 1393 if (tls_subtlvs_data != NULL) { 1394 isc_buffer_putmem(outbuf, tls_subtlvs_data->base, 1395 tls_subtlvs_data->length); 1396 } 1397 1398 return ISC_R_SUCCESS; 1399 } 1400 1401 isc_result_t 1402 isc_proxy2_append_tlv(isc_buffer_t *restrict outbuf, const uint8_t type, 1403 const isc_region_t *restrict data) { 1404 size_t new_data_len = 0; 1405 REQUIRE(outbuf != NULL); 1406 REQUIRE(data != NULL); 1407 1408 new_data_len = (data->length + 3); 1409 1410 if (isc_buffer_availablelength(outbuf) < new_data_len) { 1411 return ISC_R_NOSPACE; 1412 } else if ((isc_buffer_usedlength(outbuf) + (data->length + 3)) > 1413 UINT16_MAX) 1414 { 1415 return ISC_R_RANGE; 1416 } 1417 1418 append_type_and_length(outbuf, (uint8_t)type, ((uint16_t)data->length), 1419 false); 1420 1421 if (data->length > 0) { 1422 isc_buffer_putmem(outbuf, data->base, data->length); 1423 } 1424 1425 return ISC_R_SUCCESS; 1426 } 1427 1428 isc_result_t 1429 isc_proxy2_append_tlv_string(isc_buffer_t *restrict outbuf, const uint8_t type, 1430 const char *restrict str) { 1431 isc_result_t result; 1432 isc_region_t region = { 0 }; 1433 1434 REQUIRE(str != NULL && *str != '\0'); 1435 1436 region.base = (uint8_t *)str; 1437 region.length = strlen(str); 1438 1439 result = isc_proxy2_append_tlv(outbuf, type, ®ion); 1440 1441 return result; 1442 } 1443