CESNET / netopeer2

NETCONF toolset
BSD 3-Clause "New" or "Revised" License
300 stars 188 forks source link

cert-to-name algo is picking rfc822-name from client.crt instead of ca.crt #1596

Open rakichinni opened 3 months ago

rakichinni commented 3 months ago

Hi,

Below snippet taken from ietf-x509-cert-to-name@2014-12-10.yang. It says, Once a matching cert-to-name list entry has been found, the map-type is used to determine how the name associated with the certificate should be determined

list cert-to-name {
  key id;
  description
    "This list defines how certificates are mapped to names.
     The name is derived by considering each cert-to-name
     list entry in order.  The cert-to-name entry's fingerprint
     determines whether the list entry is a match:

     1) If the cert-to-name list entry's fingerprint value
        matches that of the presented certificate, then consider
        the list entry a successful match.

     2) If the cert-to-name list entry's fingerprint value
        matches that of a locally held copy of a trusted CA
        certificate, and that CA certificate was part of the CA
        certificate chain to the presented certificate, then
        consider the list entry a successful match.

    **Once a matching cert-to-name list entry has been found, the
    map-type is used to determine how the name associated with
    the certificate should be determined**.  See the map-type
    leaf's description for details on determining the name value.
    If it is impossible to determine a name from the cert-to-name
    list entry's data combined with the data presented in the
    certificate, then additional cert-to-name list entries MUST
    be searched to look for another potential match.

We generated certificates for ca, client and server. certs.zip CA and client certificates are generated with subjectAltName's rfc822Name and outputs as below.

~/certs>openssl x509 -in ca.crt -noout -text|grep -i mail
                DNS:abc.com, DNS:www.abc.com, email:ca@abc.com
~/certs>openssl x509 -in client.crt -noout -text|grep -i mail
                DNS:abce.com, DNS:www.abc.com, email:client@abc.com
~/certs>openssl x509 -in ca.crt -fingerprint -noout
SHA1 Fingerprint=48:C6:CB:98:D4:C9:F3:41:ED:46:CB:88:E0:CA:BD:E8:79:EB:E7:9E

tls-keystore.xml, tls-truststore.xml and tls-listen.xml are zipped and attached here. certs-conf.zip

ietf-netconf-server is configured with ca certificate's fingerprint.

            <cert-maps>
              <cert-to-name>
                <id>1</id>
                <fingerprint>02:48:C6:CB:98:D4:C9:F3:41:ED:46:CB:88:E0:CA:BD:E8:79:EB:E7:9E</fingerprint>
                <map-type xmlns:x509c2n="urn:ietf:params:xml:ns:yang:ietf-x509-cert-to-name">x509c2n:san-rfc822-name</map-type>
              </cert-to-name>
            </cert-maps>

Logs from netopeer2-server

netopeer2-server|INFO "netopeer2-server-log" [INF]: LN: Accepted a connection on 0.0.0.0:6513 from 0.0.0.0:48420.
netopeer2-server|INFO "netopeer2-server-log" [INF]: SR: Session 73 (user "root", CID 7) created.
netopeer2-server|INFO "netopeer2-server-log" [INF]: SR: Session 74 (user "root", CID 7) created.
netopeer2-server|INFO "netopeer2-server-log" [INF]: SR: Session 75 (user "root", CID 7) created.
netopeer2-server|INFO "netopeer2-server-log" [INF]: LN: Cert verify: depth 1.
netopeer2-server|INFO "netopeer2-server-log" [INF]: LN: Cert verify: subject: /CN=abccacn.
netopeer2-server|INFO "netopeer2-server-log" [INF]: LN: Cert verify: issuer:  /CN=abccacn.
netopeer2-server|INFO "netopeer2-server-log" [INF]: LN: Cert verify CTN: entry with a matching fingerprint found.
netopeer2-server|INFO "netopeer2-server-log" [INF]: LN: Cert verify CTN: new client username recognized as "client@abc.com".
netopeer2-server|INFO "netopeer2-server-log" [INF]: LN: Cert verify: depth 0.
netopeer2-server|INFO "netopeer2-server-log" [INF]: LN: Cert verify: subject: /CN=abcclient.
netopeer2-server|INFO "netopeer2-server-log" [INF]: LN: Cert verify: issuer:  /CN=abccacn.
netopeer2-server|INFO "netopeer2-server-log" [INF]: LN: Client certificate verified.

From logs (and ietf-netconf-monitoring data dumps) it is clear that, 'username' is derived from client certificate as client@abc.com

Expectation: 'username' must be derived from ca certificate which is ca@abc.com which is as per yang statements mentioned above.

Please clarify if our understanding of cert-to-name is not correct.

Versions used libnetconf2: 2.1.25 netopeer2-server: 2.1.41 sysrepo: 2.27 libyang: 2.0.263

Roytak commented 3 months ago

Hello,

our understanding of the cert-to-name process is that the client's username is always determined from the client's (peer's) certificate. The YANG description is not very clear in this regard. Furthermore, with your expectations different clients would be able to share the same username and we did not think this was an actual use case. Also you are using quite an old version and if I recall correctly there have been some improvements to the cert-to-name mechanism, yet this logic of obtaining the username solely from the peer's certificate remains.

We may have interpreted the YANG description incorrectly and you may be right. My question is why would you need to obtain the username from a CA certificate instead of the peer's? Are there any resources that would further support your expectations?

rakichinni commented 3 months ago

Thank you for response.

Security administrators are encouraged to make use of
certificates with subjectAltName fields that can be mapped to
names so that a single root CA certificate can allow all
child certificates' subjectAltName fields to map directly to
a name via a 1:1 transformation.";

RFC 6353 (section 7) and cert-to-name yang pointing to use CA to have all child certificates to have common username/privileges.

Use case is to have a common privileges if child certificates signed by CA1 for example.

rakichinni commented 3 months ago

@Roytak Pls let us know if you have any comments or suggestions.

Making changes in nc_tls_cert_to_name and nc_tlsclb_verify to derive name as per the RFC 6353 (section 7) and cert-to-name yang description. I will update once validated.

Roytak commented 3 months ago

Hi, seems like you are right and it should work like you expected. I started working on the changes and they should be in the devel branch soon.

alekssprg commented 2 months ago

@Roytak Hello. Excuse me, I check this changes and can't understand. How I can get username from client certificate if it's fingerprint is absent on server? libnetconf2 tried to get SAN from CA certificate, because I use it's fingerprint in cert-to-name. And this CA certificate don't contains SAN in my case. But I want to have possibility to connect from different clients with different usernames.

michalvasko commented 2 months ago

Then you should use a different cert-to-name mapping. If nothing else, you can always use specified and just set a specific username for each client certificate.

alekssprg commented 2 months ago

Thanks, but all of this cases of cert-to-name mapping expect information about client certificates. If I have only CA certificate on server before client will be connected, in this case I can't get different username for different clients, right?

michalvasko commented 2 months ago

No, it seems with the current YANG modules you cannot.

alekssprg commented 2 months ago

Thank you