~ubuntu-branches/debian/sid/subversion/sid

« back to all changes in this revision

Viewing changes to subversion/libsvn_ra_serf/util.c

  • Committer: Package Import Robot
  • Author(s): James McCoy
  • Date: 2014-02-20 20:38:10 UTC
  • mfrom: (0.2.11)
  • Revision ID: package-import@ubuntu.com-20140220203810-w61omsda8fs70pta
Tags: 1.8.8-1
* New upstream release.  Refresh patches.
  - Remove backported patches sqlite_3.8.x_workaround & swig-pl_build_fix
  - Fix integer overflows with 32-bit svnserv, which could cause an infinite
    loop (Closes: #738840) or inaccurate statistics (Closes: #738841)
  - Work around SQLite not honoring umask when creating rep-cache.db.
    (Closes: #735446)
  - Includes security fix:
    + CVE-2014-0032: mod_dav_svn crash when handling certain requests with
      SVNListParentPath on  (Closes: #737815)
* Add a subversion-dbg package.  (Closes: #508147)
* Bump libdb5.1-dev → libdb5.3-dev  (Closes: #738650)

Show diffs side-by-side

added added

removed removed

Lines of Context:
48
48
#include "private/svn_dep_compat.h"
49
49
#include "private/svn_fspath.h"
50
50
#include "private/svn_subr_private.h"
 
51
#include "private/svn_auth_private.h"
51
52
 
52
53
#include "ra_serf.h"
53
54
 
269
270
  svn_auth_iterstate_t *state;
270
271
  const char *realmstring;
271
272
  apr_uint32_t svn_failures;
272
 
  apr_hash_t *issuer, *subject, *serf_cert;
273
 
  apr_array_header_t *san;
 
273
  apr_hash_t *issuer;
 
274
  apr_hash_t *subject = NULL;
 
275
  apr_hash_t *serf_cert = NULL;
274
276
  void *creds;
275
277
  int found_matching_hostname = 0;
276
278
 
277
 
  /* Implicitly approve any non-server certs. */
278
 
  if (serf_ssl_cert_depth(cert) > 0)
 
279
  svn_failures = (ssl_convert_serf_failures(failures)
 
280
      | conn->server_cert_failures);
 
281
 
 
282
  if (serf_ssl_cert_depth(cert) == 0)
279
283
    {
280
 
      if (failures)
281
 
        conn->server_cert_failures |= ssl_convert_serf_failures(failures);
282
 
      return APR_SUCCESS;
 
284
      /* If the depth is 0, the hostname must match the certificate.
 
285
 
 
286
      ### This should really be handled by serf, which should pass an error
 
287
          for this case, but that has backwards compatibility issues. */
 
288
      apr_array_header_t *san;
 
289
 
 
290
      serf_cert = serf_ssl_cert_certificate(cert, scratch_pool);
 
291
 
 
292
      san = svn_hash_gets(serf_cert, "subjectAltName");
 
293
      /* Try to find matching server name via subjectAltName first... */
 
294
      if (san) {
 
295
          int i;
 
296
          for (i = 0; i < san->nelts; i++) {
 
297
              const char *s = APR_ARRAY_IDX(san, i, const char*);
 
298
              if (apr_fnmatch(s, conn->session->session_url.hostname,
 
299
                  APR_FNM_PERIOD | APR_FNM_CASE_BLIND) == APR_SUCCESS)
 
300
              {
 
301
                  found_matching_hostname = 1;
 
302
                  break;
 
303
              }
 
304
          }
 
305
      }
 
306
 
 
307
      /* Match server certificate CN with the hostname of the server */
 
308
      if (!found_matching_hostname)
 
309
        {
 
310
          const char *hostname = NULL;
 
311
 
 
312
          subject = serf_ssl_cert_subject(cert, scratch_pool);
 
313
 
 
314
          if (subject)
 
315
            hostname = svn_hash_gets(subject, "CN");
 
316
 
 
317
          if (!hostname
 
318
              || apr_fnmatch(hostname, conn->session->session_url.hostname,
 
319
                             APR_FNM_PERIOD | APR_FNM_CASE_BLIND) != APR_SUCCESS)
 
320
          {
 
321
              svn_failures |= SVN_AUTH_SSL_CNMISMATCH;
 
322
          }
 
323
      }
283
324
    }
284
325
 
 
326
  if (!svn_failures)
 
327
    return SVN_NO_ERROR;
 
328
 
285
329
  /* Extract the info from the certificate */
286
 
  subject = serf_ssl_cert_subject(cert, scratch_pool);
 
330
  if (! subject)
 
331
    subject = serf_ssl_cert_subject(cert, scratch_pool);
287
332
  issuer = serf_ssl_cert_issuer(cert, scratch_pool);
288
 
  serf_cert = serf_ssl_cert_certificate(cert, scratch_pool);
 
333
  if (! serf_cert)
 
334
    serf_cert = serf_ssl_cert_certificate(cert, scratch_pool);
289
335
 
290
336
  cert_info.hostname = svn_hash_gets(subject, "CN");
291
 
  san = svn_hash_gets(serf_cert, "subjectAltName");
292
337
  cert_info.fingerprint = svn_hash_gets(serf_cert, "sha1");
293
338
  if (! cert_info.fingerprint)
294
339
    cert_info.fingerprint = apr_pstrdup(scratch_pool, "<unknown>");
301
346
  cert_info.issuer_dname = convert_organisation_to_str(issuer, scratch_pool);
302
347
  cert_info.ascii_cert = serf_ssl_cert_export(cert, scratch_pool);
303
348
 
304
 
  svn_failures = (ssl_convert_serf_failures(failures)
305
 
                  | conn->server_cert_failures);
306
 
 
307
 
  /* Try to find matching server name via subjectAltName first... */
308
 
  if (san) {
309
 
      int i;
310
 
      for (i = 0; i < san->nelts; i++) {
311
 
          char *s = APR_ARRAY_IDX(san, i, char*);
312
 
          if (apr_fnmatch(s, conn->session->session_url.hostname,
313
 
                          APR_FNM_PERIOD | APR_FNM_CASE_BLIND) == APR_SUCCESS)
314
 
            {
315
 
              found_matching_hostname = 1;
316
 
              cert_info.hostname = s;
317
 
              break;
318
 
            }
319
 
      }
320
 
  }
321
 
 
322
 
  /* Match server certificate CN with the hostname of the server */
323
 
  if (!found_matching_hostname && cert_info.hostname)
 
349
  /* Handle any non-server certs. */
 
350
  if (serf_ssl_cert_depth(cert) > 0)
324
351
    {
325
 
      if (apr_fnmatch(cert_info.hostname, conn->session->session_url.hostname,
326
 
                      APR_FNM_PERIOD | APR_FNM_CASE_BLIND) == APR_FNM_NOMATCH)
327
 
        {
328
 
          svn_failures |= SVN_AUTH_SSL_CNMISMATCH;
329
 
        }
 
352
      svn_error_t *err;
 
353
 
 
354
      svn_auth_set_parameter(conn->session->wc_callbacks->auth_baton,
 
355
                             SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO,
 
356
                             &cert_info);
 
357
 
 
358
      svn_auth_set_parameter(conn->session->wc_callbacks->auth_baton,
 
359
                             SVN_AUTH_PARAM_SSL_SERVER_FAILURES,
 
360
                             &svn_failures);
 
361
 
 
362
      realmstring = apr_psprintf(scratch_pool, "AUTHORITY:%s",
 
363
                                 cert_info.fingerprint);
 
364
 
 
365
      err = svn_auth_first_credentials(&creds, &state,
 
366
                                       SVN_AUTH_CRED_SSL_SERVER_AUTHORITY,
 
367
                                       realmstring,
 
368
                                       conn->session->wc_callbacks->auth_baton,
 
369
                                       scratch_pool);
 
370
 
 
371
      svn_auth_set_parameter(conn->session->wc_callbacks->auth_baton,
 
372
                             SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO, NULL);
 
373
 
 
374
      svn_auth_set_parameter(conn->session->wc_callbacks->auth_baton,
 
375
                             SVN_AUTH_PARAM_SSL_SERVER_FAILURES, NULL);
 
376
 
 
377
      if (err)
 
378
        {
 
379
          if (err->apr_err != SVN_ERR_AUTHN_NO_PROVIDER)
 
380
            return svn_error_trace(err);
 
381
 
 
382
          /* No provider registered that handles server authorities */
 
383
          svn_error_clear(err);
 
384
          creds = NULL;
 
385
        }
 
386
 
 
387
      if (creds)
 
388
        {
 
389
          server_creds = creds;
 
390
          SVN_ERR(svn_auth_save_credentials(state, scratch_pool));
 
391
 
 
392
          svn_failures &= ~server_creds->accepted_failures;
 
393
        }
 
394
 
 
395
      if (svn_failures)
 
396
        conn->server_cert_failures |= svn_failures;
 
397
 
 
398
      return APR_SUCCESS;
330
399
    }
331
400
 
332
401
  svn_auth_set_parameter(conn->session->wc_callbacks->auth_baton,
347
416
  if (creds)
348
417
    {
349
418
      server_creds = creds;
 
419
      svn_failures &= ~server_creds->accepted_failures;
350
420
      SVN_ERR(svn_auth_save_credentials(state, scratch_pool));
351
421
    }
352
422
 
 
423
  while (svn_failures && creds)
 
424
    {
 
425
      SVN_ERR(svn_auth_next_credentials(&creds, state, scratch_pool));
 
426
 
 
427
      if (creds)
 
428
        {
 
429
          server_creds = creds;
 
430
          svn_failures &= ~server_creds->accepted_failures;
 
431
          SVN_ERR(svn_auth_save_credentials(state, scratch_pool));
 
432
        }
 
433
    }
 
434
 
353
435
  svn_auth_set_parameter(conn->session->wc_callbacks->auth_baton,
354
436
                         SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO, NULL);
355
437
 
356
 
  if (!server_creds)
 
438
  /* Are there non accepted failures left? */
 
439
  if (svn_failures)
357
440
    {
358
441
      svn_stringbuf_t *errmsg;
359
442
      int reasons = 0;