configuring their TLS implementations.  ACME servers that support TLS 1.3 MAY allow clients to send early data (0-RTT).  This is safe because the ACME protocol itself includes anti-replay protections <del> (see replay-protection). </del>  ACME clients MUST send a User-Agent header field, in accordance with RFC7231.  This header field SHOULD include the name and version of

URL URL
Thanks NAME looks fine, just adding clarifications. Benjamin Kaduk has entered the following ballot position for draft-ietf-acme-acme-14: Discuss When responding, please keep the subject line intact and reply to all email addresses included in the To and CC lines. (Feel free to cut this introductory paragraph, however.) Please refer to URL for more information about IESG DISCUSS and COMMENT positions. The document, along with other ballot positions, can be found here: URL DISCUSS: This is a great thing to have, and I intend to eventually ballot Yes, but I do have some questions that may require further discussion before this document is approved. It looks like the server returns an unauthenticated "badSignatureAlgorithm" error when the client sends a JWS using an unsupported signature algorithm (Section 6.2). What prevents an active attacker from performing a downgrade attack on the signature algorithm used? Similarly, since we include in the threat model a potentially hostile CDN/MitM between the ACME client and ACME server, can that attacker strip a success response and replace it with a badNonce error, causing the client to retry (and thus duplicate the request processing on the server)? I am not an ART AD, but there is not yet an internationalization directorate, and seeing statements like "inputs for digest computations MUST be encoded using the UTF-8 character set" (Section 5) without additional discussion of normalization and/or what the canonical form for the digest input is makes me nervous. Has sufficient internationalization review been performed to ensure that there are no latent issues in this space? Section 6.1 has text discussing TLS 1.3's 0-RTT mode. If this text is intended to be a profile that defines/allows the use of TLS 1.3 0-RTT data for the ACME protocol, I think you need to be more specific and say something like "MAY allow clients to send early data (0-RTT); there are no ACME-specific restrictions on which types of requests are permitted in 0-RTT", since the runtime configuration is just 0-RTT yes/no, and the protocol spec is in charge of saying which PDUs are allowed or not. Section 6.2 notes that servers MUST NOT respond to GET requests for sensitvie resources. Why are account resources the only sensitive ones? Are authorizations not sensitive? Or are those considered to fall under the umbrella of "account resources" (Section 7.1 seems pretty clear that they do not)? Section 7.1.1 discusses how the server can include a caaIdentities element in its directory metadata; does this (or anything else) need to be integrity protected by anything stronger than the Web PKI cert authenticating the HTTPS connection? It seems that a bogus caaIdentities value could lead to an unfortunate DoS in some cases. I am also a bit uncertain if the document is internally consistent about whether one challenge verification suffices or there can be cases when multiple challenge verifications are required for a successful authorization. I attmpted to note relevant snippets of the text in my comments on Section 7.1.4. I also have some important substantive comments in the section-by-section COMMENTS, since they would not in and of themselves block publication. COMMENT: This document was quite easy to read -- thank you for the clear prose and document structure! It did leave me with some questions as to whether there are missing clarifications, though, so there are a pile of notes in the section-by-section comments below. It seems natural to feel some unease when the concept of automated certificate issuance like this comes up. As far as I can tell, though, the only substantive difference between this flow and the flow it's replacing is that this one qualitatively feels like it weakens the "know your customer" aspect for the CA -- with current/legacy methods registering for an account can be slow and involves real-world information. Such can be spoofed/forged, of course, but ACME seems to be weakening some aspect by automating it. Given the spoofability, though, this weakening does not seem to be a particular concern with the document. I was going to suggest mentioning the potential for future work in doing time-delayed or periodic revalidation or other schemes to look at the stability of the way that identifiers/challenges were validated, but I see that discussion has already happened. It's probably worth going over the examples and checking whether nonce values are repeated in ways that are inconsistent with expected usage. For example, I see these three values appearing multiple times (but I did not cross-check if a nonce returned in the Replay-Nonce response header was then used in a JWS header attribute): 2 K60BWPrMQG9SDxBDSxtSw 3 IXVHDyxIRGcTE0VSblhPzw 4 JHb54aTKTXBWQOzGYkt9A Perhaps the examples could be offset by a description of what they are? (They would probably also benefit from a disclaimer that the whitespace in the JSON is for ease of reading only.) Section-by-section comments follow. Abstract (also Introduction) If I read "authentication of domain names" with no context, I would be more likely to think of the sort of challenge/authorization process that this document describes, than I would be to think of using an X.509 certificate to authenticate myself as being the owner of a given domain name. But it's unclear whether there's an alternative phrasing that would be better. Section 1 Different types of certificates reflect different kinds of CA verification of information about the certificate subject. "Domain Validation" (DV) certificates are by far the most common type. The only validation the CA is required to perform in the DV issuance process is to verify that the requester has effective control of the domain. Can we get an (informative) ref for the "required"/requirements? Section 6.1 W3C.CR-cors-2013-0129 shows up as "outdated" when I follow the link. Section 6.2 IMPORTANT: The JSON Web Signature and Encryption Algorithms registry does not appear to include an explicit indicator of whether an algorithm is MAC-based; do we need to include text on how to make such a determination? Section 6.3 For servers following the "SHOULD ... string equality check" and for requests where the equality check fails, does that fall into the "MUST reject the request as unauthorized" bucket? Section 6.4 In order to protect ACME resources from any possible replay attacks, ACME requests have a mandatory anti-replay mechanism. We don't seem to actually define what an "ACME request" is that I can see. >From context, this requirement only applies to JWS POST bodies, and not to, say, newNonce, but I wonder if some clarification would be useful. IMPORTANT: How tightly are these nonces scoped? Are they only good on a specific TLS connection? Bound to an account key pair? Globally valid? (This is not a DISCUSS point because AFAICT there is no loss in security if the nonce space is global to the server.) Section 6.6 IMPORTANT: Providing an accountDoesNotExist error type probably means we need to give guidance that the server should choose account URLs in a non-guessable way, to avoid account enumeration attacks. [...] Servers MUST NOT use the ACME URN namespace Section 9.6 for errors other than the standard types. "standard" as determined by inclusion in this document, or in the IANA registry? Section 7.1 The "up" link relation for going from certificate to chain seems to only be needed for alternate content types that can only represent a single certificate. (Also, the "alternate" link relation is used to provide alternate certifciation chains.) Could this text be made more clear? Presumably this is just my confusion, but what does "GET order certificate" mean? Section 7.1.1 [...] It is a JSON object, whose field names are drawn from the following table and whose values are the corresponding URLs. Er, from the IANA registry, right? The following metadata items are defined, all of which are OPTIONAL: Maybe also refer to the registry? Section 7.1.2 IMPORTANT: I'm unclear if the "contact" is supposed to be a "talk to a human" thing or not. If there are supposed to be different URLs that are used for different purposes, wouldn't more metadata be needed about them? So it seems most likely that this is indeed "talk to a human", in which case that might be worth mentioning. (Are these always going to be mailto:?) Section 7.1.2.1 IMPORTANT: Am I reading this correctly that the GET to the orders URL does not require the client to be authenticated, in effect relying on security-through-obscurity (of the account URL) for indicating which account is trying to order certificates for which identifiers? Section 7.1.4 challenges (required, array of objects): For pending authorizations, the challenges that the client can fulfill in order to prove possession of the identifier. For final authorizations (in the "valid" or "invalid" state), the challenges that were used. Each array entry is an object with parameters required to validate the challenge. A client should attempt to fulfill one of these challenges, and a server should consider any one of the challenges sufficient to make the authorization valid. This leaves me slightly confused. A final authorization can have multiple challenges. But a client should only attempt to fulfill one, and a server should treat any one as sufficient. So I can only get to the case with multiple challenges present in a final order of both "should"s are violated? Is there a way for the server to express that multiple challenges are going to be required? Hmm, but Section 7.1.6's flow chart for Authorization objects says that a single challenge's transition to valid also makes the authorization transition to valid, which would seem to close the window? Section 7.5.1 has inline text that implicitly assumes that only one challenge will be completed/validated. wildcard (optional, boolean): For authorizations created as a result of a newOrder request containing a DNS identifier with a value that contained a wildcard prefix this field MUST be present, and true. Is there a difference between false and absent? Section 7.3 A client creates a new account with the server by sending a POST request to the server's new-account URL. The body of the request is a stub account object optionally containing the "contact" and "termsOfServiceAgreed" fields. Given that we go on to describe those two and also the optional onlyReturnExisting and externalAccountBinding fields, does this list need expanding? IMPORTANT: How does the client know if a termsOfService in the directory is actually required or just optional? (There doesn't seem to be a dedicated error type for this?) The text as-is seems to only say that if the server requires it, the field must be present in the directory, but not the other way around. I guess Section 7.3.4 describes the procedure for a similar case; should the same thing happen for the original terms acceptance? IMPORTANT: The example response uses what appears to be a sequential counter for account ID in the returned account URL, which loses any sort of security-through-obscurity protections if those were desired. Should a more opaque URL component be present, maybe a UUID? (The "orders" field would need to be modified accordingly, of course, and this pattern appears in later examples, as well.) Section 7.3.2 It's a little unclear to me whether the fields the client can put in the POST are the ones listed from Section 7.3 or 7.1.2, or the full set from the registry. But presumably the server must ignore the "status" field, too, or at least some values should be disallowed! The IANA registry's "configurable" column may not quite be the right thing for this usage, especially given how account deactivation works. Section 7.3.5 The server MAY require a value for the "externalAccountBinding" field to be present in "newAccount" requests. All requests including queries for the current status and modification of existing accounts? Or just creation of new ones? To enable ACME account binding, the CA operating the ACME server needs to provide the ACME client with a MAC key and a key identifier, using some mechanism outside of ACME. This key needs to also be tied to the external account in question, right? One might even say that it is provided not to the ACME client, but to the external account holder, who is also running an ACME client. [...] The payload of this JWS is the account key being registered, in JWK form. This is presumably my fault and not the document's, but I had to read this a few time to bind it as the ACME account key, and not the external MAC key. If a CA requires that new-account requests contain an "externalAccountBinding" field, then it MUST provide the value "true" in the "externalAccountRequired" subfield of the "meta" field in the directory object. If the CA receives a new-account request without [...] nit: maybe "If such a CA"? IMPORTANT: I don't think I understand why "nonce" MUST NOT be present in the external-binding JWS object, though I think I understand why one is not needed in order to bind the MAC to the current transaction. (That is, this is in effect a "triply nested" construct, where a standalone MAC that certifies an ACME account (public) key as being authorized by the external-account holder to act on behal of that external account. But this standalone MAC will only be accepted by the ACME server in the context of the outer JWS POST, that must be signed by the ACME account key, which is assumed to be kept secure by the ACME client, ensuring that both key-holding entities agree to the account linkage.) Proof of freshness of the commitment from the external account holder to authorize the ACME account key would only be needed if there was a scenario where the external account holder would revoke that association, which does not seem to be a workflow supported by this document. Any need to effectuate such a revocation seems like it would involve issuing a new MAC key for the external account (and invalidating the old one), and revoking/deactivating the ACME account, which is a somewhat heavy hammer but perhaps reasonable for such a scenario. Account key rollover just says that the nonce is NOT REQUIRED, and also uses some nicer (to me) language about "outer JWS" and "inner JWS". It might be nice to synchronize these two sections. Section 7.3.7 IMPORTANT: The "url" in this example looks like an account URL, not an account-deactivation url. If they are one and the same, please include some body text to this effect as is done for account update in Section Section 7.4 Is Section 7.1.3 or the registry a better reference for the request payload's fields? Does the exact-match policy (e.g., on notBefore and notAfter) result in CA maximum lifetime policies needing to be hardcoded in client software (as opposed to being discoverable at runtime)? (I like the order url in the example, "[...]/order/asdf". Not much entropy though.) IMPORTANT: Why does the example response include an identifier of URL that was not in the request? Is the "order's requested identifiers appear in commonName or subjectAltName" requirement an exclusive or? After a valid request to finalize has been issued, are "pending" or "ready" still valid statuses that could be returned for that order? Section 7.4.1 Elsewhere when we list "identifier (required, object)" in a JWS payload we also inline the "type" and "value" breakdown of the object. How is "expires" set for this pre-authorization object? We probably need a reference for "certificate chain as defined in TLS". Section 7.5 "When a client receives an order from the server" is a bit jarring without some additional context of "in a reply to a new-order request" or "an order object" or similar. Section 7.5.1 To do this, the client updates the authorization object received from the server by filling in any required information in the elements of the "challenges" dictionary. "challenges" looks like an array of objects, not directly a dictionary with elements within it. Section 8 IMPORTANT: What do I do if I get a challenge object that has status "valid" but also includes an "error" field? Section 8.1 [...] A key authorization is a string that expresses a domain holder's authorization for a specified key to satisfy a specified challenge, [...] I'm going to quibble with the language here and say that the keyAuthorization string as defined does not express a specific authorization for a specific challenge, since there is no signature involved, and the JWK thumbprint is separable and can be attached to some other token. (This may just be an editorial matter with no broader impact, depending on how it's used.) One could perhaps argue that the mere existence of the token constitutes an authorization for a specified key to satisfy the challenge, since the token only gets generated upon receipt of such an authorized request. Section 8.3 I'm not sure that 4086 is a great cite, here. For example, in RFC 8446 we say that "TLS requires a [CSPRNG]. In most case, the operating system provides an appropriate facility [...] Should these prove unsatisfactory, [RFC4086] provides guidance on the generation of random values." On the other hand, citing 4086 like this is not wrong, so use your judgment. Verify that the body of the response is well-formed key authorization. The server SHOULD ignore whitespace characters at the end of the body. nit: "a well-formed" Can we get some justification for the "SHOULD follow redirects", given the security considerations surrounding doing so? Section 8.4 Should this "token" description include the same text about entropy as for the HTTP challenge? Section 9.7.1 There is perhaps some subtlety here, in that the "configurable" column applies only to the new-account request, but its description in the template does not reflect that restriction. In particular, "status" values from the client are accepted when posted to the account URL, e.g., for account deactivation. Section 10.1 Can there be overlap between the "validation server" function and the "ACME client" function? Section 10.2 [...] The key authorization reflects the account public key, is provided to the server in the validation response over the validation channel and signed afterwards by the corresponding private key in the challenge response over the ACME channel. I'm stumbling up around the comma trying to parse this sentence. (Maybe a serial comma or using "and is signed" would help?) IMPORTANT: Also, I don't see where the key authorization is signed in the challenge response -- the payload is just an empty object for both the HTTP and DNS challenges' responses. Some of this text sounds like we're implicitly placing requirements on all (HTTP|DNS) server operators (not just ones trying to use ACME) to mitgate the risks being described. In general this sort of behavior seems like an anti-design-pattern, though perhaps one could argue that the behaviors in question should be avoided in general, indepnedent of ACME. Section 10.4 Some server implementations include information from the validation server's response (in order to facilitate debugging). Such Disambiguating "ACME server implementations" may help, since we talk about other HTTP requests in the previous paragraph. Section 11.1 IMPORTANT: This may be an appropriate place to recommend against reuse of account keys, whether after an account gets deactivated or by cycling through keys in a sequence of key-change operations (or otherwise). I think there are some attack scenarios possible wherein (inner) JWS objects could be replayed against a different account, if such key reuse occurs. Section 11.3 The http-01, and dns-01 validation methods mandate the usage of a nit: spurious comma. [...] Secondly, the entropy requirement prevents ACME clients from implementing a "naive" validation server that automatically replies to challenges without participating in the creation of the initial authorization request. IMPORTANT: I'm not sure I see how this applies to the HTTP mechanism -- couldn't you write a script to reply to .well-known/acme-challenge/ with . for a fixed key thumbprint? The validation server would ned to know about the ACME account in question, but not about any individual authorization request. Thanks for addressing my Discuss and other points; as promised, I'm switching to Yes.  (But I support Adam's discuss and look forward to seeing it come to a close as well.) This document was quite easy to read -- thank you for the clear prose and document structure!  It did leave me with some questions as to whether there are missing clarifications, though, so there are a pile of notes in the section-by-section comments below. It seems natural to feel some unease when the concept of automated certificate issuance like this comes up.  As far as I can tell, though, the only substantive difference between this flow and the flow it's replacing is that this one qualitatively feels like it weakens the "know your customer" aspect for the CA -- with current/legacy methods registering for an account can be slow and involves real-world information.  Such can be spoofed/forged, of course, but ACME seems to be weakening some aspect by automating it.  Given the spoofability, though, this weakening does not seem to be a particular concern with the document. I was going to suggest mentioning the potential for future work in doing time-delayed or periodic revalidation or other schemes to look at the stability of the way that identifiers/challenges were validated, but I see that discussion has already happened. It's probably worth going over the examples and checking whether nonce values are repeated in ways that are inconsistent with expected usage.  For example, I see these three values appearing multiple times (but I did not cross-check if a nonce returned in the Replay-Nonce response header was then used in a JWS header attribute): Perhaps the examples could be offset by a description of what they are? (They would probably also benefit from a disclaimer that the whitespace in the JSON is for ease of reading only.) Section-by-section comments follow. Abstract (also Introduction) If I read "authentication of domain names" with no context, I would be more likely to think of the sort of challenge/authorization process that this document describes, than I would be to think of using an X.509 certificate to authenticate myself as being the owner of a given domain name.  But it's unclear whether there's an alternative phrasing that would be better. Can we get an (informative) ref for the "required"/requirements? W3C.CR-cors-2013-0129 shows up as "outdated" when I follow the link. IMPORTANT: The JSON Web Signature and Encryption Algorithms registry does not appear to include an explicit indicator of whether an algorithm is MAC-based; do we need to include text on how to make such a determination? For servers following the "SHOULD ... string equality check" and for requests where the equality check fails, does that fall into the "MUST reject the request as unauthorized" bucket? We don't seem to actually define what an "ACME request" is that I can see. From context, this requirement only applies to JWS POST bodies, and not to, say, newNonce, but I wonder if some clarification would be useful. IMPORTANT: How tightly are these nonces scoped?  Are they only good on a specific TLS connection?  Bound to an account key pair?  Globally valid? (This is not a DISCUSS point because AFAICT there is no loss in security if the nonce space is global to the server.) IMPORTANT: Providing an accountDoesNotExist error type probably means we need to give guidance that the server should choose account URLs in a non-guessable way, to avoid account enumeration attacks. "standard" as determined by inclusion in this document, or in the IANA registry? The "up" link relation for going from certificate to chain seems to only be needed for alternate content types that can only represent a single certificate.  (Also, the "alternate" link relation is used to provide alternate certifciation chains.)  Could this text be made more clear? Presumably this is just my confusion, but what does "GET order certificate" mean? Er, from the IANA registry, right? Maybe also refer to the registry? IMPORTANT: I'm unclear if the "contact" is supposed to be a "talk to a human" thing or not.  If there are supposed to be different URLs that are used for different purposes, wouldn't more metadata be needed about them? So it seems most likely that this is indeed "talk to a human", in which case that might be worth mentioning.  (Are these always going to be mailto:?) IMPORTANT: Am I reading this correctly that the GET to the orders URL does not require the client to be authenticated, in effect relying on security-through-obscurity (of the account URL) for indicating which account is trying to order certificates for which identifiers? This leaves me slightly confused.  A final authorization can have multiple challenges.  But a client should only attempt to fulfill one, and a server should treat any one as sufficient.  So I can only get to the case with multiple challenges present in a final order of both "should"s are violated?  Is there a way for the server to express that multiple challenges are going to be required? Hmm, but Section 7.1.6's flow chart for Authorization objects says that a single challenge's transition to valid also makes the authorization transition to valid, which would seem to close the window? Section 7.5.1 has inline text that implicitly assumes that only one challenge will be completed/validated. Is there a difference between false and absent? Given that we go on to describe those two and also the optional onlyReturnExisting and externalAccountBinding fields, does this list need expanding? IMPORTANT: How does the client know if a termsOfService in the directory is actually required or just optional?  (There doesn't seem to be a dedicated error type for this?)  The text as-is seems to only say that if the server requires it, the field must be present in the directory, but not the other way around.  I guess Section 7.3.4 describes the procedure for a similar case; should the same thing happen for the original terms acceptance? IMPORTANT: The example response uses what appears to be a sequential counter for account ID in the returned account URL, which loses any sort of security-through-obscurity protections if those were desired.  Should a more opaque URL component be present, maybe a UUID?  (The "orders" field would need to be modified accordingly, of course, and this pattern appears in later examples, as well.) It's a little unclear to me whether the fields the client can put in the POST are the ones listed from Section 7.3 or 7.1.2, or the full set from the registry.  But presumably the server must ignore the "status" field, too, or at least some values should be disallowed!  The IANA registry's "configurable" column may not quite be the right thing for this usage, especially given how account deactivation works. All requests including queries for the current status and modification of existing accounts?  Or just creation of new ones? This key needs to also be tied to the external account in question, right? One might even say that it is provided not to the ACME client, but to the external account holder, who is also running an ACME client. This is presumably my fault and not the document's, but I had to read this a few time to bind it as the ACME account key, and not the external MAC key. nit: maybe "If such a CA"? IMPORTANT: I don't think I understand why "nonce" MUST NOT be present in the external-binding JWS object, though I think I understand why one is not needed in order to bind the MAC to the current transaction.  (That is, this is in effect a "triply nested" construct, where a standalone MAC that certifies an ACME account (public) key as being authorized by the external-account holder to act on behal of that external account.  But this standalone MAC will only be accepted by the ACME server in the context of the outer JWS POST, that must be signed by the ACME account key, which is assumed to be kept secure by the ACME client, ensuring that both key-holding entities agree to the account linkage.)  Proof of freshness of the commitment from the external account holder to authorize the ACME account key would only be needed if there was a scenario where the external account holder would revoke that association, which does not seem to be a workflow supported by this document.  Any need to effectuate such a revocation seems like it would involve issuing a new MAC key for the external account (and invalidating the old one), and revoking/deactivating the ACME account, which is a somewhat heavy hammer but perhaps reasonable for such a scenario. Account key rollover just says that the nonce is NOT REQUIRED, and also uses some nicer (to me) language about "outer JWS" and "inner JWS".  It might be nice to synchronize these two sections. IMPORTANT: The "url" in this example looks like an account URL, not an account-deactivation url. If they are one and the same, please include some body text to this effect as is done for account update in Section 7.3.2. Is Section 7.1.3 or the registry a better reference for the request payload's fields? Does the exact-match policy (e.g., on notBefore and notAfter) result in CA maximum lifetime policies needing to be hardcoded in client software (as opposed to being discoverable at runtime)? (I like the order url in the example, "[...]/order/asdf".  Not much entropy though.) IMPORTANT: Why does the example response include an identifier of www.example.com that was not in the request? Is the "order's requested identifiers appear in commonName or subjectAltName" requirement an exclusive or? After a valid request to finalize has been issued, are "pending" or "ready" still valid statuses that could be returned for that order? Elsewhere when we list "identifier (required, object)" in a JWS payload we also inline the "type" and "value" breakdown of the object. How is "expires" set for this pre-authorization object? We probably need a reference for "certificate chain as defined in TLS". "When a client receives an order from the server" is a bit jarring without some additional context of "in a reply to a new-order request" or "an order object" or similar. "challenges" looks like an array of objects, not directly a dictionary with elements within it. IMPORTANT: What do I do if I get a challenge object that has status "valid" but also includes an "error" field? I'm going to quibble with the language here and say that the keyAuthorization string as defined does not express a specific authorization for a specific challenge, since there is no signature involved, and the JWK thumbprint is separable and can be attached to some other token.  (This may just be an editorial matter with no broader impact, depending on how it's used.)  One could perhaps argue that the mere existence of the token constitutes an authorization for a specified key to satisfy the challenge, since the token only gets generated upon receipt of such an authorized request. I'm not sure that 4086 is a great cite, here.  For example, in RFC 8446 we say that "TLS requires a [CSPRNG].  In most case, the operating system provides an appropriate facility [...] Should these prove unsatisfactory,[RFC4086] provides guidance on the generation of random values."  On the other hand, citing 4086 like this is not wrong, so use your judgment. nit: "a well-formed" Can we get some justification for the "SHOULD follow redirects", given the security considerations surrounding doing so? Should this "token" description include the same text about entropy as for the HTTP challenge? There is perhaps some subtlety here, in that the "configurable" column applies only to the new-account request, but its description in the template does not reflect that restriction.  In particular, "status" values from the client *are* accepted when posted to the account URL, e.g., for account deactivation. Can there be overlap between the "validation server" function and the "ACME client" function? I'm stumbling up around the comma trying to parse this sentence.  (Maybe a serial comma or using "and is signed" would help?) IMPORTANT: Also, I don't see where the key authorization is signed in the challenge response -- the payload is just an empty object for both the HTTP and DNS challenges' responses. Some of this text sounds like we're implicitly placing requirements on all (HTTP|DNS) server operators (not just ones trying to use ACME) to mitgate the risks being described.  In general this sort of behavior seems like an anti-design-pattern, though perhaps one could argue that the behaviors in question should be avoided in general, indepnedent of ACME. Disambiguating "ACME server implementations" may help, since we talk about other HTTP requests in the previous paragraph. IMPORTANT: This may be an appropriate place to recommend against reuse of account keys, whether after an account gets deactivated or by cycling through keys in a sequence of key-change operations (or otherwise).  I think there are some attack scenarios possible wherein (inner) JWS objects could be replayed against a different account, if such key reuse occurs. nit: spurious comma. IMPORTANT: I'm not sure I see how this applies to the HTTP mechanism -- couldn't you write a script to reply to .well-known/acme-challenge/<foo> with <foo>.<key thumbprint> for a fixed key thumbprint?  The validation server would ned to know about the ACME account in question, but not about any individual authorization request.

configuring their TLS implementations.  ACME servers that support TLS 1.3 MAY allow clients to send early data (0-RTT).  This is safe because the ACME protocol itself includes anti-replay protections  <ins> (see replay-protection) in all cases where they are required.  For this reason, there are no restrictions on what ACME data can be carried in 0-RTT. </ins> ACME clients MUST send a User-Agent header field, in accordance with RFC7231.  This header field SHOULD include the name and version of


"status" field. For pending authorizations, the challenges that the client can <del> fulfill in order to prove possession of the identifier.  For final authorizations (in the "valid" or "invalid" state), the challenges that were used.  Each array entry is an object with parameters required to validate the challenge.  A client should attempt to fulfill one of these challenges, and a server should consider any one of the challenges sufficient to make the authorization valid. </del>  For authorizations created as a result of a newOrder request containing a DNS identifier with a value that contained a wildcard

"status" field. For pending authorizations, the challenges that the client can  <ins> fulfill in order to prove possession of the identifier.  For valid authorizations, the challenge that was validated.  For invalid authorizations, the challenge that was attempted and failed.  Each array entry is an object with parameters required to validate the challenge.  A client should attempt to fulfill one of these challenges, and a server should consider any one of the challenges sufficient to make the authorization valid. </ins> For authorizations created as a result of a newOrder request containing a DNS identifier with a value that contained a wildcard


Authorization objects are created in the "pending" state.  If one of the challenges listed in the authorization transitions to the "valid" state, then the authorization also changes to the "valid" state.  If <del> there is an error while the authorization is still pending, then the </del>  authorization transitions to the "invalid" state.  Once the authorization is in the valid state, it can expire ("expired"), be deactivated by the client ("deactivated", see deactivating-an-

Authorization objects are created in the "pending" state.  If one of the challenges listed in the authorization transitions to the "valid" state, then the authorization also changes to the "valid" state.  If  <ins> the client attempts to fulfill a challenge and fails, or if there is an error while the authorization is still pending, then the </ins> authorization transitions to the "invalid" state.  Once the authorization is in the valid state, it can expire ("expired"), be deactivated by the client ("deactivated", see deactivating-an-


can't obtain illegitimate authorization by acting as an ACME client (legitimately, in terms of the protocol).  10.2. ACME allows anyone to request challenges for an identifier by

can't obtain illegitimate authorization by acting as an ACME client (legitimately, in terms of the protocol). <ins> ACME does not protect against other types of abuse by a MitM on the ACME channel.  For example, such an attacker could send a bogus "badSignatureAlgorithm" error response to downgrade a client to the lowest-quality signature algorithm that the server supports.  A MitM that is present on all connections (such as a CDN), can cause denial- of-service conditions in a variety of ways. </ins> 10.2. ACME allows anyone to request challenges for an identifier by


9.1. A file of this type contains one or more certificates encoded with <del> the PEM textual encoding, according to RFC 7468 RFC7468.  In order to provide easy interoperation with TLS, the first certificate MUST be an end-entity certificate.  Each following certificate SHOULD directly certify the one preceding it.  Because certificate validation requires that trust anchors be distributed independently, a certificate that represents a trust anchor MAY be omitted from the chain, provided that supported peers are known to possess any omitted certificates. </del>  The "Media Types" registry should be updated with the following additional value:

In addition to forbidding explanatory text, this PR restricts the PEM-certificate-chain structure to the "strict" production defined in RFC 7468, Figure 3.
s/Figure 3 of RFC 7468/Section 3 of RFC 7468/

9.1. A file of this type contains one or more certificates encoded with  <ins> the PEM textual encoding, according to RFC 7468 RFC7468.  The textual encoding of certificates in this file MUST use the strict encoding and MUST NOT include explanatory text.  The ABNF for this format is as follows, where "stricttextualmsg" and "eol" are as defined in Section 3 of RFC 7468: In order to provide easy interoperation with TLS, the first certificate MUST be an end-entity certificate.  Each following certificate SHOULD directly certify the one preceding it.  Because certificate validation requires that trust anchors be distributed independently, a certificate that represents a trust anchor MAY be omitted from the chain, provided that supported peers are known to possess any omitted certificates. </ins> The "Media Types" registry should be updated with the following additional value:


anchors.  Clients can fetch these alternates and use their own heuristics to decide which is optimal. <del> An ACME client MAY attempt to fetch the certificate with a GET request.  If the server does not allow GET requests for certificate resources, then it will return an error as described in post-as-get. On receiving such an error, the client SHOULD fall back to a POST-as- GET request. </del> A certificate resource represents a single, immutable certificate. If the client wishes to obtain a renewed certificate, the client initiates a new order process to request one.

Thanks to Felipe Gasper for .
Merging despite spurious CI failure, since it seems pretty clear that the CI failure is spurious. Hi all, Draft 16 has this: An ACME client MAY attempt to fetch the certificate with a GET request. If the server does not allow GET requests for certificate resources, then it will return an error as described in Section 6.3 . On receiving such an error, the client SHOULD fall back to a POST-as- GET request. From what I can discern from this list’s most recent posts on the topic, I’m under the impression that plain GET for certificates is not to be part of the principal ACME spec; should the above, then, be removed? -FG

anchors.  Clients can fetch these alternates and use their own heuristics to decide which is optimal.  A certificate resource represents a single, immutable certificate. If the client wishes to obtain a renewed certificate, the client initiates a new order process to request one.


with an array of supported "alg" values.  See errors for more details on the structure of error responses.  Because client requests in ACME carry JWS objects in the Flattened JSON Serialization, they must have the Content-Type header field set to "application/jose+json".  If a request does not meet this

NAME Sure. I've just posted this: URL
LGTMThe bullet points improve readability quite a bit, thanks NAME !also not purely editorial, but okay. I realize it's very late for making non-editorial changes to draft-ietf-acme-acme, but I'd like to propose adding a new badPublicKey error. This error would be returned by the server whenever it does not support, or wishes to reject, a "jwk" public key supplied in a client's request. Proposed text: URL The 'array of supported "alg" values' in a badSignatureAlgorithm response is useful, but ISTM that it doesn't provide detailed enough information to assist a client in generating a suitable public key. (If the consensus is that it's too late to add a new error type, then my alternative proposal will be to use "malformed" instead of adding "badPublicKey", but keep the rest of PR 478 as is; I think it's a good idea to call out the need for a server to sanity check each client-supplied public key). Rob Stradling Senior Research & Development Scientist Sectigo Limited

with an array of supported "alg" values.  See errors for more details on the structure of error responses. <ins> If the server supports the signature algorithm "alg" but either does not support or chooses to reject the public key "jwk", then the server MUST return an error with status code 400 (Bad Request) and type "urn:ietf:params:acme:error:badPublicKey".  The problem document detail SHOULD describe the reason for rejecting the public key; some example reasons are: "alg" is "RS256" but the modulus "n" is too small (e.g., 512-bit) "alg" is "ES256" but "jwk" does not contain a valid P-256 public key "alg" is "EdDSA" and "crv" is "Ed448", but the server only supports "EdDSA" with "Ed25519" the corresponding private key is known to have been compromised </ins> Because client requests in ACME carry JWS objects in the Flattened JSON Serialization, they must have the Content-Type header field set to "application/jose+json".  If a request does not meet this


process can be represented and performed by Internet protocols with no out-of-band human intervention. <del> When an operator deploys a current HTTPS server, it generally prompts him to generate a self-signed certificate.  When an operator deploys an ACME-compatible web server, the experience would be something like this: </del>  The ACME client prompts the operator for the intended domain name(s) that the web server is to stand for.

Avoid changing the "him" in the MitM paragraph, because of the inherent notion of a Man in the Middle, which is a larger discussion.
LGTM. Thanks for the elegant fix.

process can be represented and performed by Internet protocols with no out-of-band human intervention.  <ins> When deploying a current HTTPS server, an operator generally gets a prompt to generate a self-signed certificate.  When an operator deploys an ACME-compatible web server, the experience would be something like this: </ins> The ACME client prompts the operator for the intended domain name(s) that the web server is to stand for.


certificate was issued, and one with relation "author" to indicate the registration under which this certificate was issued. <del> The server MAY include an Expires header as a hint to the client about when to renew the certificate.  (Of course, the real expiration of the certificate is controlled by the notAfter time in the certificate itself.) </del> If the CA participates in Certificate Transparency (CT) RFC6962, then they may want to provide the client with a Signed Certificate Timestamp (SCT) that can be used to prove that a certificate was

For discussion.
See also: URL
I proposed on the mailing list to remove implicit renewal some time ago, and it received some support. Creating this issue to track it. All discussion should be done on the mailing list.

certificate was issued, and one with relation "author" to indicate the registration under which this certificate was issued.  If the CA participates in Certificate Transparency (CT) RFC6962, then they may want to provide the client with a Signed Certificate Timestamp (SCT) that can be used to prove that a certificate was


for a certificate using a Link relation header field with relation "ct-sct". <del> A certificate resource always represents the most recent certificate issued for the name/key binding expressed in the CSR.  If the CA allows a certificate to be renewed, then it publishes renewed versions of the certificate through the same certificate URI. Clients retrieve renewed versions of the certificate using a GET query to the certificate URI, which the server should then return in a 200 (OK) response.  The server SHOULD provide a stable URI for each specific certificate in the Content-Location header field, as shown above.  Requests to stable certificate URIs MUST always result in the same certificate. To avoid unnecessary renewals, the CA may choose not to issue a renewed certificate until it receives such a request (if it even allows renewal at all).  In such cases, if the CA requires some time to generate the new certificate, the CA MUST return a 202 (Accepted) response, with a Retry-After header field that indicates when the new certificate will be available.  The CA MAY include the current (non- renewed) certificate as the body of the response. Likewise, in order to prevent unnecessary renewal due to queries by parties other than the account key holder, certificate URIs should be structured as capability URLs W3C.WD-capability-urls-20140218. From the client's perspective, there is no difference between a certificate URI that allows renewal and one that does not.  If the client wishes to obtain a renewed certificate, and a GET request to the certificate URI does not yield one, then the client may initiate a new-certificate transaction to request one. </del>  6.6.

for a certificate using a Link relation header field with relation "ct-sct".  <ins> A certificate resource represents a single, immutable certificate. If the client wishes to obtain a renewed certificate, the client initiates a new-certificate transaction to request one. Because certificate resources are immutable once issuance is complete, the server MAY enable the caching of the resource by adding Expires and Cache-Control headers specifying a point in time in the distant future.  These headers have no relation to the certificate's period of validity. </ins> 6.6.


In addition, the client MAY advise the server at which IP the challenge is provisioned: <del> An IPv4 or IPv6 address which, if given, MUST be included in the set of IP addresses to which the domain name resolves.  If given, the server will connect to that specific IP address instead of arbitrarily choosing an IP from the set of A and AAAA records to which the domain name resolves.  If the field is given but equal to ""peer"", the server MUST treat the field as if it contained the IP address from which the response was received. </del>  On receiving a response, the server MUST verify that the key authorization in the response matches the "token" value in the

The format should be specified more clearly, by reference to a couple of RFCs The "peer" provision seems kind of awkward. For server implementations where the validation is done by a separate entity than the ACME interactions (like ), this means that the challenge no longer has all the information that the validation agent needs to do the validation. I'm inclined to drop it and put the burden on the client.

In addition, the client MAY advise the server at which IP the challenge is provisioned:  <ins> An IPv4 or IPv6 address which, in dotted decimal form or RFC4291 form, respectively.  If given, this address MUST be included in the set of IP addresses to which the domain name resolves.  If given, the server SHOULD connect to that specific IP address instead of arbitrarily choosing an IP from the set of A and AAAA records to which the domain name resolves. </ins> On receiving a response, the server MUST verify that the key authorization in the response matches the "token" value in the


IANA is requested to register the following Service Names:  8. 8.1.

(n.b., i was not able to "make" and test the change, due to external pyang dependencies of some form.

IANA is requested to register the following Service Names: <ins> 7.5. The IANA is requested to list the name "masa" in the MUD extensions registry defined in I-D.ietf-opsawg-mud.  Its use is documented in mud-extension. </ins> 8. 8.1.


"Connection Priority" on one Connection does not change it on the other Connections in the same Connection Group.  Message Properties set on a Connection also apply only to that Connection.

Does this make sense outside of a protocol-specific context? I am aware that this is a different can of worms adding protocol specific parameters to clone, but this looks like a strange concept to add an Integer here that may have different side effects in QUIC and SCTP…
That's a very good question. This feature request came up in the QuIC mapping part of the discussion in Vienna, see: URL Not sure what to do: keep it as it is, remove it, or add the protocol: assign: "if protocol = x, then stream ID = y" read: "stream ID is y, and your protocol is x" I have to say, I don't like this particular way, as it would complicate matters quite a bit. But how else to do it?
All of the multistreaming protocols we know about have an integer stream identifier. I suppose a future protocol could use some sort of binary blob for identifying streams (which are... pedantically... representable as arbitrary-length integers)
Interim discussion: let's make Clone() and Initiate() take a group of protocol-specific parameters (optionally) which allow protocols like QUIC and SCTP to extend this.
I just made a very minimalist update, where "protocolSpecificProperties" is only a parameter of Clone(). Why not list it as readable properties, and why not as a parameter of Initiate, as we discussed? What's the point of saying "there can be protocol-specific properties which are currently not defined, and they can be readable"? This is for a future spec to say, when it proposes a new transport property. Regarding Initiate(), I think this should in fact not be a parameter to the Initiate Action itself, but a transport property to be supplied when creating a Preconnection. Again, this made me find that I would only write something like "There can also be transport properties that are not yet defined", which doesn't seem to be useful text. In conclusion, I found that only the Clone() Action needs this as a new parameter. Everything else is for future mapping documents. Thoughts?
Many thanks! I incorporated your suggestion, and made a tiny edit to it (behaviour => behavior, underlaying => underlying, and "stream or connection" instead of "stream/connection").
... combined with "if the transport is mux'ing, else ..."
Thanks – I guess we have a fairly good solution.

"Connection Priority" on one Connection does not change it on the other Connections in the same Connection Group. <ins> The optional "connectionProperties" parameter allows passing Transport Properties that control the behavior of the underlying stream or connection to be created, e.g., protocol-specific properties to request specific stream IDs for SCTP or QUIC. </ins> Message Properties set on a Connection also apply only to that Connection.


Data Unit: Datagram The Transport Services API mappings for UDP-Lite are identical to <del> UDP.  Properties that require checksum coverage are not supported by UDP-Lite, such as "msgChecksumLen", "fullChecksumSend", "recvChecksumLen", and "fullChecksumRecv". </del>  10.5.

Initially I thought the description for UDP-Lite was incomplete, but mapping back to the details of the API draft I realized it was incorrect. UDP-Lite supports the msgChecksumLen and recvChecksumLen properties. The API for theses primitives is a bit messy. As specified I think it means the following: UDP can use them to set full coverage or no checksum using the special value of 0. UDP-Lite can use them to set full coverage or a partial coverage. Setting the checksum to only cover the header, although supported by UDP-Lite, will not be possible as 0 is a special value. The special value of 0 can not be used by UDP-Lite, but I left this detail out of the pull request as I thought it got very detailed. It can be added if you think it is needed.

Data Unit: Datagram The Transport Services API mappings for UDP-Lite are identical to  <ins> UDP.  In addition, UDP-Lite supports the "msgChecksumLen" and "recvChecksumLen" Properties that allow an application to specify the minimum number of bytes in a message that need to be covered by a checksum. </ins> 10.5.


of efficiency.  This is not a strict requirement.  The default is to not have this option. <del> Notification of special errors (excessive retransmissions, ICMP error message arrival): This boolean property specifies whether an application considers it useful to be informed in case sent data was retransmitted more often than a certain threshold, or when an ICMP error message arrives.  This property applies to Connections and Connection Groups.  This is not a strict requirement.  The default is to have this option. </del>  Control checksum coverage on sending or receiving: This boolean property specifies whether the application considers it useful to

What makes these errors "special"? It seems a strange term to use, and the meaning is unclear.
I didn't write this, but I think it was an effort to lump together, from minset, two quite different types of errors: 1) notification of excessive retransmissions; 2) notification of icmp error message arrival. Any suggestions for a common term?
If it's just those two types of errors, we can probably just list them...
URL is what I did in minset :)
so the suggestion is to split these out into two protocol selection properties?
yes, I think so
all right then, see
lgtm

of efficiency.  This is not a strict requirement.  The default is to not have this option.  <ins> Notification of excessive retransmissions: This boolean property specifies whether an application considers it useful to be informed in case sent data was retransmitted more often than a certain threshold.  This property applies to Connections and Connection Groups.  This is not a strict requirement.  The default is to have this option. Notification of ICMP error message arrival: This boolean property specifies whether an application considers it useful to be informed when an ICMP error message arrives.  This property applies to Connections and Connection Groups.  This is not a strict requirement.  The default is to have this option. </ins> Control checksum coverage on sending or receiving: This boolean property specifies whether the application considers it useful to


Remote Endpoint and the Local Endpoint, such as IP addresses resolved from a DNS hostname.  5. RFC-EDITOR: Please remove this section before publication.

This is a reworking of the text from Section 4.2 of draft-trammell-taps-post-sockets-03, intended to help motivate the choice of Message-based APIs with framing for the transport services architecture. The level of detail here seems appropriate for the architecture document, rather than the API.
Well written, NAME
What's convenient about the framer? If I have messages of 100 bytes and the length is what defines my message, what's the point of requiring me to define a framer function that I give to the system? I just send, send, send, off go 3 100-byte messages. Hard to get more convenient than that :) I understand that the hook to a sender-side and receiver-side framer can allow you to offer a library that does framing when needed; I don't personally see this as a big win, but okay... and I understand that forcing apps to use a receiver side de-framer can, in principle, let us do cool things on the receiver side (accessing messages out of the bytestream). But for sending this just seems to be an uncomfortable add-on. I guess I shouldn't be arguing it as somehow it's again just syntactical sugar, and I said before that I don't care too much about syntax here. I get it, for the 100-byte messages the framer just won't do anything, and for sending I have to use Connection.Send(Framer.Frame(Message)) instead of Connection.Send(Message)... these calls could basically be renamed into SendMessage vs. SendSomethingHuge. I said before that I don't care too much about these syntactical bits. I guess it's just that tying "Connection.Send(Message)" to "we assume your Message is big and terminates a TCP connection" is really counterintuitive to me.
... and I think I answered to NAME in the wrong place :( sorry github
NAME what’s convenient about the framer? In a C based implementation, very little. In a high level language implementation, however, it means I can and have it convert the high-level structured data into the on the wire format automatically, using a reusable library.
no, no, that was right. Framers can take an object by reference or value of any type, and turn them into an appropriately framed octet array. Syntactic sugar, yes, and pointless in some languages. But have a look at URL -- here, you're pushing down the thing that converts application structures into wire structures into the API, so the API speaks to you in terms of your own structures (in Go, this is generally called a ; IIRC from Java is the terminology there). If your application-internal structures are already serialized byte arrays, you're right, there is zero win here.
NAME Framers are still very very useful in C. You can use callbacks, function pointers, etc, to help lay our your data, and doing that in the context of the networking thread improves efficiency (beyond the simpler API).
NAME even better, then!
also: so this whole line of argument is extremely perplexing to me, and indicative of some sort of fundamental failure to communicate on this particular point. absolutely nobody is saying that this interface implies "your Message... terminates a TCP connection" on the sender side. I can't see where you're getting the impression otherwise in the text. (When receiving, yes, if the receiver has no way to deframe the stream, you get a message that never ends, as a series of partial reads that looks just like a bunch of calls on a stream; i.e. when it fails, it fails to something that basically works exactly like sockets with callbacks.) I really suggest we table this whole discussion until London, because we don't seem to be making much progress in here, and ask you to trust me until then when I say that there is never, ever, ever a situation in which an implementation of this interface that was actually working would ever look at a single message on the sender side "oh, cool, that's done, guess I'll send a FIN then!", ever, because that would be an incredibly silly thing to do. (where's the blink tag in github markdown? i really need the blink tag for this)
On this: Sorry, there's a lack of context - I interpreted this out of private emails from Tommy, which seemed to pretty clearly say that, if you just call "send" without providing a framer, you do send a FIN - and I just found that awkward. But heck! Clearly we all don't want silliness to happen and we want a nice clean interface, and clearly we can quickly agree on this in London. So no worries, and see y'all soon!

Remote Endpoint and the Local Endpoint, such as IP addresses resolved from a DNS hostname. <ins> 4.2.3. While some transports expose a byte stream abstraction, most higher level protocols impose some structure onto that byte stream.  That is, the higher level protocol operates in terms of messages, protocol data units (PDUs), rather than using unstructured sequences of bytes, with each message being processed in turn.  Protocols are specified in terms of state machines acting on semantic messages, with parsing the byte stream into messages being a necessary annoyance, rather than a semantic concern.  Accordingly, the Transport Services architecture exposes messages as the primary abstraction.  Protocols that deal only in byte streams, such as TCP, represent their data in each direction as a single, long message.  When framing protocols are placed on top of byte streams, the messages used in the API represent the framed messages within the stream. Providing a message-based abstraction also provides: the ability to associate deadlines with messages, for transports that care about timing; the ability to provide control of reliability, choosing what messages to retransmit in the event of packet loss, and how best to make use of the data that arrived; the ability to manage dependencies between messages, when some messages may not be delivered due to either packet loss or missing a deadline, in particular the ability to avoid (re-)sending data that relies on a previous transmission that was never received. All require explicit message boundaries, and application-level framing of messages, to be effective.  Once a message is passed to the transport, it can not be cancelled or paused, but prioritization as well as lifetime and retransmission management will provide the protocol stack with all needed information to send the messages as quickly as possible without blocking transmission unnecessarily.  The transport services architecture facilitates this by handling messages, with known identity (sequence numbers, in the simple case), lifetimes, niceness, and antecedents. Transport protocols such as SCTP provide a message-oriented API that has similar features to those we describe.  Other transports, such as TCP, do not.  To support a message oriented API, while still being compatible with stream-based transport protocols, implementations of the transport services architecture should provide APIs for framing and de-framing messages.  That is, we push message framing down into the transport services API, allowing applications to send and receive complete messages.  This is backwards compatible with existing protocols and APIs, since the wire format of messages does not change, but gives the protocol stack additional information to allow it to make better use of modern transport services. </ins> 5. RFC-EDITOR: Please remove this section before publication.


Boolean <del> If true, it specifies that a Message should be delivered to the other side after the previous Message which was passed to the same Connection via the Send Action.  If false, the Message may be delivered out of order.  This property is used for protocols that support preservation of data ordering, see prop-ordering, but allow out-of-order delivery for certain messages. </del>  7.3.4.

I didn't like something about reliability (let's not throw an error when we can't be UNreliable, only when we can't be reliable). I updated the text on ordering a bit, to say that the Property is ignored for the first Message on a Connection, and rephrased it slightly to talk about the receiver-side transport system and the receiving application - before, the text might have talked about a sender-side behavior. I added a TODO DISCUSS comment about per-message Niceness.
Fine with me, maybe fix minor knitThanks, all good now I think.

Boolean  <ins> If true, it specifies that the receiver-side transport protocol stack only deliver the Message to the receiving application after the previous ordered Message which was passed to the same Connection via the Send Action, when such a Message exists.  If false, the Message may be delivered to the receiving application out of order.  This property is used for protocols that support preservation of data ordering, see prop-ordering, but allow out-of-order delivery for certain messages. </ins> 7.3.4.


This property specifies that a message should be sent in such a way that the transport protocol ensures all data is received on the other side without corruption.  Changing the 'Reliable Data Transfer' <del> property on Messages is only possible if the transport protocol supports partial reliability (see prop-partially-reliable). Therefore, for protocols that always transfer data reliably, this property is always true and for protocols that always transfer data unreliably, this property is always false.  Changing it may generate an error. </del>  7.3.8.

This property specifies that a message should be sent in such a way that the transport protocol ensures all data is received on the other side without corruption.  Changing the 'Reliable Data Transfer'  <ins> property on Messages is only possible if the Connection supports reliability.  When this is not the case, changing it will generate an error. </ins> 7.3.8.


Preconnection, Connection (read only) <del> This property specifies whether the application wishes to use a </del>  transport protocol that ensures that all data is received on the other side without corruption.  This also entails being notified when a Connection is closed or aborted.  The default is to enable Reliable

Preconnection, Connection (read only)  <ins> This property specifies whether the application needs to use a </ins> transport protocol that ensures that all data is received on the other side without corruption.  This also entails being notified when a Connection is closed or aborted.  The default is to enable Reliable


12.3.22.  Integer Message Property - see msg-niceness. Note that this property is not a per-message override of the connection Niceness - see conn-niceness.  Both Niceness properties <del> may interact, but can be used indepentendly and be realized by </del>  different mechanisms. 12.3.23.

12.3.22. <ins> [TODO: Discuss: should we remove this?  Whether we need this or the other depends on how we want to implement multi-streaming.  We don't need both, so we should make a decision.] </ins> Integer Message Property - see msg-niceness. Note that this property is not a per-message override of the connection Niceness - see conn-niceness.  Both Niceness properties  <ins> may interact, but can be used independently and be realized by </ins> different mechanisms. 12.3.23.


as an asynchronous interface, they generally use a try-and-fail model.  If the application wants to read, but data has not yet been received from the peer, the call to read will fail.  The application <del> then waits for a notification to indicate when it can try again. </del>  All interaction with a Transport Services system is expected to be asynchronous, and use an event-driven model unlike sockets events.

I guess here is not nessecarily a notification required in sychronuous communication
Merged in master to avoid conflict, and tweaked working to remove "some times", which felt a bit too colloquial in tone.

as an asynchronous interface, they generally use a try-and-fail model.  If the application wants to read, but data has not yet been received from the peer, the call to read will fail.  The application  <ins> then waits and can try again later. </ins> All interaction with a Transport Services system is expected to be asynchronous, and use an event-driven model unlike sockets events.


5.2.10.  This property specifies whether an application wants to use the connection for sending and/or receiving data.  Possible values are:

Notable changes: added control over using multipath (which was a late addition to minset) added a timeout for conn. establishment, separate from the other conn. abort timeout (see ) renamed InitiateWithIdempotentSend into InitiateWithSend, and adjusted the text to recommend declaring idempotence. This addresses the minset function that goes back to TCP's send-with-SYN.
Status: NAME said "LGTM modulo tiny nits" and I think these nits are now addressed. NAME requests something more than just a boolean to enable/disable usage of multiple paths. It seems to me that this needs more discussion, but it also doesn't seem like a show-stopper for the boolean to begin with; I think we can discuss this more after landing this PR. NAME hasn't reacted (or am I missing this), but this has an ok from NAME and NAME In conclusion: I think this is good to go. I'll wait until tomorrow; unless someone speaks up by then, I'll merge this PR.
If you make it a boolean it cannot be used as a selection property, so I do not think that is a good choice. Or how should it be interpreted for the selection?
NAME what do you mean, that it should be a (binary - yes/no) Preference instead? I thought this would be more limiting but I'm fine with this as well.
NAME I meant that it should be a Preference as pointed out in the original comment by NAME I do not understand what a boolean means during selection (is it a requirement or a preference?) I also do not understand what it means in the middle of a connection. You mean you should try and use a single or several subflows for scheduling data, assuming you already have a multipath connection? I guess this is possible, but then the description needs to be more clear that this is what it means. In the appendix about minset your have "Disable MPTCP: "Parallel Use of Multiple Paths" Property." I assume this refers to the Protocol Selection phase? It does not make sense to disable or enable MPTCP in the middle of a connection I think. I guess part of how to specify the property depends on how to interpret this part from the intro to the Managing Connections section: "The application can set and query Connection Properties on a per-Connection basis. Connection Properties that are not read-only can be set during pre-establishment (see {{selection-props}}), as well as on connections directly using the SetProperty action" I interpreted this as properties set during pre-establishment are selection properties, but maybe this is not the intention as they may need to be expressed differently? If they are not intended as selection properties, we are missing a selection property for multipath I guess.
NAME Ok. That's what I meant, yes - but I agree that's not covered by the description, it really is a selection preference only as it's written now. OK (though you CAN do it with the "real" API, by closing subflows, but this goes beyond the spec'd protocol, and I'm also not sure it's a good idea, especially when limited to only enabling / disabling it altogether). I would have understood this as in your first interpretation: "properties set during pre-establishment are selection properties".
NAME Closing a subflow is not the same as disabling MPTCP to me. You will still be using MPTCP, only with a single subflow. And you can certainly not open a subflow unless MPTCP is already enabled. But seems we now have a common understanding.
NAME ack, we've converged. I just pushed a commit that turns the "Parallel Use of Multiple Paths" property into a Selection property.
these are a few minor changes to apply, and properties to add (e.g. "disable MPTCP")
this is done, yes?
No. But I'm planning to do a PR to address this issue this week.
Note that this also requires closing , which I re-opened with a concrete proposal to address something from minset.
LGTM modulo tiny nitsSorry, missed this until just now. Looks fine with me, I just have a small question and my 2 cents to the multipath discussion (which we can have at a later point).

5.2.10. <ins> This property specifies whether an application considers it useful to transfer data across multiple paths between the same end hosts. Generally, in most cases, this will improve performance (e.g., achieve greater throughput).  One possible side-effect is increased jitter, which may be problematic for delay-sensitive applications. The recommended default is to have this option. 5.2.11. </ins> This property specifies whether an application wants to use the connection for sending and/or receiving data.  Possible values are:


connections are not supported by the transport protocol, the system should fall back to bidirectional transport.  5.3. Most security parameters, e.g., TLS ciphersuites, local identity and

connections are not supported by the transport protocol, the system should fall back to bidirectional transport. <ins> 5.2.12. This property specifies how long to wait before aborting a Connection during establishment. </ins> 5.3. Most security parameters, e.g., TLS ciphersuites, local identity and


7.6. For application-layer protocols where the Connection initiator also <del> sends the first message, the InitiateWithIdempotentSend() action combines Connection initiation with a first Message sent, provided that message is idempotent. </del>  Without a message context (as in send-basic): With a message context (as in message-props): <del> The message passed to InitiateWithIdempotentSend() is, as suggested by the name, considered to be idempotent (see msg-idempotent) regardless of declared message properties or defaults.  If protocol stacks supporting 0-RTT establishment with idempotent data are available on the Preconnection, then 0-RTT establishment may be used with the given message when establishing candidate connections.  For a non-idemponent initial message, or when the selected stack(s) do not support 0-RTT establishment, InitiateWithIdempotentSend is identical to Initiate() followed by Send(). </del>  Neither partial sends nor send batching are supported by <del> InitiateWithIdempotentSend(). </del>  <del> The Events that may be sent after InitiateWithIdempotentSend() are equivalent to those that would be sent by an invocation of Initate() followed immediately by an invocation of Send(), with the caveat that a send failure that occurs because the Connection could not be established will not result in a SendError separate from the InitiateError signaling the failure of Connection establishment. </del>  7.7.

7.6. For application-layer protocols where the Connection initiator also  <ins> sends the first message, the InitiateWithSend() action combines Connection initiation with a first Message sent. </ins> Without a message context (as in send-basic): With a message context (as in message-props):  <ins> Whenever possible, a messageContext should be provided to declare the message passed to InitiateWithSend as idempotent.  This allows the transport system to make use of 0-RTT establishment in case this is supported by the available protocol stacks.  When the selected stack(s) do not support transmitting data upon connection establishment, InitiateWithSend is identical to Initiate() followed by Send(). </ins> Neither partial sends nor send batching are supported by  <ins> InitiateWithSend(). </ins>  <ins> The Events that may be sent after InitiateWithSend() are equivalent to those that would be sent by an invocation of Initate() followed immediately by an invocation of Send(), with the caveat that a send failure that occurs because the Connection could not be established will not result in a SendError separate from the InitiateError signaling the failure of Connection establishment. </ins> 7.7.


9.1.6. <del> Integer This property specifies how long to wait before aborting a Connection during establishment, or before deciding that a Connection has failed after establishment.  It is given in seconds. </del>  9.1.7.

9.1.6.  <ins> This property specifies how long to wait before deciding that a Connection has failed after establishment. </ins> 9.1.7.


Abort terminates a Connection without delivering remaining data: <del> A ConnectionError can inform the application that the other side has aborted the Connection; however, there is no guarantee that an Abort will indeed be signaled. </del>  11.

Abort terminates a Connection without delivering remaining data:  <ins> A ConnectionError informs the application that data to could not be delivered after a timeout, or the other side has aborted the Connection; however, there is no guarantee that an Abort will indeed be signaled. </ins> 11.


events: Ready<> occurs when a Connection created with Initiate() or <del> InitiateWithIdempotentData() transitions to Established state. </del>  ConnectionReceived<> occurs when a Connection created with Listen() transitions to Established state.

events: Ready<> occurs when a Connection created with Initiate() or  <ins> InitiateWithSend() transitions to Established state. </ins> ConnectionReceived<> occurs when a Connection created with Listen() transitions to Established state.


Selection properties are represented as preferences, which can have one of five preference levels:  Internally, the transport system will first exclude all protocols and paths that match a Prohibit, then exclude all protocols and paths that do not match a Require, then sort candidates according to

This closes issue
Weren't we supposed to stop making PRs and issues until March 5? See Zahed's email to the TAPS list
NAME sorry – I did not read list mails since yesterday morning.
Yes, let's hold off on these until we move repos!
We discussed the use of a "Default" preference level that restores the system default in . In addition, we should check whether we really need to fix the default values for all Selection Properties in the API document or can make some of them to be "Implementation Specific".
Closed by PR
Looks good to me.

Selection properties are represented as preferences, which can have one of five preference levels: <ins> In addition, the pseudo-level "Default" can be used to reset the property to the default level used by the implementation.  This level will never show up when queuing the value of a preference - the effective preference must be returned instead. </ins> Internally, the transport system will first exclude all protocols and paths that match a Prohibit, then exclude all protocols and paths that do not match a Require, then sort candidates according to


Passive open is the Action of waiting for Connections from remote endpoints, commonly used by servers in client-server interactions. <del> Passive open is supported by this interface through the Listen Action: </del>  Before calling Listen, the caller must have initialized the Preconnection during the pre-establishment phase with a Local Endpoint specifier, as well as all properties necessary for Protocol Stack selection.  A Remote Endpoint may optionally be specified, to <del> constrain what Connections are accepted.  The Listen() Action consumes the Preconnection.  Once Listen() has been called, no further properties may be added to the Preconnection, and no subsequent establishment call may be made on the Preconnection. </del>  Listening continues until the global context shuts down, or until the <del> Stop action is performed on the same Preconnection: </del>  <del> After Stop() is called, the preconnection can be disposed of. </del>  The ConnectionReceived Event occurs when a Remote Endpoint has <del> established a transport-layer connection to this Preconnection (for </del>  Connection-oriented transport protocols), or when the first Message has been received from the Remote Endpoint (for Connectionless protocols), causing a new Connection to be created.  The resulting

This adds an explicit Listener object to the API ( to clarify behaviour of multi-streaming protocols ( clarify behaviour and enable re-use of Preconnections (
We talk about listen objects in architecture and implementation, but not in the API. Changes needed: Let return a Listener Move the the Listener Allow Preconnection to be used multiple times.
This issue popped up while discussing and seem to be a wired QUIC multi-streaming issue, possible affecting SCTP too): When a multi-streaming protocol like QUIC allows both ends to open new streams (e.g. by cloning the QUIC connection representing the stream), the both side needs a way to get a ConnectionReceived event for a new stream. That might result in the following weird pattern: I think this needs to be documented somehow and we may need to add a Selection Property do turn off this behaviour.
Calling is an active open. Once the connection is open, the peer can open new streams, but those would surely be events on the not on the .
NAME I am not sure with this one: assuming you have a bunch of ? The first one? What happens if I close the first one?
That's a good point, and I'm not sure I know the answer, but I don't think the should fire the events. A is a potential connection, yet to be instantiated, but these connections come from an already active connection. I've never been entirely comfortable with cloning a connection as the multi-streaming abstraction. This is perhaps the first scenario where it struggles though.
I do not understand the pattern in the example. You do not get a ConnectionReceived after an active open, you need a Listen?
NAME Your assumption is true for TCP, but not for multi-streaming transports like QUIC. With QUIC, you can indeed get additional TAPS connections (QUIC streams) based on an existing, initiated connections. The question is how to handle this. NAME A possible way out would be making itself is returned by an event then.
NAME the TAPS interface is the same weather you have TCP or QUIC underneath. For TAPS an active open generates a READY event not a ConnectionReceived? I do not think your example is a valid TAPS sequence.
NAME the Ready event is not shown in the example (it would be within the first ). The problem I raised is how to model the addition of streams to a multi-streaming connection. In case of QUIC, additional streams can be initiated by the server/listening side of the QUIC connection. If we model QUIC streams as TAPS connections, this results in events at the client (and server) side for each new QUIC stream.
NAME agree we could add , although it's a significant shift in the model. If we did that, we might also want to revisit as the way of creating a new stream on a connection, in favour of a method on . NAME did you implement this with QUIC? How does your implementation work?
I also see a problem with the communication pattern here. To me, modelling a stream as a TAPS connection means that for every new connection that a peer creates (be it a stream of an existing connection or not), I'll have to listen. So: if I expect 5 incoming connections, which may e.g. be 1 connection with 1 stream and 4 later-added streams below the API, I'll have to listen 5 times. What this also means is that the grouping notion should be a readable property - I believe that we currently only describe it as something that's actively created via clone(). Regarding code, no idea how NAME has done this, but I believe that the NEAT implementation is like I describe here. For more details on this specific aspect, see: URL
NAME We create a Listener from a Connection to handle inbound streams associated with the same parent transport connection. NAME Currently, our Listener object doesn't require calling Listen() for each new connection—you can get the event invoked many times, so it doesn't require knowing how many streams may be opened by the peer. In order to get back pressure, we're talking about having a window for how many new inbound connections will be allowed at a time.
Ok, that also sounds perfectly reasonable. Actually it seems that this (receiving multiple ConnectionReceived events on one Preconnection) is already supported by our current text, sorry for missing this! So... what is the problem we're discussing here - what do we need to change in the text? I think we need only the following: do we have a use case for one Listener getting multiple Connections without having these Connections grouped? (I guess not? Grouping is not a promise of multi-streaming.) If so, we need the ability to query whether connections are grouped (currently grouping is only created actively via "clone"). Otherwise, we can just statically say that all Connections that are created from the same Preconnections are grouped. some kind of ConnectionReceived event for the Rendezvous case, with text saying that all Connections created off the same PreConnection are grouped. (right?) a way to provide back pressure. Here, we already have PreConnection.Stop(). In the interest of keeping things simple, do we think that intelligently switching between a listening and a non-listening mode would be enough? If so, maybe we should have a call similar to Stop which stops listening, but does not dispose of the PreConnection, such that Listen could be called again. Maybe have an "End" call which stops and disposes, and let Stop only stop listening (because "Stop", to me, indicates only stopping but nothing else).
NAME This solution sounds very reasonable – I guess we should do it the same way for TAPS and add that as Text to the API NAME Some comments: It depends – if writing a server, you might want all streams of a multi-streaming connection grouped, but not all multi-streaming connections received through the same listener. So the behaviour wether to group should be a property of the Listener. I would not group connections received through the same Rendezvous (analogous to server-style listener). We might want to add a property to the listener
NAME I agree, but: just because groups may encompass more than the Connections from one Listener doesn't mean that it would be bad to always group the Connections from one Listener (i.e., group them among themselves, but maybe group them with others too). Besides, I think that wouldn't be the listener deciding anyway. Just to understand this, are you saying "no, see my argument for case 1" ? Then we're just discussing case 1, my answer is above. Otherwise I'd say: why not? yes ... but what do you mean with ? We have , just the semantics are not what I suggested. Regarding , I think that's a good idea - my own proposal was me overdoing "keep it simple, let's not add features". Nobody needs to use this unless they want to.
NAME I guess the answer really depends on what a connection group is for you. I always saw connection groups as an abstraction for multi-streaming connections (or their emulation) – therefore I see no use for grouping connections from multiple listeners. My opinion is auto-grouping for multi-streaming is fine, otherwise it is not. really falls out of 1 I want your semantics, but call it
NAME Me too. I can imagine other things ( this paper of ours comes to mind: URL ), but generally I agree and don't think we should complicate the API for this. But I'm getting confused: you wrote "you might want all streams of a multi-streaming connection grouped, but not all multi-streaming connections received through the same listener". That sounded to me like you want to support multiple streams, but from several listeners?! ACK Agreed!
NAME let me elaborate on this… You might want all streams of a multi-streaming connection grouped, e.g., all streams within a QUIC connection You might not want all multi-streaming connections (e.g., QUIC connections) received through the same Listener object grouped You definitely do not want all all streams of all QUIC connection received through one listener grouped (except if you have hierarchical groups that allows you to sort that out the cases above)
I agree with all this. Anyway I think it's a moot point: whether they're grouped or not is not up to the listener to decide? So grouping needs to be something that can be queried.
Ok – fair enough – but I still think the Listener is the right place to configure whether connections that come out of it should be grouped by default or not.
Not unless we have a concrete idea on what to do with this information inside the transport system. => I think no text update is needed as a result of this issue and lean towards closing it...
I don't think we really need a text update for the grouping, but for the original question. To address the handling of incoming streams in multi-streaming connections, I would like to have the solution NAME outlined reflected in the API.
One question on this, for NAME the description of your Listener object being able to accept multiple events, is that how it works in general or was that specif for a multi-streaming scenario? As specified I am not sure that our Listen action does not allow multiple ConnectionReceived events? The text says
NAME The listener object for all cases (both multi streaming and receiving brand-new transport connections) allows multiple events. I think the existing text is a bit ambiguous, but it seems that "listening continues" implies that the event can certainly fire again.
Revisit after is done
Regarding this text: This seems to imply that the Preconnection object, which may be full of many carefully tuned settings that could be useful for another Connection, is no longer usable. While I understand that the specific Preconnection cannot change for a Connection, this is inconvenient to the application. I see two good options to solve this: Make a deep copy of the Preconnection upon Initiate(), and say that a Preconnection may be used or changed but changes can no longer influence the Connection (this is what Network.framework currently does) Allow a URL() method to let the applications do the deep copy themselves when and if they want to re-use.
+1 to reusing the preconnection. Do you even need a deep copy. The connection is a new object that should be independent of the preconnection anyway, no? Another thought: Are there actually ways to get different connections out of the preconenction. E.g. you do racing and end up with two open connections and (suddenly) want to use both...?
I'd like to see this as well. To me it makes most sense to allow calling Initiate() on the same Preconnection multiple times to get multiple Connections, but not allow to change this Preconnection anymore after the first Initiate. This way it would be similar to Listen() and Rendezvous(), where we have a Preconnection that yields multiple Connections, and that cannot be changed anymore after Listen() or Rendezvous(). So here we already have a binding between the Preconnection and the Connections that come out of it. If the application wants to change the Preconnection before re-using it, I'd be in favor of letting it explicitly clone the Preconnection - not sure if we actually want to call it clone() though, because we already have Connection.Clone(), which creates a Connection Group, a completely different thing.
Why do you think it should not be allowed that a preconnection can be changed after the first initiate? If you don't change it you should get the same kind of connection, if you change it you might get something different. Your choice!
I wanted the API contract to be similar for different forms of Connection establishment. But I may be overthinking this.
First, I like the idea of reusing Preconnections. I am not sure whether we should define now whether they should be changeable after the first initiation. There might be kinds of Preconnections where this is a good idea, there might be others where it is not. I anticipate one can realize connection pools as a sub-class of Preconnection. In this case, in such cases, it should not be possible to change a Preconnection.
So the difference is if you think you morph a preconnection into a connection, or if the preconnection create the connection. i think the first think does not make sense because their are two completely different things; they have not actions or events in common.
NAME The morphing one has its beauty for modeling TCP fastopen / 0-RTT data.
Whether it makes sense to re-use a perhaps depends on how fully specified it is? Reusing a completely specified , that will just re-open an identical 5-tuple as an existing might not make sense. Reusing a partially specified , e.g., with the source port left as a wildcard to new connections can open without conflicts, seems reasonable.
NAME right, using the exact same set of fully-specified properties isn't going to work. But having a partially specified one and copying it, or modifying one that was used (by switching out the Remote, etc) would be useful.
This might work better the other way -- on , the Preconnection corresponding to the initiated/initiating connection gets deep-copied into the new connection, leaving the existing Preconnection in the state that it was. That deep copy, inside the connection, cannot be reused, but the existing one could be. (This probably only works for connections on which you . turns the preconnection into a listener from which multiple , each of which will have their own deep copy of the listener, will spawn. might be even weirder, but there's a potentially bigger win to allowing reuse, but I don't quite have my head around how it would work)
So i think there is actually not that much too deep copy because a preconception is not a super class of a connection. At the moment when you call initiate or rendezvous the preconception should create a connection and store all information regarding this connection in the connection object which is later returned. The only thing that needs "copying" is the properties but you need to create a new object anyway because preconnection properties have preferences and connection properties not but have to be marked as mutable or unmutable. These two things are also not the same. So the only that that's left to copy maybe are the endpoints. Not sure if the preconnection and connection both have a copy of the endpoints or if an endpoint only exists once and both have a reference (which means if the endpoint gets somehow updated that's relevant for both) or maybe even the connection does not need a reference to the endpoint anymore...?
NAME right – but I don't know a way of specifying "a is consumed if fully specified, else may be reusedin any current programming language. Maybe tracking lifetimes so closely doesn't matter though, and we can just write this in the draft.
I have no problem with an Interface where some Preconnections can be reused and others can not. That makes a pretty nice case for -- preconnection reuses itself for multiple incoming connections. For ` I see this API-wise as some kind of listen called at both sides.
Side meeting says we can reuse the initiate call. Implementation should specify that a deep copy is made on Initiate() or Listen()
Will be trivial to fix after is done
Sorry to reopen an old issue, but when reading the current API draft, I noticed that it still says that reusing the Preconnection is possible for Listeners, but not possible for Initiate() and Rendezvous(). For example, see Section 6.1: "The Initiate() Action consumes the Preconnection […]" From what I read in this issue, I think Preconnections should be allowed to be reused for Initiate() and Rendezvous() as well (possibly with a note on deep-copy).
This looks just right to me, thanks a lot for doing this! In particular having read again, I believe that NAME should definitely have the last word on this one. So I'll go with whatever NAME says.

Passive open is the Action of waiting for Connections from remote endpoints, commonly used by servers in client-server interactions.  <ins> Passive open is supported by this interface through the Listen Action and returns a Listener object: </ins> Before calling Listen, the caller must have initialized the Preconnection during the pre-establishment phase with a Local Endpoint specifier, as well as all properties necessary for Protocol Stack selection.  A Remote Endpoint may optionally be specified, to  <ins> constrain what Connections are accepted.  The Listen() Action returns a Listener object.  Once Listen() has been called, properties added to the Preconnection have no effect on the Listener and the Preconnection can be disposed of or reused. </ins> Listening continues until the global context shuts down, or until the  <ins> Stop action is performed on the Listener object: </ins>  <ins> After Stop() is called, the Listener can be disposed of. </ins> The ConnectionReceived Event occurs when a Remote Endpoint has  <ins> established a transport-layer connection to this Listener (for </ins> Connection-oriented transport protocols), or when the first Message has been received from the Remote Endpoint (for Connectionless protocols), causing a new Connection to be created.  The resulting


ready to use as soon as it is passed to the application via the event. <del> A ListenError occurs either when the Preconnection cannot be fulfilled for listening, when the Local Endpoint (or Remote Endpoint, if specified) cannot be resolved, or when the application is prohibited from listening by policy. </del>  <del> A Stopped event occurs after the Preconnection has stopped listening. </del>  6.3.

ready to use as soon as it is passed to the application via the event.  <ins> A ListenError occurs either when the Properties of the Preconnection cannot be fulfilled for listening, when the Local Endpoint (or Remote Endpoint, if specified) cannot be resolved, or when the application is prohibited from listening by policy. </ins>  <ins> A Stopped event occurs after the Listener has stopped listening. </ins> 6.3.


6.4. <del> Groups of Connections can be created using the Clone Action: </del>  Calling Clone on a Connection yields a group of two Connections: the parent Connection on which Clone was called, and the resulting cloned

6.4.  <ins> Entangled Connections can be created using the Clone Action: </ins> Calling Clone on a Connection yields a group of two Connections: the parent Connection on which Clone was called, and the resulting cloned


on.  Connections in a Connection Group share all Protocol Properties that are not applicable to a Message.  Changing one of these Protocol Properties on one Connection in the group changes it for all others.  Per-Message Protocol Properties, however, are not entangled.  For example, changing "Timeout for

on.  Connections in a Connection Group share all Protocol Properties that are not applicable to a Message. <ins> In addition, incoming entangled Connections can be received by creating a Listener on an existing connection: </ins> Changing one of these Protocol Properties on one Connection in the group changes it for all others.  Per-Message Protocol Properties, however, are not entangled.  For example, changing "Timeout for