On 7 February 2014 08:32, <bre...@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
Index: subversion/libsvn_ra_serf/util.c =================================================================== --- subversion/libsvn_ra_serf/util.c (revision 1615135) +++ subversion/libsvn_ra_serf/util.c (working copy) @@ -231,17 +231,18 @@ ### 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 = FALSE; svn_boolean_t found_matching_hostname = FALSE; serf_cert = serf_ssl_cert_certificate(cert, scratch_pool); san = svn_hash_gets(serf_cert, "subjectAltName"); - /* Try to find matching server name via subjectAltName first... */ - if (san) + /* 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 = san->nelts > 0; for (i = 0; i < san->nelts; i++) { const char *s = APR_ARRAY_IDX(san, i, const char*); @@ -255,12 +256,7 @@ } } } - - /* 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) + else { const char *hostname = NULL;