1 /* $NetBSD: proxy2.h,v 1.2 2025/01/26 16:25:42 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 #pragma once 16 17 #include <isc/buffer.h> 18 #include <isc/mem.h> 19 #include <isc/sockaddr.h> 20 21 /* Definitions taken or derived from the specification */ 22 23 #define ISC_PROXY2_HEADER_SIGNATURE \ 24 ("\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A") 25 26 #define ISC_PROXY2_HEADER_SIGNATURE_SIZE (12) 27 28 #define ISC_PROXY2_HEADER_SIZE \ 29 (ISC_PROXY2_HEADER_SIGNATURE_SIZE + 1 /* version and command */ + \ 30 1 /* protocol and family */ + 2 /* data size */) 31 32 #define ISC_PROXY2_MAX_SIZE (ISC_PROXY2_HEADER_SIZE + UINT16_MAX) 33 34 #define ISC_PROXY2_MIN_AF_INET_SIZE \ 35 (ISC_PROXY2_HEADER_SIZE + 4 /* src_addr */ + 4 /* dst_addr */ + \ 36 2 /* src port */ + 2 /* dst_port */) 37 38 #define ISC_PROXY2_MIN_AF_INET6_SIZE \ 39 (ISC_PROXY2_HEADER_SIZE + 16 /* src_addr */ + 16 /* dst_addr */ + \ 40 2 /* src port */ + 2 /* dst_port */) 41 42 #define ISC_PROXY2_AF_UNIX_MAX_PATH_LEN (108) 43 44 #define ISC_PROXY2_MIN_AF_UNIX_SIZE \ 45 (ISC_PROXY2_HEADER_SIZE + \ 46 ISC_PROXY2_AF_UNIX_MAX_PATH_LEN /* src_addr */ + \ 47 ISC_PROXY2_AF_UNIX_MAX_PATH_LEN /* dst_addr */) 48 49 #define ISC_PROXY2_TLV_HEADER_SIZE \ 50 (1 /* type */ + 1 /* length_hi */ + 1 /* length_lo */) 51 52 #define ISC_PROXY2_TLS_SUBHEADER_MIN_SIZE \ 53 (1 /* client_flags */ + 4 /* verify */) 54 55 ISC_LANG_BEGINDECLS 56 57 typedef enum isc_proxy2_command { 58 ISC_PROXY2_CMD_ILLEGAL = -1, 59 /* 60 * PROXYv2 header does not contain any addresses and is supposedly 61 * created on behalf of locally running software. 62 */ 63 ISC_PROXY2_CMD_LOCAL = 0, 64 /* 65 * PROXYv2 header contains address-related information and is 66 * created on a behalf of the client. 67 */ 68 ISC_PROXY2_CMD_PROXY = 1 69 } isc_proxy2_command_t; 70 71 typedef enum isc_proxy2_addrfamily { 72 ISC_PROXY2_AF_UNSPEC = 0, 73 ISC_PROXY2_AF_INET = 1, 74 ISC_PROXY2_AF_INET6 = 2, 75 ISC_PROXY2_AF_UNIX = 3 76 } isc_proxy2_addrfamily_t; 77 78 typedef enum isc_proxy2_socktype { 79 ISC_PROXY2_SOCK_ILLEGAL = -1, 80 ISC_PROXY2_SOCK_UNSPEC = 0, 81 ISC_PROXY2_SOCK_STREAM = 1, 82 ISC_PROXY2_SOCK_DGRAM = 2 83 } isc_proxy2_socktype_t; 84 85 typedef enum isc_proxy2_tlv_type { 86 /* 87 * Application-Layer Protocol Negotiation (ALPN). It is a byte 88 * sequence defining the upper layer protocol in use over the 89 * connection. 90 */ 91 ISC_PROXY2_TLV_TYPE_ALPN = 0x01, 92 /* 93 * Contains the host name value passed by the client, as an 94 * UTF8-encoded string. 95 */ 96 ISC_PROXY2_TLV_TYPE_AUTHORITY = 0x02, 97 /* 98 * The value is a 32-bit number storing the CRC32c checksum of the 99 * PROXY protocol header. 100 */ 101 ISC_PROXY2_TLV_TYPE_CRC32C = 0x03, 102 /* 103 * The TLV of this type should be ignored when parsed. The value 104 * is zero or more bytes. Can be used for data padding or 105 * alignment. 106 */ 107 ISC_PROXY2_TLV_TYPE_NOOP = 0x04, 108 /* 109 * The value is an opaque byte sequence of up to 128 bytes 110 * generated by the upstream proxy that uniquely identifies the 111 * connection. 112 */ 113 ISC_PROXY2_TLV_TYPE_UNIQUE_ID = 0x05, 114 /* 115 * SSL type contains subfields of the given subtypes (see 116 * isc_proxy2_tlv_subtype_tls_t). The header contains: 117 * 118 * - uint8_t client is a bit-field made of 119 * isc_proxy2_tls_client_flags_t; 120 * - uint32_t verify (0 for a successfully verified certificate); 121 */ 122 ISC_PROXY2_TLV_TYPE_TLS = 0x20, 123 /* 124 * The type PP2_TYPE_NETNS defines the value as the US-ASCII 125 * string representation of the namespace's name. 126 */ 127 ISC_PROXY2_TLV_TYPE_NETNS = 0x30, 128 /* 129 * The following range of 16 type values is reserved for 130 * application-specific data and will be never used by the PROXY 131 * Protocol. 132 */ 133 ISC_PROXY2_TLV_TYPE_MIN_CUSTOM = 0xE0, 134 ISC_PROXY2_TLV_TYPE_MAX_CUSTOM = 0xEF, 135 /* 136 * This range of 8 values is reserved for temporary experimental 137 * use by application developers and protocol designers. 138 */ 139 ISC_PROXY2_TLV_TYPE_MIN_EXPERIMENT = 0xF0, 140 ISC_PROXY2_TLV_TYPE_MAX_EXPERIMENT = 0xF7, 141 /* 142 * The following range of 8 values is reserved for future use, 143 * potentially to extend the protocol with multibyte type values. 144 */ 145 ISC_PROXY2_TLV_TYPE_MIN_FUTURE = 0xF8, 146 ISC_PROXY2_TLV_TYPE_MAX_FUTURE = 0xFF 147 } isc_proxy2_tlv_type_t; 148 149 typedef enum isc_proxy2_tls_client_flags { 150 /* The flag indicates that the client connected over SSL/TLS. */ 151 ISC_PROXY2_CLIENT_TLS = 0x01, 152 /* The client provided a certificate over the current connection. */ 153 ISC_PROXY2_CLIENT_CERT_CONN = 0x02, 154 /* 155 * The client provided a certificate at least once over the TLS 156 * session this connection belongs to. 157 */ 158 ISC_PROXY2_CLIENT_CERT_SESS = 0x04 159 } isc_proxy2_tls_client_flags_t; 160 161 typedef enum isc_proxy2_tlv_subtype_tls { 162 /* 163 * The US-ASCII string representation of the TLS version the TLV 164 * format. 165 */ 166 ISC_PROXY2_TLV_SUBTYPE_TLS_VERSION = 0x21, 167 /* 168 * The Common Name field of the client certificate's Distinguished 169 * Name in the TLV format. 170 */ 171 ISC_PROXY2_TLV_SUBTYPE_TLS_CN = 0x22, 172 /* 173 * The US-ASCII string name of the used cipher, for 174 * example "ECDHE-RSA-AES128-GCM-SHA256". 175 */ 176 ISC_PROXY2_TLV_SUBTYPE_TLS_CIPHER = 0x23, 177 /* 178 * The US-ASCII string name of the algorithm used to sign the 179 * certificate presented by the frontend when the incoming 180 * connection was made over an SSL/TLS transport layer, for 181 * example "SHA256". 182 */ 183 ISC_PROXY2_TLV_SUBTYPE_TLS_SIG_ALG = 0x24, 184 /* 185 * The US-ASCII string name of the algorithm used to generate the 186 * key of the certificate presented by the frontend when the 187 * incoming connection was made over an SSL/TLS transport layer, 188 * for example "RSA2048". 189 */ 190 ISC_PROXY2_TLV_SUBTYPE_TLS_KEY_ALG = 0x25 191 } isc_proxy2_tlv_subtype_tls_t; 192 193 /* 194 * Definitions related to processing and verification of existing PROXYv2 195 * headers 196 */ 197 198 typedef struct isc_proxy2_handler isc_proxy2_handler_t; 199 /*!< 200 * 'isc_proxy2_handler_t' is an entity designed for processing of the 201 * PROXYv2 data received from a network. Despite its purpose, it is 202 * designed as a state machine which, in fact, has no direct connection 203 * to the networking code. Interaction with the networking code is done 204 * via the provided API only. 205 * 206 * The entity is designed as a state machine which accepts data on 207 * input and calls a user-provided data processing callback to notify 208 * about data processing status and, in the case of successful 209 * processing, provide the upper level code with the data obtained 210 * from the PROXYv2 header and associated payload. 211 * 212 * The reason for the state machine-based approach is 213 * many-fold. Firstly, the protocol itself is well suited for 214 * processing by a state machine with well-defined steps. Secondly, 215 * such a design allows iterative data processing combined with 216 * verification, which is more secure than trying to read seemingly 217 * enough data, process it, and then retrospectively verify 218 * it. Thirdly, such an approach aligns well with how stream-based 219 * transports work - PROXYv2 headers might arrive torn into multiple 220 * parts which need to be assembled (theoretically, it is fine to send 221 * data over TCP bite-by-bite), and we should handle such 222 * cases. Additionally to that, we should stop reading data as soon as 223 * we detect that it is ill-formed. This design allows that and also 224 * can be used easily with datagram-based networking code. 225 * 226 * Another important characteristic of the state machine-based code is 227 * that it can be unit-tested separately from the rest of the code 228 * base. Of course, we use that to our advantage. 229 * 230 * The implementations closely follows the PROXYv2 protocol 231 * specification from 2020/03/05 232 * (https://www.haproxy.org/download/2.9/doc/proxy-protocol.txt), 233 * however, enough functionality is provided to handle future 234 * extensions, too. To be fair, our needs are quite modest and we are 235 * not interested in all the information PROXYv2 protocol could carry 236 * - we are mostly interested in the basics. However, our protocol 237 * handling code is fairly complete at the time of writing leaving a 238 * good foundation for further extensions, as the PROXYv2 protocol is 239 * itself extensible. The only missing thing is header checksum 240 * verification - but that functionality is optional. That being said, it is 241 * easy to add that, should we ever need to. 242 */ 243 244 typedef void (*isc_proxy2_handler_cb_t)(const isc_result_t result, 245 const isc_proxy2_command_t cmd, 246 const int socktype, 247 const isc_sockaddr_t *restrict src_addr, 248 const isc_sockaddr_t *restrict dst_addr, 249 const isc_region_t *restrict tlv_data, 250 const isc_region_t *restrict extra, 251 void *cbarg); 252 /*!< 253 * PROXYv2 data processing callback. 254 * 255 * Arguments: 256 *\li 'result' - error status code; 257 *\li 'cmd' - PROXYv2 command; 258 *\li 'socktype' - PROXYv2 addresses socket type 259 *(SOCK_STREAM, SOCK_DGRAM, or '0' for "unspecified" (SOCK_UNSPEC)). 260 *\li 'src_addr' - original source address extracted from the PROXYv2 header; 261 *\li 'dst_addr' - original destination address extracted from the PROXYv2 262 *header; 263 *\li 'tlv_data' - TLV-data extracted from the header; 264 *\li 'extra_data' - extra unprocessed data past the PROXYv2 header. It is 265 *not a part of the header, but it is fine to receive this when reading data 266 *over TCP-based transports. In general, needs to be passed to the upper 267 *level as is; 268 *\li 'cbarg' - opaque pointer to user supplied data. 269 * 270 * The user-provided data processing callback function can get the 271 * following error status codes: 272 * \li 'ISC_R_SUCCESS' - the header has been processed, and data has been 273 * extracted from the received header and its payload; 274 * \li 'ISC_R_NOMORE' - the data passed was processed, and we need more to 275 * continue processing (=resume reading from the network as we have no more 276 * data to process); 277 * \li 'ISC_R_UNEXPECTED' - an unexpected value has been detected; 278 * \li 'ISC_R_RANGE' - an expected value is not within an expected range. 279 * 280 * When processing error status within the callback, in general, we 281 * are interested in dispatching on the first two values, as anything 282 * else can be treated as hard-stop errors: their purpose is to give a 283 * little insight into what has happened without going into gory 284 * details (as we are not interested in them most of the time anyway). 285 * 286 * Any of the argument pointers can be 'NULL', identifying that the 287 * corresponding data is not present in the PROXYv2 header. Also, 288 * 'socktype' can be '-1' in a case of processing error. 289 * 290 */ 291 292 struct isc_proxy2_handler { 293 isc_buffer_t hdrbuf; /*!< Internal buffer for assembling PROXYv2 header 294 */ 295 uint8_t buf[256]; /*!< Internal buffer static storage */ 296 297 int state; /*!< Current state machine state */ 298 uint16_t expect_data; /*!< How much data do we need to switch to the 299 next state */ 300 uint16_t max_size; /*!< Max PROXYv2 header size including its payload */ 301 302 isc_proxy2_handler_cb_t cb; /*!< Data processing callback. */ 303 void *cbarg; /*!< Callback argument. */ 304 bool calling_cb; /*<! Callback calling marker. Used to detect recursive 305 object uses (changing the data state from within 306 the callback). */ 307 isc_result_t result; /*<! The last passed to the callback processing 308 status value. */ 309 isc_mem_t *mctx; 310 311 uint16_t header_size; /*!< Total PROXYv2 header size (including the 312 payload. */ 313 uint16_t tlv_data_size; /*!< The size of TLVs payload size */ 314 315 isc_proxy2_command_t cmd; /*!< The decoded PROXYv2 command */ 316 isc_proxy2_addrfamily_t proxy_addr_family; /*!< The decoded PROXYv2 317 address family */ 318 isc_proxy2_socktype_t proxy_socktype; /*!< The decoded PROXYv2 socket 319 type */ 320 321 isc_region_t tlv_data; /*!< TLV data region within the handled PROXYv2 322 header */ 323 isc_region_t extra_data; /*!< Data past the PROXYv2 header (not 324 belonging to it) */ 325 }; 326 327 void 328 isc_proxy2_handler_init(isc_proxy2_handler_t *restrict handler, isc_mem_t *mctx, 329 const uint16_t max_size, isc_proxy2_handler_cb_t cb, 330 void *cbarg); 331 /*!< 332 * \brief Initialise the given 'isc_proxy2_handler_t' object, attach 333 * to the memory context. 334 * 335 * Arguments: 336 *\li 'mctx' - memory context; 337 *\li 'max_size' - the upper limit for the PROXYv2 header and its payload (0 - 338 *unlimited); 339 *\li 'cb' - data processing callback; 340 *\li 'cbarg' - data processing callback argument. 341 * 342 * Requires: 343 *\li 'handler' is not NULL; 344 *\li 'mctx' is not NULL; 345 *\li 'max_size' is >= `ISC_PROXY2_HEADER_SIZE` or is 0; 346 *\li 'cb' is not NULL. 347 */ 348 349 void 350 isc_proxy2_handler_uninit(isc_proxy2_handler_t *restrict handler); 351 /*!< 352 * \brief Un-initialise the given 'isc_proxy2_handler_t' object, detach 353 * from the attached memory context. Invalidate any internal unprocessed data. 354 * 355 * Requires: 356 *\li 'handler' is not NULL. 357 */ 358 359 void 360 isc_proxy2_handler_clear(isc_proxy2_handler_t *restrict handler); 361 /*!< 362 * \brief Clear the given 'isc_proxy2_handler_t' object from 363 * any unprocessed data, clear the last data processing status (set it to 364 * 'ISC_R_UNSET'). Effectively, the function returns the object to its initial 365 * state. 366 * 367 * Requires: 368 *\li 'handler' is not NULL. 369 */ 370 371 isc_proxy2_handler_t * 372 isc_proxy2_handler_new(isc_mem_t *mctx, const uint16_t max_size, 373 isc_proxy2_handler_cb_t cb, void *cbarg); 374 /*!< 375 * \brief Allocate and initialise a new 'isc_proxy2_handler_t' 376 * object, attach to the memory context. 377 * 378 * Arguments: 379 *\li 'mctx' - memory context; 380 *\li 'max_size' - the upper limit for the PROXYv2 header and its payload (0 - 381 *unlimited); 382 *\li 'cb' - data processing callback; 383 *\li 'cbarg' - data 384 *processing callback argument. 385 * 386 * Requires: 387 *\li 'mctx' is not NULL; 388 *\li 'max_size' is >= `ISC_PROXY2_HEADER_SIZE` or is 0; 389 *\li 'cb' is not NULL. 390 */ 391 392 void 393 isc_proxy2_handler_free(isc_proxy2_handler_t **restrict handler); 394 /*!< 395 * \brief Un-initialise the given 'isc_proxy2_handler_t' object, detach 396 * from the attached memory context, free the memory consumed by the object. 397 * 398 * Requires: 399 *\li 'handler' is not NULL; 400 *\li 'handler' is not pointing to NULL. 401 */ 402 403 void 404 isc_proxy2_handler_setcb(isc_proxy2_handler_t *restrict handler, 405 isc_proxy2_handler_cb_t cb, void *cbarg); 406 /*!< 407 * \brief Change the data processing callback and its argument within the 408 * given 'isc_proxy2_handler_t' object. 409 * 410 * Arguments: 411 *\li 'handler' - PROXYv2 handler object; 412 *\li 'cb' - new data processing callback; 413 *\li 'cbarg' - new data processing callback argument. 414 * 415 * Requires: 416 *\li 'handler' is not NULL; 417 *\li 'cb' is not NULL. 418 */ 419 420 isc_result_t 421 isc_proxy2_handler_push_data(isc_proxy2_handler_t *restrict handler, 422 const void *restrict buf, 423 const unsigned int buf_size); 424 /*!< 425 * \brief Push new data to the given 'isc_proxy2_handler_t' 426 * object. Call the callback passing a status and a result of data 427 * processing to it. 428 * 429 * To avoid erroneously recursive usage of the object, it is forbidden to call 430 * this function from within the callback. Doing so will abort the program. 431 * 432 * Requires: 433 *\li 'handler' is not NULL; 434 *\li 'buf' is not NULL; 435 *\li 'buf_size' is not 0. 436 */ 437 438 isc_result_t 439 isc_proxy2_handler_push(isc_proxy2_handler_t *restrict handler, 440 const isc_region_t *restrict region); 441 /*!< 442 * \brief The same as 'isc_proxy2_handler_push_data()' but pushes that 443 * data for processing via an 'isc_region_t' object. 444 * 445 * Requires: 446 *\li 'handler' is not NULL; 447 *\li 'region' is not NULL. 448 */ 449 450 isc_result_t 451 isc_proxy2_handler_result(const isc_proxy2_handler_t *restrict handler); 452 /*!< 453 * \brief Return the last data processing status passed to the 454 * callback. 455 * 456 * Requires: 457 *\li 'handler' is not NULL. 458 * 459 * Return values: 460 * \li 'ISC_R_SUCCESS' - the header has been processed, and data has been 461 * extracted from the received header and its payload; 462 * \li 'ISC_R_NOMORE' - the data passed was processed, and we need more to 463 * continue processing (=resume reading from the network as we have no more 464 * data to process); 465 * \li 'ISC_R_UNEXPECTED' - an unexpected value has been detected; 466 * \li 'ISC_R_RANGE' - an expected value is not within an expected range. 467 */ 468 469 size_t 470 isc_proxy2_handler_header(const isc_proxy2_handler_t *restrict handler, 471 isc_region_t *restrict region); 472 /*!< 473 * \brief Get the complete processed PROXYv2 header as is 474 * (e.g. for forwarding). 475 * 476 * Requires: 477 *\li 'handler' is not NULL; 478 *\li 'region' is NULL or points to a zeroed 'isc_region_t' object. 479 * 480 * Return the size of the header or 0 on error (if it has not been 481 * processed yet). 482 */ 483 484 size_t 485 isc_proxy2_handler_tlvs(const isc_proxy2_handler_t *restrict handler, 486 isc_region_t *restrict region); 487 /*!< 488 * \brief Get the TLV-data within the processed PROXYv2 header. 489 * 490 * Requires: 491 *\li 'handler' is not NULL; 492 *\li 'region' is NULL or points to a zeroed 'isc_region_t' object. 493 * 494 * Return the size of the header or 0 on error (if it has not been 495 * processed yet). 496 */ 497 498 size_t 499 isc_proxy2_handler_extra(const isc_proxy2_handler_t *restrict handler, 500 isc_region_t *restrict region); 501 /*!< 502 * \brief Get the data past the processed PROXYv2 header. The data 503 * is not the part of the PROXYv2 header itself. That can happen (and 504 * does happen) when data is being sent over TCP. 505 * 506 * Requires: 507 *\li 'handler' is not NULL; 508 *\li 'region' is NULL or points to a zeroed 'isc_region_t' object. 509 * 510 * Return the size of the header or 0 on error (if it has not been 511 * processed yet). 512 */ 513 514 isc_result_t 515 isc_proxy2_handler_addresses(const isc_proxy2_handler_t *restrict handler, 516 int *restrict psocktype, 517 isc_sockaddr_t *restrict psrc_addr, 518 isc_sockaddr_t *restrict pdst_addr); 519 /*!< 520 * \brief Get the addresses directly from the processed PROXYv2 521 * header. If you are not interested in particular data, you can pass 522 * NULL as the argument to ignore it. 523 * 524 * Requires: 525 *\li 'handler' is not NULL. 526 */ 527 528 isc_result_t 529 isc_proxy2_header_handle_directly(const isc_region_t *restrict header_data, 530 const isc_proxy2_handler_cb_t cb, 531 void *cbarg); 532 /*!< 533 * \brief Process PROXYv2 header in one go directly without memory 534 * allocation and copying. Specifically designed to work when a 535 * complete header and associated follow-up data is expected (for 536 * example, when datagram transports are used, like UDP). 537 * 538 * Requires: 539 *\li 'header_data' is not NULL; 540 *\li 'cb' is not NULL. 541 * 542 * Return values are the same that get passed to the processing 543 * callback. Given that processing should complete in one go, getting 544 * anything except `ISC_R_SUCCESS` indicates failure. 545 */ 546 547 typedef bool (*isc_proxy2_tlv_cb_t)(const isc_proxy2_tlv_type_t tlv_type, 548 const isc_region_t *restrict data, 549 void *cbarg); 550 /*!< 551 * \brief Callback used for iterating over TLV data extracted from 552 * PROXYv2 headers. 553 * 554 * Arguments: 555 *\li 'tlv_type' - type value (see the 'isc_proxy2_tlv_type_t' enumeration); 556 *\li 'data' - pointer to 'isc_region_t' object referring to the data; 557 *\li 'cbarg' - opaque pointer to user supplied data. 558 * 559 * Return values: 560 *\li 'true' - continue processing the next TLV entry (if any); 561 *\li 'false' - stop processing TLV-entries. 562 */ 563 564 isc_result_t 565 isc_proxy2_tlv_iterate(const isc_region_t *restrict tlv_data, 566 const isc_proxy2_tlv_cb_t cb, void *cbarg); 567 /*!< 568 * \brief Iterate over the TLV data extracted from PROXYv2 headers. 569 * 570 * Arguments: 571 *\li 'tlv_data' - TLV data extracted from a PROXYv2 header; 572 *\li 'cb' - user provided iteration callback; 573 *\li 'cbarg' - user provided iteration callback argument. 574 * 575 * Requires: 576 *\li 'tlv_data' is not NULL; 577 *\li 'cb' is not NULL. 578 * 579 * Return values: 580 *\li 'ISC_R_SUCCESS' - iteration over the data was successful; 581 *\li 'ISC_R_RANGE' - malformed TLV data was detected. 582 */ 583 584 typedef bool (*isc_proxy2_tls_subtlv_cb_t)( 585 const uint8_t client_flags, const bool client_cert_verified, 586 const isc_proxy2_tlv_subtype_tls_t tls_subtlv_type, 587 const isc_region_t *restrict data, void *cbarg); 588 /*!< 589 * \brief Callback used for iterating over TLS sub-TLV data extracted from 590 * PROXYv2 headers. 591 * 592 * Arguments: 593 *\li 'client_flags' - TLS client flags extracted from TLS TLV data 594 * (see 'isc_proxy2_tls_client_flags_t' enumeration); 595 *\li 'client_cert_verified' - flag which indicates if the supplied 596 *TLS client certificate was verified- (if provided by the client); 597 *\li 'tls_subtlv_type' - TLS sub-TLV type (see the 598 *'isc_proxy2_tlv_subtype_tls_t' enumeration); 599 *\li 'cbarg' - opaque pointer to user supplied data. 600 * 601 * Return values: 602 *\li 'true' - continue processing the next TLV entry (if any); 603 *\li 'false' - stop processing TLV-entries. 604 */ 605 606 isc_result_t 607 isc_proxy2_subtlv_tls_header_data(const isc_region_t *restrict tls_tlv_data, 608 uint8_t *restrict pclient_flags, 609 bool *restrict pclient_cert_verified); 610 /*!< 611 * \brief Get data from a TLS ('ISC_PROXY2_TLV_TYPE_TLS') TLV value. 612 * 613 * Arguments: 614 *\li 'pclient_flags' - a pointer to the variable to receive the TLS client 615 *flags (see 'isc_proxy2_tls_client_flags_t' enumeration for more details); 616 *\li 'pclient_cert_verified' - a pointer the value to receive TLS client 617 *certificate verification status ('true' - verified). 618 * 619 * Requires: 620 *\li 'tls_tlv_data' is not NULL; 621 *\li 'pclient_flags' is either NULL or a pointer pointing to a 622 *zeroed variable; 623 *\li 'pclient_cert_verified' is either NULL or a pointer pointing to a 624 *zeroed variable. 625 * 626 * Return values: 627 *\li 'ISC_R_SUCCESS' - iteration over the data was successful; 628 *\li 'ISC_R_RANGE' - malformed TLV data was detected. 629 */ 630 631 isc_result_t 632 isc_proxy2_subtlv_tls_iterate(const isc_region_t *restrict tls_tlv_data, 633 const isc_proxy2_tls_subtlv_cb_t cb, void *cbarg); 634 /*!< 635 * \brief Iterate over the sub-TLV data extracted from TLS 636 * ('ISC_PROXY2_TLV_TYPE_TLS') TLV value of a PROXYv2 header. 637 * 638 * Arguments: 639 *\li 'tls_tlv_data' - TLS-realted sub-TLV data extracted from 640 *a PROXYv2 header; 641 *\li 'cb' - user provided iteration callback; 642 *\li 'cbarg' - user provided iteration callback argument. 643 * 644 * Requires: 645 *\li 'tls_tlv_data' is not NULL; 646 *\li 'cb' is not NULL. 647 * 648 * Return values: 649 *\li 'ISC_R_SUCCESS' - iteration over the data was successful; 650 *\li 'ISC_R_RANGE' - malformed TLV data was detected. 651 */ 652 653 isc_result_t 654 isc_proxy2_tlv_data_verify(const isc_region_t *restrict tlv_data); 655 /*!< 656 * \brief Verify TLV-data structure extracted from a PROXYv2 header. 657 * The function loops over the data verifying that TLVs are structured 658 * in a correct way. 659 * 660 * NOTE: If you are using an 'isc_proxy2_handler_t' object then there 661 * is no need for you to call this function as it is called during 662 * the normal operation. It is exposed mostly for unit testing 663 * purposes or for verifying outgoing data, should it be required. 664 * 665 * Arguments: 666 *\li 'tlv_data' - TLV data extracted from a PROXYv2 header. 667 * 668 * Requires: 669 *\li 'tlv_data' is not NULL. 670 * 671 * Return values: 672 *\li 'ISC_R_SUCCESS' - iteration over the data was successful; 673 *\li 'ISC_R_RANGE' - malformed TLV data was detected. 674 */ 675 676 /* 677 * Definitions related to generation of PROXYv2 headers 678 */ 679 680 isc_result_t 681 isc_proxy2_make_header(isc_buffer_t *restrict outbuf, 682 const isc_proxy2_command_t cmd, const int socktype, 683 const isc_sockaddr_t *restrict src_addr, 684 const isc_sockaddr_t *restrict dst_addr, 685 const isc_region_t *restrict tlv_data); 686 /*!< 687 * \brief Create a PROXYv2 header. 688 * 689 * Arguments: 690 *\li 'outbuf' - the output buffer; 691 *\li 'cmd' - PROXYv2 command; 692 *\li 'socktype' - PROXYv2 socket type (possible values are 'SOCK_STREAM', 693 *'SOCK_DGRAM', or '0' for "unspecified"); 694 *\li 'src_addr' - source address, if any; 695 *\li 'dst_addr' - destination address, if any; 696 *\li 'tlv_data' - TLV data, if any. 697 * 698 * Requires: 699 *\li 'outbuf' is not NULL; 700 *\li 'cmd' is 'ISC_PROXY2_CMD_PROXY' or 'socktype' is equal to '0'; 701 *\li either both of 'src_addr' and 'dst_addr' are NULL or both are not; 702 *\li both of 'src_addr' and 'dst_addr' are of the same type when specified. 703 * 704 * Notes: 705 * 706 * When 'cmd' equals 'ISC_PROXY2_CMD_LOCAL', then 'socktype' must equal '0' 707 * (unspecified) and both 'src_addr' and 'dst_addr' must be 'NULL'. 708 * When 'cmd' equals 'ISC_PROXY2_CMD_PROXY', then having 'socktype' being equal 709 * to '0' will instruct the function to create PROXYv2 header marked as bearing 710 * address of "unspecified" ('0') opaque type. In this case both 'src_addr' and 711 * 'dst_addr' must be 'NULL'. In other cases the address type is determined 712 * from the 'src_addr' and 'dst_addr' arguments (and might 'AF_INET', 713 * 'AF_INET6', and 'AF_UNIX' per the protocol spec). 714 * The socket type, when applicable, is determined from the 'socktype' argument 715 * and must be any of 'SOCK_STREAM', 'SOCK_DGRAM', when applicable, or '0' 716 * (unspecified). 717 * 718 * Return values: 719 *\li 'ISC_R_SUCCESS' - iteration over the data was successful; 720 *\li 'ISC_R_UNEXPECTED' - an unexpected value has been detected in the input 721 *data (function arguments); 722 *\li 'ISC_R_NOSPACE' - not enough data in the output buffer; 723 *\li 'ISC_R_RANGE' - too much data to fit PROXYv2 header. 724 */ 725 726 isc_result_t 727 isc_proxy2_header_append(isc_buffer_t *restrict outbuf, 728 const isc_region_t *restrict data); 729 /*!< 730 * \brief Append arbitrary data to PROXYv2 header and update the 731 * length field within the header accordingly. It is used as foundation 732 * for TLV appending functionality. Also, it can be used to add address 733 * information in the case when "unspecified" opaque format is used. 734 * 735 * Arguments: 736 *\li 'outbuf' - the output buffer containing a valid PROXYv2 header; 737 *\li 'data' - use provided arbitrary data. 738 * 739 * Requires: 740 *\li 'outbuf' is not NULL; 741 *\li used region within 'outbuf' is more or equal 742 *to 'ISC_PROXY2_HEADER_SIZE'; 743 *\li 'data' is not NULL. 744 * 745 * Return values: 746 *\li 'ISC_R_SUCCESS' - iteration over the data was successful; 747 *\li 'ISC_R_NOSPACE' - not enough data in the output buffer; 748 *\li 'ISC_R_RANGE' - too much data for PROXYv2 header. 749 */ 750 751 isc_result_t 752 isc_proxy2_header_append_tlv(isc_buffer_t *restrict outbuf, 753 const isc_proxy2_tlv_type_t tlv_type, 754 const isc_region_t *restrict data); 755 /*!< 756 * \brief Append TLV data to PROXYv2 header and update the 757 * length field within the header accordingly. 758 * 759 * Requires: 760 *\li 'outbuf' is not NULL; 761 *\li used region within 'outbuf' is more or equal 762 *to 'ISC_PROXY2_HEADER_SIZE'; 763 *\li 'data' is not NULL. 764 * 765 * Return values: 766 *\li 'ISC_R_SUCCESS' - iteration over the data was successful; 767 *\li 'ISC_R_NOSPACE' - not enough data in the output buffer 768 *\li 'ISC_R_RANGE' - too much data for PROXYv2 header. 769 */ 770 771 isc_result_t 772 isc_proxy2_header_append_tlv_string(isc_buffer_t *restrict outbuf, 773 const isc_proxy2_tlv_type_t tlv_type, 774 const char *restrict str); 775 /*!< 776 * \brief Append the string as TLV data to PROXYv2 header and update the 777 * length field within the header accordingly. 778 * 779 * Requires: 780 *\li 'outbuf' is not NULL; 781 *\li used region within 'outbuf' is more or equal 782 *to 'ISC_PROXY2_HEADER_SIZE'; 783 *\li 'data' is not NULL. 784 * 785 * Return values: 786 *\li 'ISC_R_SUCCESS' - iteration over the data was successful; 787 *\li 'ISC_R_NOSPACE' - not enough data in the output buffer. 788 *\li 'ISC_R_RANGE' - too much data for PROXYv2 header. 789 */ 790 791 isc_result_t 792 isc_proxy2_make_tls_subheader(isc_buffer_t *restrict outbuf, 793 const uint8_t client_flags, 794 const bool client_cert_verified, 795 const isc_region_t *restrict tls_subtlvs_data); 796 /*!< 797 * \brief Create TLS (ISC_PROXY2_TLV_TYPE_TLS) TLV subheader which 798 * can later be added to the PROXYv2 header TLV data. 799 * 800 * Arguments: 801 *\li 'client_flags' - TLS client flags (see 802 'isc_proxy2_tls_client_flags_t' enumeration for more details); 803 *\li 'client_cert_verified' - TLS client certificate verification 804 *status ('true' - verified). 805 *\li 'tls_subtlvs_data' - TLS subtlvs data, if any (see 806 'isc_proxy2_tlv_subtype_tls_t' for more details). 807 * 808 * Requires: 809 *\li 'outbuf' is not NULL; 810 * 811 * Return values: 812 *\li 'ISC_R_SUCCESS' - iteration over the data was successful; 813 *\li 'ISC_R_NOSPACE' - not enough data in the output buffer; 814 *\li 'ISC_R_RANGE' - too much data for a TLV value. 815 */ 816 817 isc_result_t 818 isc_proxy2_append_tlv(isc_buffer_t *restrict outbuf, const uint8_t type, 819 const isc_region_t *restrict data); 820 /*!< 821 * \brief Append TLV data to the end of the buffer. Compared to 822 * 'isc_proxy2_header_append_tlv()' it does not try to look for a 823 * correct PROXYv2 header at the beginning of the buffer and update 824 * its length field. The main purpose of this function is to work with 825 * sub-TLVs. 826 * 827 * Requires: 828 *\li 'outbuf' is not NULL; 829 *\li 'data' is not NULL. 830 * 831 * Return values: 832 *\li 'ISC_R_SUCCESS' - iteration over the data was successful; 833 *\li 'ISC_R_NOSPACE' - not enough data in the output buffer 834 *\li 'ISC_R_RANGE' - too much data for PROXYv2 header. 835 */ 836 837 isc_result_t 838 isc_proxy2_append_tlv_string(isc_buffer_t *restrict outbuf, const uint8_t type, 839 const char *restrict str); 840 /*!< 841 * \brief Append the string as TLV data to the end of the 842 * buffer. Compared to 'isc_proxy2_header_append_tlv_string()' it does not 843 * try to look for a correct PROXYv2 header at the beginning of the 844 * buffer and update its length field. The main purpose of this 845 * function is to work with sub-TLVs. 846 * 847 * Requires: 848 *\li 'outbuf' is not NULL; 849 *\li 'data' is not NULL. 850 * 851 * Return values: 852 *\li 'ISC_R_SUCCESS' - iteration over the data was successful; 853 *\li 'ISC_R_NOSPACE' - not enough data in the output buffer 854 *\li 'ISC_R_RANGE' - too much data for PROXYv2 header. 855 */ 856 857 ISC_LANG_ENDDECLS 858