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

« back to all changes in this revision

Viewing changes to subversion/mod_dav_svn/util.c

  • Committer: Package Import Robot
  • Author(s): James McCoy
  • Date: 2015-08-07 21:32:47 UTC
  • mfrom: (0.2.15) (4.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20150807213247-ozyewtmgsr6tkewl
Tags: 1.9.0-1
* Upload to unstable
* New upstream release.
  + Security fixes
    - CVE-2015-3184: Mixed anonymous/authenticated path-based authz with
      httpd 2.4
    - CVE-2015-3187: svn_repos_trace_node_locations() reveals paths hidden
      by authz
* Add >= 2.7 requirement for python-all-dev Build-Depends, needed to run
  tests.
* Remove Build-Conflicts against ruby-test-unit.  (Closes: #791844)
* Remove patches/apache_module_dependency in favor of expressing the
  dependencies in authz_svn.load/dav_svn.load.
* Build-Depend on apache2-dev (>= 2.4.16) to ensure ap_some_authn_required()
  is available when building mod_authz_svn and Depend on apache2-bin (>=
  2.4.16) for runtime support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * util.c: some handy utility functions
 
2
 * util.c:
 
3
 * # ****************************************************************************
 
4
 * # TRASHY LITTLE SUBROUTINES
 
5
 * # ****************************************************************************
3
6
 *
4
7
 * ====================================================================
5
8
 *    Licensed to the Apache Software Foundation (ASF) under one
37
40
 
38
41
#include "dav_svn.h"
39
42
#include "private/svn_fspath.h"
40
 
#include "private/svn_string_private.h"
41
43
 
42
44
dav_error *
43
45
dav_svn__new_error(apr_pool_t *pool,
59
61
  return dav_new_error(pool, status, error_id, 0, desc);
60
62
#else
61
63
 
62
 
  errno = 0; /* For the same reason as in dav_svn__new_error_tag */
 
64
  errno = 0; /* For the same reason as in dav_svn__new_error_svn */
63
65
 
64
66
  return dav_new_error(pool, status, error_id, desc);
65
67
#endif
66
68
}
67
69
 
68
70
dav_error *
69
 
dav_svn__new_error_tag(apr_pool_t *pool,
 
71
dav_svn__new_error_svn(apr_pool_t *pool,
70
72
                       int status,
71
73
                       int error_id,
72
 
                       const char *desc,
73
 
                       const char *namespace,
74
 
                       const char *tagname)
 
74
                       const char *desc)
75
75
{
76
76
  if (error_id == 0)
77
77
    error_id = SVN_ERR_RA_DAV_REQUEST_FAILED;
78
78
 
79
79
#if AP_MODULE_MAGIC_AT_LEAST(20091119,0)
80
80
  return dav_new_error_tag(pool, status, error_id, 0,
81
 
                           desc, namespace, tagname);
 
81
                           desc, SVN_DAV_ERROR_NAMESPACE, SVN_DAV_ERROR_TAG);
82
82
#else
83
83
  /* dav_new_error_tag will record errno but Subversion makes no attempt
84
84
     to ensure that it is valid.  We reset it to avoid putting incorrect
86
86
     valid information. */
87
87
  errno = 0;
88
88
 
89
 
  return dav_new_error_tag(pool, status, error_id, desc, namespace, tagname);
 
89
  return dav_new_error_tag(pool, status, error_id, desc,
 
90
                           SVN_DAV_ERROR_NAMESPACE, SVN_DAV_ERROR_TAG);
90
91
#endif
91
92
}
92
93
 
96
97
static dav_error *
97
98
build_error_chain(apr_pool_t *pool, svn_error_t *err, int status)
98
99
{
99
 
  char *msg = err->message ? apr_pstrdup(pool, err->message) : NULL;
 
100
  char buffer[128];
 
101
  const char *msg = svn_err_best_message(err, buffer, sizeof(buffer));
100
102
 
101
 
  dav_error *derr = dav_svn__new_error_tag(pool, status, err->apr_err, msg,
102
 
                                           SVN_DAV_ERROR_NAMESPACE,
103
 
                                           SVN_DAV_ERROR_TAG);
 
103
  dav_error *derr = dav_svn__new_error_svn(pool, status, err->apr_err,
 
104
                                           apr_pstrdup(pool, msg));
104
105
 
105
106
  if (err->child)
106
107
    derr->prev = build_error_chain(pool, err->child, status);
115
116
                     const char *message,
116
117
                     apr_pool_t *pool)
117
118
{
118
 
    dav_error *derr;
119
 
 
120
 
    /* Remove the trace-only error chain links.  We need predictable
121
 
       protocol behavior regardless of whether or not we're in a
122
 
       debugging build. */
123
 
    svn_error_t *purged_serr = svn_error_purge_tracing(serr);
124
 
 
125
 
    /* ### someday mod_dav_svn will send back 'rich' error tags, much
126
 
       finer grained than plain old svn_error_t's.  But for now, all
127
 
       svn_error_t's are marshalled to the client via the single
128
 
       generic <svn:error/> tag nestled within a <D:error> block. */
129
 
 
130
 
    /* Examine the Subverion error code, and select the most
131
 
       appropriate HTTP status code.  If no more appropriate HTTP
132
 
       status code maps to the Subversion error code, use the one
133
 
       suggested status provided by the caller. */
134
 
    switch (purged_serr->apr_err)
135
 
      {
136
 
      case SVN_ERR_FS_NOT_FOUND:
137
 
        status = HTTP_NOT_FOUND;
138
 
        break;
139
 
      case SVN_ERR_UNSUPPORTED_FEATURE:
140
 
        status = HTTP_NOT_IMPLEMENTED;
141
 
        break;
142
 
      case SVN_ERR_FS_LOCK_OWNER_MISMATCH:
143
 
      case SVN_ERR_FS_PATH_ALREADY_LOCKED:
144
 
        status = HTTP_LOCKED;
145
 
        break;
146
 
      case SVN_ERR_FS_PROP_BASEVALUE_MISMATCH:
147
 
        status = HTTP_PRECONDITION_FAILED;
148
 
        break;
149
 
        /* add other mappings here */
150
 
      }
151
 
 
152
 
    derr = build_error_chain(pool, purged_serr, status);
153
 
    if (message != NULL
154
 
        && purged_serr->apr_err != SVN_ERR_REPOS_HOOK_FAILURE)
155
 
      /* Don't hide hook failures; we might hide the error text */
156
 
      derr = dav_push_error(pool, status, purged_serr->apr_err,
157
 
                            message, derr);
158
 
 
159
 
    /* Now, destroy the Subversion error. */
160
 
    svn_error_clear(serr);
161
 
 
162
 
    return derr;
 
119
  dav_error *derr;
 
120
 
 
121
  /* Remove the trace-only error chain links.  We need predictable
 
122
     protocol behavior regardless of whether or not we're in a
 
123
     debugging build. */
 
124
  svn_error_t *purged_serr = svn_error_purge_tracing(serr);
 
125
 
 
126
  /* ### someday mod_dav_svn will send back 'rich' error tags, much
 
127
     finer grained than plain old svn_error_t's.  But for now, all
 
128
     svn_error_t's are marshalled to the client via the single
 
129
     generic <svn:error/> tag nestled within a <D:error> block. */
 
130
 
 
131
  /* Examine the Subverion error code, and select the most
 
132
     appropriate HTTP status code.  If no more appropriate HTTP
 
133
     status code maps to the Subversion error code, use the one
 
134
     suggested status provided by the caller. */
 
135
  switch (purged_serr->apr_err)
 
136
    {
 
137
    case SVN_ERR_FS_NOT_FOUND:
 
138
    case SVN_ERR_FS_NO_SUCH_REVISION:
 
139
      status = HTTP_NOT_FOUND;
 
140
      break;
 
141
    case SVN_ERR_UNSUPPORTED_FEATURE:
 
142
      status = HTTP_NOT_IMPLEMENTED;
 
143
      break;
 
144
    case SVN_ERR_FS_LOCK_OWNER_MISMATCH:
 
145
    case SVN_ERR_FS_PATH_ALREADY_LOCKED:
 
146
      status = HTTP_LOCKED;
 
147
      break;
 
148
    case SVN_ERR_FS_PROP_BASEVALUE_MISMATCH:
 
149
      status = HTTP_PRECONDITION_FAILED;
 
150
      break;
 
151
      /* add other mappings here */
 
152
    }
 
153
 
 
154
  derr = build_error_chain(pool, purged_serr, status);
 
155
  if (message != NULL
 
156
      && !svn_error_find_cause(purged_serr, SVN_ERR_REPOS_HOOK_FAILURE))
 
157
    /* Don't hide hook failures; we might hide the error text */
 
158
    derr = dav_push_error(pool, status, purged_serr->apr_err,
 
159
                          message, derr);
 
160
 
 
161
  /* Now, destroy the Subversion error. */
 
162
  svn_error_clear(serr);
 
163
 
 
164
  return derr;
163
165
}
164
166
 
165
167
 
176
178
  const char *ignored;
177
179
 
178
180
  /* Get an initial HISTORY baton. */
179
 
  SVN_ERR(svn_fs_node_history(&history, root, path, pool));
 
181
  SVN_ERR(svn_fs_node_history2(&history, root, path, pool, pool));
180
182
 
181
183
  /* Now get the first *real* point of interesting history. */
182
 
  SVN_ERR(svn_fs_history_prev(&history, history, FALSE, pool));
 
184
  SVN_ERR(svn_fs_history_prev2(&history, history, FALSE, pool, pool));
183
185
 
184
186
  /* Fetch the location information for this history step. */
185
187
  return svn_fs_history_location(&ignored, revision, history, pool);
193
195
  svn_revnum_t history_rev;
194
196
  svn_fs_root_t *other_root;
195
197
  svn_fs_t *fs = svn_fs_root_fs(root);
196
 
  const svn_fs_id_t *id, *other_id;
 
198
  svn_fs_node_relation_t node_relation;
197
199
  svn_error_t *err;
198
200
 
199
 
  if ((err = svn_fs_node_id(&id, root, path, pool)))
200
 
    {
201
 
      svn_error_clear(err);
202
 
      return revision;   /* couldn't get id of root/path */
203
 
    }
204
 
 
205
201
  if ((err = get_last_history_rev(&history_rev, root, path, pool)))
206
202
    {
207
203
      svn_error_clear(err);
214
210
      return revision;   /* couldn't open the history rev */
215
211
    }
216
212
 
217
 
  if ((err = svn_fs_node_id(&other_id, other_root, path, pool)))
 
213
  if ((err = svn_fs_node_relation(&node_relation, root, path,
 
214
                                  other_root, path, pool)))
218
215
    {
219
216
      svn_error_clear(err);
220
 
      return revision;   /* couldn't get id of other_root/path */
 
217
      return revision;
221
218
    }
222
219
 
223
 
  if (svn_fs_compare_ids(id, other_id) == 0)
 
220
  if (node_relation == svn_fs_node_unchanged)
224
221
    return history_rev;  /* the history rev is safe!  the same node
225
222
                            exists at the same path in both revisions. */
226
223
 
234
231
                   enum dav_svn__build_what what,
235
232
                   svn_revnum_t revision,
236
233
                   const char *path,
237
 
                   int add_href,
 
234
                   svn_boolean_t add_href,
238
235
                   apr_pool_t *pool)
