idnits 2.17.1 draft-ietf-curdle-ssh-ext-info-15.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- -- The draft header indicates that this document updates RFC4254, but the abstract doesn't seem to directly say this. It does mention RFC4254 though, so this could be OK. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year == Line 164 has weird spacing: '... string exte...' == Line 165 has weird spacing: '... string exte...' == Line 244 has weird spacing: '...me-list publ...' == Line 287 has weird spacing: '...me-list com...' == Line 288 has weird spacing: '...me-list com...' (Using the creation date from RFC4252, updated by this document, for RFC5378 checks: 1997-03-26) -- The document seems to lack a disclaimer for pre-RFC5378 work, but may have content which was first submitted before 10 November 2008. If you have contacted all the original authors and they are all willing to grant the BCP78 rights to the IETF Trust, then this is fine, and you can ignore this comment. If not, you may need to add the pre-RFC5378 disclaimer. (See the Legal Provisions document at https://trustee.ietf.org/license-info for more information.) -- The document date (September 23, 2017) is 2369 days in the past. Is this intentional? Checking references for intended status: Proposed Standard ---------------------------------------------------------------------------- (See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs) == Outdated reference: A later version (-12) exists of draft-ietf-curdle-rsa-sha2-10 Summary: 0 errors (**), 0 flaws (~~), 7 warnings (==), 3 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 Internet-Draft D. Bider 3 Updates: 4252, 4253, 4254 (if approved) Bitvise Limited 4 Intended status: Standards Track September 23, 2017 5 Expires: March 23, 2018 7 Extension Negotiation in Secure Shell (SSH) 8 draft-ietf-curdle-ssh-ext-info-15.txt 10 Abstract 12 This memo updates RFC 4252, RFC 4253, and RFC 4254 to define a 13 mechanism for SSH clients and servers to exchange information about 14 supported protocol extensions confidentially after SSH key exchange. 16 Status 18 This Internet-Draft is submitted in full conformance with the 19 provisions of BCP 78 and BCP 79. 21 Internet-Drafts are working documents of the Internet Engineering Task 22 Force (IETF), its areas, and its working groups. Note that other 23 groups may also distribute working documents as Internet-Drafts. 25 Internet-Drafts are draft documents valid for a maximum of six months 26 and may be updated, replaced, or obsoleted by other documents at any 27 time. It is inappropriate to use Internet-Drafts as reference material 28 or to cite them other than as "work in progress." 30 The list of current Internet-Drafts can be accessed at 31 http://www.ietf.org/1id-abstracts.html 33 The list of Internet-Draft Shadow Directories can be accessed at 34 http://www.ietf.org/shadow.html 36 Copyright 38 Copyright (c) 2017 IETF Trust and the persons identified as the 39 document authors. All rights reserved. 41 This document is subject to BCP 78 and the IETF Trust's Legal 42 Provisions Relating to IETF Documents 43 (http://trustee.ietf.org/license-info) in effect on the date of 44 publication of this document. Please review these documents 45 carefully, as they describe your rights and restrictions with respect 46 to this document. Code Components extracted from this document must 47 include Simplified BSD License text as described in Section 4.e of 48 the Trust Legal Provisions and are provided without warranty as 49 described in the Simplified BSD License. 51 Table of Contents 53 1. Overview and Rationale ...........................................3 54 1.1. Requirements Terminology ...................................3 55 1.2. Wire Encoding Terminology ..................................3 56 2. Extension Negotiation Mechanism ..................................3 57 2.1. Signaling of Extension Negotiation in SSH_MSG_KEXINIT .......3 58 2.2. Enabling Criteria ...........................................4 59 2.3. SSH_MSG_EXT_INFO Message ....................................4 60 2.4. Message Order ...............................................4 61 2.5. Interpretation of Extension Names and Values ................5 62 3. Initially Defined Extensions .....................................6 63 3.1. "server-sig-algs" ...........................................6 64 3.2. "delay-compression" .........................................7 65 3.2.1. Awkwardly Timed Key Re-Exchange ......................8 66 3.2.2. Subsequent Re-Exchange ...............................8 67 3.2.3. Compatibility Note: OpenSSH up to 7.5 ................8 68 3.3. "no-flow-control" ...........................................9 69 3.3.1. Prior "No Flow Control" Practice .....................9 70 3.4. "elevation" ................................................10 71 4. IANA Considerations .............................................11 72 4.1. Additions to existing tables ...............................11 73 4.2. New table: Extension Names .................................11 74 4.2.1. Future Assignments to Extension Names ...............11 75 5. Security Considerations .........................................11 76 6. References ......................................................12 77 6.1. Normative References .......................................12 78 6.2. Informative References .....................................12 79 Author's Address ...................................................13 80 Acknowledgments ....................................................13 82 1. Overview and Rationale 84 Secure Shell (SSH) is a common protocol for secure communication on 85 the Internet. The original design of the SSH transport layer [RFC4253] 86 lacks proper extension negotiation. Meanwhile, diverse implementations 87 take steps to ensure that known message types contain no unrecognized 88 information. This makes it difficult for implementations to signal 89 capabilities and negotiate extensions without risking disconnection. 90 This obstacle has been recognized in relationship with [SSH-RSA-SHA2], 91 where the need arises for a client to discover public key algorithms a 92 server accepts, to avoid authentication penalties and trial-and-error. 94 This memo updates RFC 4252, RFC 4253, and RFC 4254. 96 1.1. Requirements Terminology 98 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 99 "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this 100 document are to be interpreted as described in [RFC2119]. 102 1.2. Wire Encoding Terminology 104 The wire encoding types in this document - "byte", "uint32", "string", 105 "boolean", "name-list" - have meanings as described in [RFC4251]. 107 2. Extension Negotiation Mechanism 109 2.1. Signaling of Extension Negotiation in SSH_MSG_KEXINIT 111 Applications implementing this mechanism MUST add one of the following 112 indicator names to the field "kex_algorithms" in the SSH_MSG_KEXINIT 113 message sent by the application in the first key exchange: 115 - When acting as server: "ext-info-s" 116 - When acting as client: "ext-info-c" 118 The indicator name is added without quotes, and MAY be added at any 119 position in the name-list, subject to proper separation from other 120 names as per name-list conventions. 122 The names are added to the "kex_algorithms" field because this is one 123 of two name-list fields in SSH_MSG_KEXINIT that do not have a separate 124 copy for each data direction. 126 The indicator names inserted by the client and server are different to 127 ensure these names will not produce a match, and therefore not affect 128 the algorithm chosen in key exchange algorithm negotiation. 130 The inclusion of textual indicator names is intended to provide a clue 131 for implementers to discover this mechanism. 133 2.2. Enabling Criteria 135 If a client or server offers "ext-info-c" or "ext-info-s" 136 respectively, it MUST be prepared to accept an SSH_MSG_EXT_INFO 137 message from the peer. 139 A server only needs to send "ext-info-s" if it intends to process 140 SSH_MSG_EXT_INFO from the client. A client only needs to send 141 "ext-info-c" if it plans to process SSH_MSG_EXT_INFO from the server. 143 If a server receives an "ext-info-c", or a client receives an 144 "ext-info-s", it MAY send an SSH_MSG_EXT_INFO message, but is not 145 required to do so. 147 Neither party needs to wait for the other's SSH_MSG_KEXINIT in order 148 to decide whether to send the appropriate indicator in its own 149 SSH_MSG_KEXINIT. 151 Implementations MUST NOT send an incorrect indicator name for their 152 role. Implementations MAY disconnect if the counter-party sends an 153 incorrect indicator. If "ext-info-c" or "ext-info-s" ends up being 154 negotiated as a key exchange method, the parties MUST disconnect. 156 2.3. SSH_MSG_EXT_INFO Message 158 A party that received the "ext-info-c" or "ext-info-s" indicator 159 MAY send the following message: 161 byte SSH_MSG_EXT_INFO (value 7) 162 uint32 nr-extensions 163 repeat the following 2 fields "nr-extensions" times: 164 string extension-name 165 string extension-value (binary) 167 Implementers' attention is called to Section 2.5., in particular the 168 requirement to tolerate any sequence of bytes - including null bytes 169 at any position - in an unknown extension's extension-value. 171 2.4. Message Order 173 If a client sends SSH_MSG_EXT_INFO, it MUST send it as the next packet 174 following the client's first SSH_MSG_NEWKEYS message to the server. 176 If a server sends SSH_MSG_EXT_INFO, it MAY send it at zero, one, or 177 both of the following opportunities: 179 - As the next packet following the server's first SSH_MSG_NEWKEYS. 181 Where clients need information in the server's SSH_MSG_EXT_INFO to 182 authenticate, it is helpful if the server sends its SSH_MSG_EXT_INFO 183 not only as next packet after SSH_MSG_NEWKEYS, but without delay. 185 Clients cannot rely on this because the server is not required to 186 send the message at this time; and if sent, it may be delayed by 187 the network. However, if a timely SSH_MSG_EXT_INFO is received, 188 a client can pipeline an authentication request after its 189 SSH_MSG_SERVICE_REQUEST, even when it needs extension information. 191 - Immediately preceding the server's SSH_MSG_USERAUTH_SUCCESS, as 192 defined in [RFC4252]. 194 The server MAY send SSH_MSG_EXT_INFO at this second opportunity, 195 whether or not it sent it at the first. A client that sent 196 "ext-info-c" MUST accept a server's SSH_MSG_EXT_INFO at both 197 opportunities, but MUST NOT require it. 199 This allows a server to reveal support for additional extensions 200 that it was unwilling to reveal to an unauthenticated client. If a 201 server sends a second SSH_MSG_EXT_INFO, this replaces any initial 202 one, and both the client and the server re-evaluate extensions in 203 effect. The server's second SSH_MSG_EXT_INFO is matched against the 204 client's original. 206 The timing of the second opportunity is chosen for the following 207 reasons. If the message was sent earlier, it would not allow the 208 server to withhold information until the client has authenticated. 209 If it was sent later, a client that needs information from the 210 second SSH_MSG_EXT_INFO immediately after it authenticates would 211 have no way to reliably know whether to expect the message. 213 2.5. Interpretation of Extension Names and Values 215 Each extension is identified by its extension-name, and defines the 216 conditions under which the extension is considered to be in effect. 217 Applications MUST ignore unrecognized extension-names. 219 An extension MAY dictate, where it is specified, that in order to take 220 effect, both parties must include it in their SSH_MSG_EXT_INFO; or it 221 can be sufficient that only one party includes it; or other rules MAY 222 be specified. The relative order in which extensions appear in an 223 SSH_MSG_EXT_INFO message MUST be ignored. 225 Extension-value fields are interpreted as defined by their respective 226 extension. This field MAY be empty if permitted by the extension. 227 Applications that do not implement or recognize an extension MUST 228 ignore its extension-value, regardless of its size or content. 229 Applications MUST tolerate any sequence of bytes - including null 230 bytes at any position - in an unknown extension's extension-value. 232 The cumulative size of an SSH_MSG_EXT_INFO message is limited only by 233 the maximum packet length that an implementation may apply in 234 accordance with [RFC4253]. Implementations MUST accept well-formed 235 SSH_MSG_EXT_INFO messages up to the maximum packet length they accept. 237 3. Initially Defined Extensions 239 3.1. "server-sig-algs" 241 This extension is sent with the following extension name and value: 243 string "server-sig-algs" 244 name-list public-key-algorithms-accepted 246 The name-list type is a strict subset of the string type, and is thus 247 permissible as an extension-value. See [RFC4251] for more information. 249 This extension is sent by the server, and contains a list of public 250 key algorithms that the server is able to process as part of a 251 "publickey" authentication request. If a client sends this extension, 252 the server MAY ignore it, and MAY disconnect. 254 In this extension, a server MUST enumerate all public key algorithms 255 it might accept during user authentication. However, there exist early 256 server implementations which do not enumerate all accepted algorithms. 257 For this reason, a client MAY send a user authentication request using 258 a public key algorithm not included in "server-sig-algs". 260 A client that wishes to proceed with public key authentication MAY 261 wait for the server's SSH_MSG_EXT_INFO so it can send a "publickey" 262 authentication request with an appropriate public key algorithm, 263 rather than resorting to trial and error. 265 Servers that implement public key authentication SHOULD implement this 266 extension. 268 If a server does not send this extension, a client MUST NOT make any 269 assumptions about the server's public key algorithm support, and MAY 270 proceed with authentication requests using trial and error. Note that 271 implementations are known to exist that apply authentication 272 penalties (*) if the client attempts to use an unexpected public key 273 algorithm. 275 (*) Authentication penalties are applied by servers to deter brute 276 force password guessing, username enumeration, and other types of 277 behavior deemed suspicious by server administrators or implementers. 278 Penalties may include automatic IP address throttling or blocking, 279 and may trigger email alerts or auditing. 281 3.2. "delay-compression" 283 This extension MAY be sent by both parties as follows: 285 string "delay-compression" 286 string: 287 name-list compression_algorithms_client_to_server 288 name-list compression_algorithms_server_to_client 290 The extension-value is a string that encodes two name-lists. The 291 name-lists themselves have the encoding of strings. For example: to 292 indicate a preference for algorithms "foo,bar" in the client-to-server 293 direction, and "bar,baz" in the server-to-client direction, a sender 294 encodes the extension-value as follows (including its length): 296 00000016 00000007 666f6f2c626172 00000007 6261722c62617a 298 This same encoding could be sent by either party - client or server. 300 This extension allows the server and client to renegotiate compression 301 algorithm support without having to conduct a key re-exchange, putting 302 new algorithms into effect immediately upon successful authentication. 304 This extension takes effect only if both parties send it. Name-lists 305 MAY include any compression algorithm that could have been negotiated 306 in SSH_MSG_KEXINIT, except algorithms that define their own delayed 307 compression semantics. This means "zlib,none" is a valid algorithm 308 list in this context; but "zlib@openssh.com" is not. 310 If both parties send this extension, but the name-lists do not contain 311 a common algorithm in either direction, the parties MUST disconnect in 312 the same way as if negotiation failed as part of SSH_MSG_KEXINIT. 314 If this extension takes effect, the renegotiated compression algorithm 315 is activated for the very next SSH message after the trigger message: 317 - Sent by the server, the trigger message is SSH_MSG_USERAUTH_SUCCESS. 318 - Sent by the client, the trigger message is SSH_MSG_NEWCOMPRESS. 320 If this extension takes effect, the client MUST send the following 321 message within a reasonable number of outgoing SSH messages after 322 receiving SSH_MSG_USERAUTH_SUCCESS - but not necessarily as the first 323 such outgoing message: 325 byte SSH_MSG_NEWCOMPRESS (value 8) 327 The purpose of SSH_MSG_NEWCOMPRESS is to avoid a race condition 328 where the server cannot reliably know whether a message sent by 329 the client was sent before or after receiving the server's 330 SSH_MSG_USERAUTH_SUCCESS. For example, clients may send keep-alive 331 messages during logon processing. 333 As is the case for all extensions unless otherwise noted, the server 334 MAY delay including this extension until its secondary 335 SSH_MSG_EXT_INFO, sent before SSH_MSG_USERAUTH_SUCCESS. This allows 336 the server to avoid advertising compression until the client has 337 authenticated. 339 If the parties re-negotiate compression using this extension in a 340 session where compression is already enabled; and the re-negotiated 341 algorithm is the same in one or both directions; then the internal 342 compression state MUST be reset for each direction at the time the 343 re-negotiated algorithm takes effect. 345 3.2.1. Awkwardly Timed Key Re-Exchange 347 A party that has signaled, or intends to signal, support for this 348 extension in an SSH session, MUST NOT initiate key re-exchange in that 349 session until either of the following occurs: 351 - This extension was negotiated, and the party that's about to start 352 key re-exchange already sent its trigger message for compression. 354 - The party has sent (if server) or received (if client) the message 355 SSH_MSG_USERAUTH_SUCCESS, and this extension was not negotiated. 357 If a party violates this rule, the other party MAY disconnect. 359 In general, parties SHOULD NOT start key re-exchange before successful 360 user authentication, but MAY tolerate it if not using this extension. 362 3.2.2. Subsequent Re-Exchange 364 In subsequent key re-exchanges that unambiguously begin after the 365 compression trigger messages, the compression algorithms negotiated in 366 re-exchange override the algorithms negotiated with this extension. 368 3.2.3. Compatibility Note: OpenSSH up to 7.5 370 This extension uses a binary extension-value encoding. OpenSSH clients 371 up to and including version 7.5 advertise support to receive 372 SSH_MSG_EXT_INFO, but disconnect on receipt of an extension-value 373 containing null bytes. This is an error fixed in OpenSSH version 7.6. 375 Implementations that wish to interoperate with OpenSSH 7.5 and earlier 376 are advised to check the remote party's SSH version string, and omit 377 this extension if an affected version is detected. Affected versions 378 do not implement this extension, so there is no harm in omitting it. 379 The extension SHOULD NOT be omitted if the detected OpenSSH version is 380 7.6 or higher. This would make it harder for the OpenSSH project to 381 implement this extension in a higher version. 383 3.3. "no-flow-control" 385 This extension is sent with the following extension name and value: 387 string "no-flow-control" 388 string choice of: "p" for preferred | "s" for supported 390 A party SHOULD send "s" if it supports "no-flow-control", but does not 391 prefer to enable it. A party SHOULD send "p" if it prefers to enable 392 the extension if the other party supports it. Parties MAY disconnect 393 if they receive a different extension value. 395 To take effect, this extension MUST be: 397 - Sent by both parties. 398 - At least one party MUST have sent the value "p" (preferred). 400 If this extension takes effect, the "initial window size" fields in 401 SSH_MSG_CHANNEL_OPEN and SSH_MSG_CHANNEL_OPEN_CONFIRMATION, as defined 402 in [RFC4254], become meaningless. The values of these fields MUST be 403 ignored, and a channel behaves as if all window sizes are infinite. 404 Neither side is required to send any SSH_MSG_CHANNEL_WINDOW_ADJUST 405 messages, and if received, such messages MUST be ignored. 407 This extension is intended, but not limited to, use by file transfer 408 applications that are only going to use one channel, and for which the 409 flow control provided by SSH is an impediment, rather than a feature. 411 Implementations MUST refuse to open more than one simultaneous channel 412 when this extension is in effect. Nevertheless, server implementations 413 SHOULD support clients opening more than one non-simultaneous channel. 415 3.3.1. Prior "No Flow Control" Practice 417 Before this extension, some applications would simply not implement 418 SSH flow control, sending an initial channel window size of 2^32 - 1. 419 Applications SHOULD NOT do this for the following reasons: 421 - It is plausible to transfer more than 2^32 bytes over a channel. 422 Such a channel will hang if the other party implements SSH flow 423 control according to [RFC4254]. 425 - There exist implementations which cannot handle large channel window 426 sizes, and can exhibit non-graceful behaviors, including disconnect. 428 3.4. "elevation" 430 The terms "elevation" and "elevated" refer to an operating system 431 mechanism where an administrator user's logon session is associated 432 with two security contexts: one limited, and one with administrative 433 rights. To "elevate" such a session is to activate the security 434 context with full administrative rights. For more information about 435 this mechanism on Windows, see also [WINADMIN] and [WINTOKEN]. 437 This extension MAY be sent by the client as follows: 439 string "elevation" 440 string choice of: "y" | "n" | "d" 442 A client sends "y" to indicate its preference that the session should 443 be elevated; "n" to not be elevated; and "d" for the server to use its 444 default behavior. The server MAY disconnect if it receives a different 446 extension value. If a client does not send the "elevation" extension, 447 the server SHOULD act as if "d" was sent. 449 If a client has included this extension, then after authentication, a 450 server that supports this extension SHOULD indicate to the client 451 whether elevation was done by sending the following global request: 453 byte SSH_MSG_GLOBAL_REQUEST 454 string "elevation" 455 boolean want reply = false 456 boolean elevation performed 458 Clients that implement this extension help reduce attack surface for 459 Windows servers that handle administrative logins. Where clients do 460 not support this extension, servers must elevate sessions to allow 461 full access by administrative users always. Where clients support this 462 extension, sessions can be created without elevation unless requested. 464 4. IANA Considerations 466 4.1. Additions to existing tables 468 IANA is requested to insert the following entries into the table 469 Message Numbers [IANA-M] under Secure Shell (SSH) Protocol Parameters 470 [RFC4250]: 472 Value Message ID Reference 473 7 SSH_MSG_EXT_INFO [this document] 474 8 SSH_MSG_NEWCOMPRESS [this document] 476 IANA is requested to insert the following entries into the table Key 477 Exchange Method Names [IANA-KE]: 479 Method Name Reference Note 480 ext-info-s [this document] Section 2.2 481 ext-info-c [this document] Section 2.2 483 4.2. New table: Extension Names 485 Also under Secure Shell (SSH) Protocol Parameters, IANA is requested 486 to create a new table, Extension Names, with initial content: 488 Extension Name Reference Note 489 server-sig-algs [this document] Section 3.1 490 delay-compression [this document] Section 3.2 491 no-flow-control [this document] Section 3.3 492 elevation [this document] Section 3.4 494 4.2.1. Future Assignments to Extension Names 496 Names in the Extension Names table MUST follow the Conventions for 497 Names defined in [RFC4250], Section 4.6.1. 499 Requests for assignments of new non-local names in the Extension Names 500 table (i.e. names not including the '@' character) MUST be done 501 through the IETF CONSENSUS method, as described in [RFC8126]. 503 5. Security Considerations 505 Security considerations are discussed throughout this document. This 506 document updates the SSH protocol as defined in [RFC4251] and related 507 documents. The security considerations of [RFC4251] apply. 509 6. References 511 6.1. Normative References 513 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 514 Requirement Levels", BCP 14, RFC 2119, March 1997. 516 [RFC4250] Lehtinen, S. and C. Lonvick, Ed., "The Secure Shell (SSH) 517 Protocol Assigned Numbers", RFC 4250, January 2006. 519 [RFC4251] Lehtinen, S. and C. Lonvick, Ed., "The Secure Shell (SSH) 520 Protocol Architecture", RFC 4251, January 2006. 522 [RFC4252] Ylonen, T. and C. Lonvick, Ed., "The Secure Shell (SSH) 523 Authentication Protocol", RFC 4252, January 2006. 525 [RFC4253] Ylonen, T. and C. Lonvick, Ed., "The Secure Shell (SSH) 526 Transport Layer Protocol", RFC 4253, January 2006. 528 [RFC4254] Ylonen, T. and C. Lonvick, Ed., "The Secure Shell (SSH) 529 Connection Protocol", RFC 4254, January 2006. 531 [RFC8126] Cotton, M., Leiba, B. and Narten, T., "Guidelines for 532 Writing an IANA Considerations Section in RFCs", BCP 26, 533 RFC 8126, June 2017. 535 6.2. Informative References 537 [SSH-RSA-SHA2] 538 Bider, D., "Use of RSA Keys with SHA-2 256 and 512 in 539 Secure Shell (SSH)", draft-ietf-curdle-rsa-sha2-10.txt, 540 August 2017, . 543 [IANA-M] "Secure Shell (SSH) Protocol Parameters", 544 . 547 [IANA-KE] "Secure Shell (SSH) Protocol Parameters", 548 . 551 [WINADMIN] "How to launch a process as a Full Administrator when UAC 552 is enabled?", . 556 [WINTOKEN] "TOKEN_ELEVATION_TYPE enumeration", 557 . 560 Author's Address 562 Denis Bider 563 Bitvise Limited 564 4105 Lombardy Court 565 Colleyville, Texas 76034 566 United States of America 568 EMail: ietf-ssh3@denisbider.com 569 URI: https://www.bitvise.com/ 571 Acknowledgments 573 Thanks to Markus Friedl and Damien Miller for comments and initial 574 implementation. Thanks to Peter Gutmann, Roumen Petrov, Mark D. 575 Baushke, Daniel Migault, Eric Rescorla, Matthew A. Miller, Mirja 576 Kuehlewind, Adam Roach, Spencer Dawkins, Alexey Melnikov, and Ben 577 Campbell for reviews and feedback.