On 7 February 2014 08:32, <breser_at_apache.org> wrote:
> Author: breser
> Date: Fri Feb 7 04:32:50 2014
> New Revision: 1565531
>
> URL: http://svn.apache.org/r1565531
> Log:
> ra_serf: Do not compare the CommonName of a certificate if there are
> subjectAltName extensions of the DNS type when validating the certificate
> as per RFC 2818.
>
> * subversion/libsvn_ra_serf/util.c
> (ssl_server_certificate): add a boolean to know if there were san
> entries, skip the CN match if there were and move the failure
> flag outside of the CN match code.
>
> Modified:
> subversion/trunk/subversion/libsvn_ra_serf/util.c
>
> Modified: subversion/trunk/subversion/libsvn_ra_serf/util.c
> URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/util.c?rev=1565531&r1=1565530&r2=1565531&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/libsvn_ra_serf/util.c (original)
> +++ subversion/trunk/subversion/libsvn_ra_serf/util.c Fri Feb 7 04:32:50 2014
> @@ -225,6 +225,7 @@ ssl_server_cert(void *baton, int failure
> ### This should really be handled by serf, which should pass an error
> for this case, but that has backwards compatibility issues. */
> apr_array_header_t *san;
> + svn_boolean_t found_san_entry;
>
> serf_cert = serf_ssl_cert_certificate(cert, scratch_pool);
>
> @@ -232,6 +233,7 @@ ssl_server_cert(void *baton, int failure
> /* Try to find matching server name via subjectAltName first... */
> if (san) {
> int i;
> + found_san_entry = san->nelts > 0;
> for (i = 0; i < san->nelts; i++) {
> const char *s = APR_ARRAY_IDX(san, i, const char*);
> if (apr_fnmatch(s, conn->session->session_url.hostname,
> @@ -243,8 +245,11 @@ ssl_server_cert(void *baton, int failure
> }
> }
>
> - /* Match server certificate CN with the hostname of the server */
> - if (!found_matching_hostname)
> + /* Match server certificate CN with the hostname of the server iff
> + * we didn't find any subjectAltName fields and try to match them.
> + * Per RFC 2818 they are authoritative if present and CommonName
> + * should be ignored. */
> + if (!found_matching_hostname && !found_san_entry)
> {
> const char *hostname = NULL;
>
> @@ -253,13 +258,16 @@ ssl_server_cert(void *baton, int failure
> if (subject)
> hostname = svn_hash_gets(subject, "CN");
>
> - if (!hostname
> - || apr_fnmatch(hostname, conn->session->session_url.hostname,
> - APR_FNM_PERIOD | APR_FNM_CASE_BLIND) != APR_SUCCESS)
> + if (hostname
> + && apr_fnmatch(hostname, conn->session->session_url.hostname,
> + APR_FNM_PERIOD | APR_FNM_CASE_BLIND) == APR_SUCCESS)
> {
> - svn_failures |= SVN_AUTH_SSL_CNMISMATCH;
> + found_matching_hostname = 1;
> }
> }
> +
> + if (!found_matching_hostname)
> + svn_failures |= SVN_AUTH_SSL_CNMISMATCH;
> }
>
Hi Ben,
I think it will be more clear to write code in the following way:
[[
san = svn_hash_gets(serf_cert, "subjectAltName");
/* Match server certificate CN with the hostname of the server iff
* we didn't find any subjectAltName fields and try to match them.
* Per RFC 2818 they are authoritative if present and CommonName
* should be ignored. */
if (san && san->nelts > 0) {
int i;
found_san_entry = ;
for (i = 0; i < san->nelts; i++) {
const char *s = APR_ARRAY_IDX(san, i, const char*);
if (apr_fnmatch(s, conn->session->session_url.hostname,
APR_FNM_PERIOD | APR_FNM_CASE_BLIND) == APR_SUCCESS)
{
found_matching_hostname = 1;
break;
}
}
}
else
{
const char *hostname = NULL;
subject = serf_ssl_cert_subject(cert, scratch_pool);
if (subject)
hostname = svn_hash_gets(subject, "CN");
if (hostname
&& apr_fnmatch(hostname, conn->session->session_url.hostname,
APR_FNM_PERIOD | APR_FNM_CASE_BLIND) ==
APR_SUCCESS)
{
found_matching_hostname = 1;
}
}
]]
Did I miss something important?
--
Ivan Zhakov
Received on 2014-08-01 17:24:42 CEST