Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support SRV-ID #1309

Closed
languitar opened this issue Dec 28, 2015 · 20 comments
Closed

Support SRV-ID #1309

languitar opened this issue Dec 28, 2015 · 20 comments

Comments

@languitar
Copy link

languitar commented Dec 28, 2015

Certificates for certain purposes should contain additional attributes, e.g. for XMPP, cf. this and that. It would be nice if the CA supported issuing certificates containing such attributes from CSRs without stripping the recommended attributes.

This is a follow up issue of certbot/certbot#2032

@hlandau
Copy link
Contributor

hlandau commented Jan 22, 2016

This should probably be retitled "Support SRV-ID". Which would indeed be nice.

I suppose certificates for any SRV-ID should be offered if hostname control is proven. You can still control the dissemination of certificates to different daemons, giving SRV-ID a small amount of meaning.

@jsha jsha changed the title Support additional attributes in CSRs, e.g. for XMPP Support SRV-ID Jan 25, 2016
@jschlyter
Copy link

If boulder has an authorization for DNS-name XXX, I believe should allow X509v3 Subject Alternative Names in the following form:

  • id-on-dnsSRV;UTF8:_SOMETHING.$XXX

For XMPP, this is:

  • id-on-dnsSRV;UTF8:_xmpp-client.$DOMAIN
  • id-on-dnsSRV;UTF8:_xmpp-server.$DOMAIN

@ge0rg
Copy link

ge0rg commented Mar 4, 2016

SRV-ID support is a major requirement for allowing XMPP-server-as-a-service implementations. If I am the owner of company.example and I want cheapxmpp.example to run my XMPP service, currently I need to provide them with a key/certificate that they could use to impersonate the company.example webserver.

If the owner of company.example was able to get a cert with SRV-ID SANs _xmpp-client.company.example and _xmpp-server.company.example (but no DNS-IDs / hostname CN), that cert could be used for delegating XMPP in a secure way.

@hlandau
Copy link
Contributor

hlandau commented Mar 4, 2016

@ge0rg This is interesting. This suggests that rather than granting SRV-ID when hostname control is proven, as I suggested above, the ACME protocol should be extended so that authorization for a SRV-ID can be obtained explicitly.

There is one hiccup with challenges; a SRV-ID does not specify a transport layer protocol but SRV does, so this change to the spec would need to specify some mapping for the purposes of name resolution for the purposes of challenge verification. A simple solution would be to always use TCP, which makes sense since all challenge methods which connect to the host use it anyway.

@ge0rg
Copy link

ge0rg commented Mar 4, 2016

@hlandau I consciously left out ACME from my prior comment to reduce confusion. The alternative approach would be indeed to extend ACME in a way that allows limiting domain authorization to a certain service type, using that type of service for challenge verificattion in the first place, i.e. make the ACME server contact the XMPP server via XMPP to obtain an XMPP-only certificate. But this looks like a much bigger implementation burden to me, compared to letting the domain owner do the hard work. On the other hand, it would make certificate automation feasible.

I haven't looked deeply into DNS-based verification yet, but I could also imagine something along the lines of:

  1. I create _xmpp-server._tcp.company.example IN SRV ... xmpp.cheapxmpp.example
  2. CheapXMPP requests an ACME DNS-based verification for _xmpp-server._tcp.company.example
  3. The ACME server follows the SRV record and expects the challenge response to be located under _acme-challenge.xmpp.cheapxmpp.example/TXT
  4. The ACME server allows CheapXMPP to obtain certificates for SRV-ID _xmpp-server.company.example only, not for DNS-ID company.example

[...] a SRV-ID does not specify a transport layer protocol but SRV does, [...]

Indeed, SRV-ID is protocol agnostic, but I think you are right that it makes sense to use TCP for challenge verification, as it is less susceptible to address manipulation attacks.

@rhansen
Copy link

rhansen commented Mar 9, 2016