239
236
{
240
237
  const char *root_path = repos->root_path;
541
538
    return NULL;
542
539
 
543
540
  /* Otherwise, generate a generic HTTP_BAD_REQUEST error. */
544
 
  return dav_svn__new_error_tag
545
 
    (pool, HTTP_BAD_REQUEST, 0,
 
541
  return dav_svn__new_error_svn(
 
542
     pool, HTTP_BAD_REQUEST, 0,
546
543
     apr_psprintf(pool,
547
544
                  "Path '%s' is not canonicalized; "
548
 
                  "there is a problem with the client.", path),
549
 
     SVN_DAV_ERROR_NAMESPACE, SVN_DAV_ERROR_TAG);
 
545
                  "there is a problem with the client.", path));
550
546
}
551
547
 
552
548
 
576
572
                        "%s", purged_serr->message);
577
573
        }
578
574
 
579
 
        svn_error_clear(serr);
580
 
      }
581
 
    return dav_svn__convert_err(safe_err, http_status,
582
 
                                apr_psprintf(r->pool, "%s", safe_err->message),
583
 
                                r->pool);
 
575
      svn_error_clear(serr);
 
576
    }
 
577
 
 
578
  return dav_svn__convert_err(safe_err, http_status,
 
579
                              apr_psprintf(r->pool, "%s", safe_err->message),
 
580
                              r->pool);
584
581
}
585
582
 
586
583
 
757
754
  content_length_str = apr_table_get(r->headers_in, "Content-Length");
758
755
  if (content_length_str)
759
756
    {
760
 
      if (svn__strtoff(&content_length, content_length_str, &endp, 10)
 
757
      if (apr_strtoff(&content_length, content_length_str, &endp, 10)
761
758
          || endp == content_length_str || *endp || content_length < 0)
762
759
        {
763
760
          ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Invalid Content-Length");
861
858
  *skel = NULL;
862
859
  status = request_body_to_string(&skel_str, r, pool);
863
860
  if (status != OK)
864
 
    return OK;
 
861
    return status;
865
862
 
866
863
  *skel = svn_skel__parse(skel_str->data, skel_str->len, pool);
867
864
  return OK;