I understand that this issue was not filed against the ACME protocol spec, but despite the risk of confusion I think it's worth discussing how the protocol would interact with this feature. Obviously the CA shouldn't blindly trust SRVName subject alternative names in CSRs, so the protocol must be involved somehow.

  1. The ACME server follows the SRV record and expects the challenge response to be located under _acme-challenge.xmpp.cheapxmpp.example/TXT

I'm assuming that in your example the ACME server chose _acme-challenge.xmpp.cheapxmpp.example because xmpp.cheapxmpp.example is the name in the _xmpp-server._tcp.company.example SRV record. Is that correct?

If so, this would require cheapxmpp.example to set up that DNS record. Setting up that DNS record might not be feasible if cheapxmpp.example is a 3rd party (outsourced service).

Fortunately, it is not necessary to involve cheapxmpp.example because the name of the target in the SRV record doesn't matter when validating the certificate. Theoretically, company.example could later switch outsourced XMPP services to a different 3rd party, change the SRV records, and still use the same certificate.

Validating a request for a SRVName SAN of _Service.example.com is really the same as validating control over example.com, so the same mechanism used to issue ordinary example.com certificates can be used.

How about this procedure:

  1. for each SRVName SAN in the CSR:
    1. verify that the string follows the pattern _Service.example.com
    2. do the same validation that is normally done for example.com
    3. if validation fails, reject the entire CSR
  2. for each dNSName SAN in the CSR:
    1. do the normal validation for the domain name
    2. if validation fails, reject the entire CSR
  3. if the requested Subject has the form cn=example.com:
    1. do the normal validation of example.com
    2. if validation fails, reject the entire CSR
  4. if there are no dNSName SANs in a CSR and the Subject does not have the form cn=example.com, do NOT use a Subject of the form cn=example.com in the resulting certificate and do NOT add a dNSName SAN (to prevent an outsourced XMPP service from being able to impersonate the customer's other services)
  5. if the Subject has the form cn=example.com, add a dNSName SAN for example.com if one does not already exist
  6. if there is one or more dNSName SANs in the CSR and the Subject does not have the form cn=example.com, then set the Subject to have the form cn=example.com where example.com is the DNS name in the first dNSName SAN

Example

Suppose a company owns example.com and has Jabber IDs of the form user@example.com. They have the following DNS records for the XMPP service:

_xmpp-client._tcp.example.com            IN SRV 0 0 5222 xmpp.example.com
_xmpp-server._tcp.example.com            IN SRV 0 0 5269 xmpp.example.com
_xmpp-server._tcp.conference.example.com IN SRV 0 0 5269 xmpp.example.com
_xmppconnect.example.com                 IN TXT "_xmpp-client-xbosh=https://xmpp.example.com:5280/http-bind"

The entire ACME process could look like this:

  1. the user configures DNS with these records:

    _acme-verify._tcp.example.com            IN SRV 0 0 49152 acme.example.com
    _acme-verify._tcp.xmpp.example.com       IN SRV 0 0 49152 acme.example.com
    _acme-verify._tcp.conference.example.com IN SRV 0 0 49152 acme.example.com
    
  2. the user runs the ACME client on acme.example.com and configures it to expect challenges on port 49152

  3. the ACME client registers with the ACME server

  4. the ACME client starts a challenge response daemon listening on port 49152

  5. for each Name in xmpp.example.com, example.com, conference.example.com:

    1. the ACME client requests validation of Name
    2. the ACME server:
      1. does a DNS SRV lookup on _acme-verify._tcp.Name and gets back a reply of acme.example.com port 49152
      2. connects to acme.example.com port 49152
      3. issues a challenge
      4. validates the response
      5. grants authorization to use the identifier Name to the client
      6. reports success to the client
  6. the ACME client stops listening on port 49152

  7. the ACME client submits a CSR that looks like this:

    • Subject: cn=xmpp.example.com
    • SANs:
      • dNSName: xmpp.example.com
      • SRVName: _xmpp-client.example.com
      • SRVName: _xmpp-server.example.com
      • SRVName: _xmpp-server.conference.example.com
  8. the ACME server parses the CSR and verifies that the client has been given authorization to use the names xmpp.example.com, example.com, and conference.example.com

  9. the ACME server issues a certificate to the client containing the requested Subject and SANs

@ge0rg
Copy link

ge0rg commented Mar 10, 2016

@rhanden I'm not really sure where you are heading to. The issue I want to solve is delegation of (XMPP) service operations without exposing a full DNS-ID certificate to third parties. I see two alternative approaches to solve this problem:

Domain Owner obtains Certificate

The domain owner of company.example requests a certificate with an SRV-ID SAN and no DNS-ID/hostname CN, i.e. based on a CSR from the actual XMPP service provider.

The domain owner already has proven ownership (by means that are out of scope for the discussion). Therefore they are eligible to a certificate containing any valid SRV-IDs for their domain, as the SRV-ID is a weaker ownership assertion than the DNS-ID they can get under the currrent rules.

This approach does not require touching the ACME protocol, but it can not be as easily automated, as the domain owner and service operator need to collaborate for each new certificate. It also precludes the service operator from getting a single certificate containing SRV-IDs for multiple customers. Still, this can be probably achieved with a bunch of cronjobs at both parties, and I would consider this a reasonable short-term solution to the problem.

The only possible restriction I can see here is a whitelist of allowed service names that can be prepended to the domain part.

Service Operator obtains Certificate

Of course it would be much easier (to automate) if the service operator (cheapxmpp.example) can directly get appropriate certificates from the CA. However, if we allow the service operator to authenticate for the domain, they could easily get a DNS-ID certificate that they could use to attack the domain's other services (web, email, ...).

Therefore I sketched a proposal to allow the service operator to prove "service ownership" to the CA, i.e. "I am operating the XMPP service(s) for company.example". This service ownership in turn will permit the operator to directly request SRV-ID certificates for the given service from the CA, but not a DNS-ID certificate for company.example.

Such a feature is obvioulsy much more complex to pull off, as it requires multiple changes in the design:

  1. The domain owner must indicate service delegation to the CA. DNS SRV records seem appropriate as they provide the same level of security as existing domain ownership verifications, and their purpose is service delegation.
  2. The ACME ecosystem must be extended to support "service ownership" in addition to "domain ownership" verification.
  3. The certificate issuing logic must be extended to only allow a given SRV-ID in a CSR if the requesting entity has proven either domain ownership or service ownership of that specific service.

@rhansen Your proposal sounds like it implements another way for a client to prove domain ownership, by using a new DNS SRV record to tell the ACME server where the ACME client is located. It looks off-topic for issuing SRV-IDs and for the service delegation problem, so I'd suggest to put it into a separate ticket against ACME or boulder.

@rhansen
Copy link

rhansen commented Mar 10, 2016

@rhansen I'm not really sure where you are heading to. The issue I want to solve is delegation of (XMPP) service operations without exposing a full DNS-ID certificate to third parties.

I believe the proposal I made (the enumerated list above the "Example" section in my comment) addresses this on the server (boulder) side. It assumes the "domain owner obtains the certificate" approach. (The client would be responsible for ensuring that the CSR it sends to the server does not include any dNSName SANs, but that's out of scope for this issue.)

Therefore I sketched a proposal to allow the service operator to prove "service ownership" to the CA, i.e. "I am operating the XMPP service(s) for company.example". This service ownership in turn will permit the operator to directly request SRV-ID certificates for the given service from the CA, but not a DNS-ID certificate for company.example.

Ahh, now I understand why your earlier comment has the server checking _acme-challenge.xmpp.cheapxmpp.example/TXT. I apologize for not understanding that you were going for the "service operator obtains certificate" approach in your earlier comment.

@rhansen Your proposal sounds like it implements another way for a client to prove domain ownership, by using a new DNS SRV record to tell the ACME server where the ACME client is located.

The part of my comment in the "Example" section is not intended to be a proposal, just an example of how the "domain owner obtains certificate" approach could work for XMPP. The existing HTTP-01 and TLS-SNI-01 identifier validation challenges don't really work well for XMPP, so I made up a new one to have a better story.

It looks off-topic for issuing SRV-IDs and for the service delegation problem,

Thinking about it more, the identifier validation challenge I made up in my example could work for the "service operator obtains certificate" approach. Whether it would work depends on how the hypothetical "acme-verify" protocol implied by the example would operate. That protocol could be designed so that the host named by the _acme-verify._tcp.company.example SRV record sends the ACME server a message that means, "I am delegating DNS name validation of company.example to cheapxmpp.example, but only for SRVName SANs for services _xmpp-server and _xmpp-client." The ACME server would then need to remember the delegation along with its limited scope when issuing a certificate to the cheapxmpp.example client.

so I'd suggest to put it into a separate ticket against ACME or boulder.

Looks like someone has already proposed something similar but not as potentially expressive: ietf-wg-acme/acme/pull/83

@ge0rg
Copy link

ge0rg commented Mar 11, 2016

I believe the proposal I made (the enumerated list above the "Example" section in my comment) addresses this on the server (boulder) side.

Ah, indeed. I don't know enough about boulder's internal processing when CN or SANs from the CSR are considered "incomplete", so the clarifications in 4.-6. do make sense.

[service operator obtains certificate]

That protocol could be designed so that the host named by the _acme-verify._tcp.company.example SRV record sends the ACME server a message that means, "I am delegating DNS name validation of company.example to cheapxmpp.example, but only for SRVName SANs for services _xmpp-server and _xmpp-client." The ACME server would then need to remember the delegation along with its limited scope when issuing a certificate to the cheapxmpp.example client.

That means adding delegation of ownership validation into the ACME protocol?

I'd rather keep it "simple" by using the expressiveness of already deployed protocols. My first idea was for the ACME server to follow SRV records during TXT-based ownership validation (#1309 (comment)).

Another possibility would be to "restrict" the delegation by inserting protocol tokens into the proposed SRV validation (ietf-wg-acme/acme#83) record: Let the SRV record be constructed as _acme-challenge._http-01._tcp._xmpp-client.company.example (give or take another _tcp) and point to CheapXMPP's ACME client.

Both variants should work without changing the ACME protocol (provided that _xmpp-client.company.example is a valid domain token), and the ACME server does not need to keep additional state when performing a service ownership check.

@rhansen
Copy link

rhansen commented Mar 13, 2016

That means adding delegation of ownership validation into the ACME protocol?

Yes, but the concept of delegation only needs to exist in the identifier validation challenge protocol. (HTTP-01 and DNS-01 already support delegation. For HTTP-01, just do a 301 or 302 redirect to the 3rd party, or if ietf-wg-acme/acme#83 is accepted then use that SRV record to delegate. For DNS-01, create a CNAME pointed at the 3rd party.)

I'd rather keep it "simple" by using the expressiveness of already deployed protocols.

It may be possible to use the existing DNS identifier type to handle SRV, but care would have to be taken to ensure that the specific mechanism for handling SRV is safe, reliable, and does not get in the way of anything else. I'm worried that reusing the existing DNS name identifier type for SRVName SANs would result in a problematic or complex protocol, but maybe there's a way to do it that's simple and robust.

I'm guessing that in the long run it would be better to introduce a new identifier type specifically for SRV (where the type is a tuple consisting of a service name and a DNS name, like {"xmpp-client", "company.example"}) and use that type to get SRVName SANs.

My first idea was for the ACME server to follow SRV records during TXT-based ownership validation (#1309 (comment)).

Following SRV records means the owner can't prevent cheapxmpp.example from obtaining a certificate in company.example's name. I think the validation protocol should require the name owner to explicitly delegate if delegation is desired. CNAME records can solve that problem.

Another possibility would be to "restrict" the delegation by inserting protocol tokens into the proposed SRV validation (ietf-wg-acme/acme#83) record: Let the SRV record be constructed as _acme-challenge._http-01._tcp._xmpp-client.company.example (give or take another _tcp) and point to CheapXMPP's ACME client.

Yes, that would work. That record could even be a CNAME to some cheapxmpp.example name, and they can resolve the record to whatever ACME client they want.

There should still be some way to communicate to the CA that the resulting cert should have _xmpp-client.company.example in a SRVName SAN, not in a dNSName SAN or in the subject, but it's fail-safe: If the CA accidentally put _xmpp-client.company.example in the subject and in a dNSName SAN it wouldn't give cheapxmpp.example the ability to impersonate other company.example services.

Both variants should work without changing the ACME protocol (provided that _xmpp-client.company.example is a valid domain token),

It does require a change: The CA needs to know that these are requests for SRVName SANs.

It could assume this from the leading _ in the name, but that's dangerous because it prevents a leading _ in DNS names from being used for other (non-SRV) purposes. Or it could test whether _Service._Protocol.Name resolves, but what does it choose for _Protocol? If it only tests _tcp and _udp then that makes it harder for some new protocol to gain acceptance.

Regardless of the approach, the specific behavior would need to be documented in the protocol spec.

and the ACME server does not need to keep additional state when performing a service ownership check.

That's should be true for any delegation mechanism. There's no need to remember anything extra when following a redirection.

@rhansen
Copy link

rhansen commented Mar 14, 2016

The following is a proposal described in the form of an example scenario. In this scenario, I assume:

  • company.example wants to outsource their XMPP service to cheapxmpp.example
  • company.example wants cheapxmpp.example to take care of obtaining certificates
  • http-01: Use client's SRV records for http validation ietf-wg-acme/acme#83 has been accepted
  • there is a new ACME identifier type called "SRV name" that is a {Service, Name} tuple
  • validating a SRV name of the form {Service, Name} is the same as validating the DNS name _Service.Name, except successful validation only authorizes the client to add a SRVName SAN of _Service.Name to a certificate (the DNS name _Service.Name can't be used in the subject or in any dNSName SANs unless separately authorized via a DNS name request)

These are the steps taken to set up the XMPP service with a certificate:

  1. company.example creates the following DNS records for its XMPP service:

    $ORIGIN company.example.
    _xmpp-client._tcp            IN CNAME _xmpp-client._tcp.company.example._customers.cheapxmpp.example.
    _xmpp-server._tcp            IN CNAME _xmpp-server._tcp.company.example._customers.cheapxmpp.example.
    _xmpp-server._tcp.conference IN CNAME _xmpp-server._tcp.conference.company.example._customers.cheapxmpp.example.
    _xmppconnect                 IN CNAME _xmppconnect.company.example._customers.cheapxmpp.example.
    
  2. company.example creates the following DNS records to allow cheapxmpp.example to obtain the relevant certificates on company.example's behalf:

    $ORIGIN company.example.
    _acme-challenge-http._tcp._xmpp-client            IN CNAME _acme-challenge-http._tcp._xmpp-client.company.example._customers.cheapxmpp.example.
    _acme-challenge-http._tcp._xmpp-server            IN CNAME _acme-challenge-http._tcp._xmpp-server.company.example._customers.cheapxmpp.example.
    _acme-challenge-http._tcp._xmpp-server.conference IN CNAME _acme-challenge-http._tcp._xmpp-server.conference.company.example._customers.cheapxmpp.example.
    
  3. cheapxmpp.example creates the following DNS records for company.example:

    $ORIGIN company.example._customers.cheapxmpp.example.
    _xmpp-client._tcp                                 IN SRV 0 0 5222 cheapxmpp.example.
    _xmpp-server._tcp                                 IN SRV 0 0 5269 cheapxmpp.example.
    _xmpp-server._tcp.conference                      IN SRV 0 0 5269 cheapxmpp.example.
    _xmppconnect                                      IN TXT "_xmpp-client-xbosh=https://cheapxmpp.example:5280/http-bind"
    _acme-challenge-http._tcp._xmpp-client            IN SRV 0 0 80 acme.cheapxmpp.example.
    _acme-challenge-http._tcp._xmpp-server            IN SRV 0 0 80 acme.cheapxmpp.example.
    _acme-challenge-http._tcp._xmpp-server.conference IN SRV 0 0 80 acme.cheapxmpp.example.
    
  4. for each {Service, Name} SRV name in {xmpp-client, company.example}, {xmpp-server, company.example}, and {xmpp-server, conference.company.example}:

    1. cheapxmpp.example's ACME client contacts the ACME server and requests authorization to use {Service, Name}
    2. the ACME server issues a challenge to the ACME client
    3. the ACME client prepares http://acme.cheapxmpp.example:80/.well-known/acme-challenge/xx_token_xx with the appropriate challenge data
    4. the ACME client informs the ACME server that it is responding to the http-01 challenge
    5. the ACME server resolves the _acme-challenge-http._tcp._Service.Name SRV record to acme.cheapxmpp.example port 80
    6. the ACME server fetches http://acme.cheapxmpp.example:80/.well-known/acme-challenge/xx_token_xx to validate the challenge response
    7. the ACME server grants an authorization to use the SRV name {Service, Name}
  5. the ACME client requests a certificate with the following form:

    • subject: cn=cheapxmpp.example (for BOSH connections)
    • SANs:
      • dNSName: cheapxmpp.example (for BOSH connections)
      • SRVName: _xmpp-client.company.example
      • SRVName: _xmpp-server.company.example
      • SRVName: _xmpp-server.conference.company.example
  6. for the subject CN and each dNSName SAN in the CSR, the ACME server verifies that the client is authorized to use the DNS name (I assume that the DNS name cheapxmpp.example has been previously authorized because it is used in certificates for other customers)

  7. for each SRVName SAN of the form _Service.Name in the CSR, the ACME server verifies that the client is authorized to use the SRV name {Service, Name}

  8. the ACME server issues the desired certificate and sends it to the ACME client

@jsha
Copy link
Contributor

jsha commented Jun 4, 2016

This is not on the immediate roadmap, so closing the Boulder issue, but we may consider in the future.

@jsha jsha closed this as completed Jun 4, 2016
@nbraud
Copy link

nbraud commented Sep 30, 2016

@jsha Would a concrete proposal (protocol spec and boulder patches) be considered for merging, or does “not in the immediate roadmap” mean “patches aren't welcome”?

@rolandshoemaker
Copy link
Contributor

@nbraud The CAB Fourm Baseline regulations disallow SRVName type otherNames to be included in the subjectAltName extension which means while Boulder could add support for this Let's Encrypt would be unable to use it, which makes the prospect of having that extra code in the tree quite unappealing.

There has been some recent movement on changing the rules so SRV-IDs can be used, but until that actually happens I don't think we'll accept any patches that add this feature.

@nbraud
Copy link

nbraud commented Sep 30, 2016

@rolandshoemaker Oh, thanks. I had a look at the CA/B Baseline Requirements, but missed 7.1.4.2.1

I might have a stab at it (assuming the requirements are changed per proposal in the ballot), but obviously this cannot land in production without the CA/B rule change being effective.

@Zash
Copy link

Zash commented Feb 1, 2017

Don't the CA//B Fourm Baseline regulations apply primarily to the web, not other TLS using protocols and services?

@ge0rg
Copy link

ge0rg commented Mar 2, 2017

@Zash the regulations apply to CAs that want to issue certificates for the web. This leads to the unfortunate situation that if LE wants to be accepted by browsers, it must comply with the Baseline regulations and thus must not issue certificates with SRVNames for anybody.

@Zash
Copy link

Zash commented Jan 12, 2021

#1309 (comment)

This is not on the immediate roadmap [in 2016], so closing the Boulder issue, but we may consider in the future.

It's the future, any chance you may reconsider?

@aarongable
Copy link
Contributor

The CABForum Baseline Requirements still prohibit issuance of certificates whose subjectAltName field contains anything other than dNSNames or a iPAddresss. We cannot issue certificates with SRVName SANs.

@rhansen
Copy link

rhansen commented Sep 22, 2021

Relevant CAB forum issue: cabforum/servercert#268

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants