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

« back to all changes in this revision

Viewing changes to subversion/libsvn_subr/x509info.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
/*
 
2
 * x509info.c:  Accessors for svn_x509_certinfo_t
 
3
 *
 
4
 * ====================================================================
 
5
 *    Licensed to the Apache Software Foundation (ASF) under one
 
6
 *    or more contributor license agreements.  See the NOTICE file
 
7
 *    distributed with this work for additional information
 
8
 *    regarding copyright ownership.  The ASF licenses this file
 
9
 *    to you under the Apache License, Version 2.0 (the
 
10
 *    "License"); you may not use this file except in compliance
 
11
 *    with the License.  You may obtain a copy of the License at
 
12
 *
 
13
 *      http://www.apache.org/licenses/LICENSE-2.0
 
14
 *
 
15
 *    Unless required by applicable law or agreed to in writing,
 
16
 *    software distributed under the License is distributed on an
 
17
 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 
18
 *    KIND, either express or implied.  See the License for the
 
19
 *    specific language governing permissions and limitations
 
20
 *    under the License.
 
21
 * ====================================================================
 
22
 */
 
23
 
 
24
 
 
25
 
 
26
#include <string.h>
 
27
 
 
28
#include <apr_pools.h>
 
29
#include <apr_tables.h>
 
30
 
 
31
#include "svn_string.h"
 
32
#include "svn_hash.h"
 
33
#include "x509.h"
 
34
 
 
35
 
 
36
 
 
37
svn_x509_name_attr_t *
 
38
svn_x509_name_attr_dup(const svn_x509_name_attr_t *attr,
 
39
                       apr_pool_t *result_pool,
 
40
                       apr_pool_t *scratch_pool)
 
41
{
 
42
  svn_x509_name_attr_t *result = apr_palloc(result_pool, sizeof(*result));
 
43
  result->oid_len = attr->oid_len;
 
44
  result->oid = apr_palloc(result_pool, result->oid_len);
 
45
  memcpy(result->oid, attr->oid, result->oid_len);
 
46
  result->utf8_value = apr_pstrdup(result_pool, attr->utf8_value);
 
47
 
 
48
  return result;
 
49
}
 
50
 
 
51
const unsigned char *
 
52
svn_x509_name_attr_get_oid(const svn_x509_name_attr_t *attr, apr_size_t *len)
 
53
{
 
54
  *len = attr->oid_len;
 
55
  return attr->oid;
 
56
}
 
57
 
 
58
const char *
 
59
svn_x509_name_attr_get_value(const svn_x509_name_attr_t *attr)
 
60
{
 
61
  return attr->utf8_value;
 
62
}
 
63
 
 
64
/* Array elements are assumed to be nul-terminated C strings. */
 
65
static apr_array_header_t *
 
66
deep_copy_array(apr_array_header_t *s, apr_pool_t *result_pool)
 
67
{
 
68
  int i;
 
69
  apr_array_header_t *d;
 
70
 
 
71
  if (!s)
 
72
    return NULL;
 
73
 
 
74
  d = apr_array_copy(result_pool, s);
 
75
 
 
76
  /* Make a deep copy of the strings in the array. */
 
77
  for (i = 0; i < s->nelts; ++i)
 
78
    {
 
79
      APR_ARRAY_IDX(d, i, const char *) =
 
80
        apr_pstrdup(result_pool, APR_ARRAY_IDX(s, i, const char *));
 
81
    }
 
82
 
 
83
  return d;
 
84
}
 
85
 
 
86
/* Copy an array with elements that are svn_x509_name_attr_t's */
 
87
static apr_array_header_t *
 
88
deep_copy_name_attrs(apr_array_header_t *s, apr_pool_t *result_pool)
 
89
{
 
90
  int i;
 
91
  apr_array_header_t *d;
 
92
 
 
93
  if (!s)
 
94
    return NULL;
 
95
 
 
96
  d = apr_array_copy(result_pool, s);
 
97
 
 
98
  /* Make a deep copy of the svn_x509_name_attr_t's in the array. */
 
99
  for (i = 0; i < s->nelts; ++i)
 
100
    {
 
101
      APR_ARRAY_IDX(d, i, const svn_x509_name_attr_t *) =
 
102
        svn_x509_name_attr_dup(APR_ARRAY_IDX(s, i, svn_x509_name_attr_t *),
 
103
                               result_pool, result_pool);
 
104
    }
 
105
 
 
106
  return d;
 
107
}
 
108
 
 
109
svn_x509_certinfo_t *
 
110
svn_x509_certinfo_dup(const svn_x509_certinfo_t *certinfo,
 
111
                      apr_pool_t *result_pool,
 
112
                      apr_pool_t *scratch_pool)
 
113
{
 
114
  svn_x509_certinfo_t *result = apr_palloc(result_pool, sizeof(*result));
 
115
  result->subject = deep_copy_name_attrs(certinfo->subject, result_pool);
 
116
  result->issuer = deep_copy_name_attrs(certinfo->issuer, result_pool);
 
117
  result->valid_from = certinfo->valid_from;
 
118
  result->valid_to = certinfo->valid_to;
 
119
  result->digest = svn_checksum_dup(certinfo->digest, result_pool);
 
120
  result->hostnames = deep_copy_array(certinfo->hostnames, result_pool);
 
121
 
 
122
  return result;
 
123
}
 
124
 
 
125
typedef struct asn1_oid {
 
126
  const unsigned char *oid;
 
127
  const ptrdiff_t oid_len;
 
128
  const char *short_label;
 
129
  const char *long_label;
 
130
} asn1_oid;
 
131
 
 
132
#define CONSTANT_PAIR(c) (unsigned char *)(c), sizeof((c)) - 1
 
133
 
 
134
static const asn1_oid asn1_oids[] = {
 
135
  { CONSTANT_PAIR(SVN_X509_OID_COMMON_NAME),  "CN", "commonName" },
 
136
  { CONSTANT_PAIR(SVN_X509_OID_COUNTRY),      "C",  "countryName" },
 
137
  { CONSTANT_PAIR(SVN_X509_OID_LOCALITY),     "L",  "localityName" },
 
138
  { CONSTANT_PAIR(SVN_X509_OID_STATE),        "ST", "stateOrProvinceName" },
 
139
  { CONSTANT_PAIR(SVN_X509_OID_ORGANIZATION), "O",  "organizationName" },
 
140
  { CONSTANT_PAIR(SVN_X509_OID_ORG_UNIT),     "OU", "organizationalUnitName"},
 
141
  { CONSTANT_PAIR(SVN_X509_OID_EMAIL),        NULL, "emailAddress" },
 
142
  { NULL },
 
143
};
 
144
 
 
145
/* Given an OID return a null-terminated C string representation.
 
146
 * For example an OID with the bytes "\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01"
 
147
 * would be converted to the string "1.2.840.113549.1.9.1". */
 
148
const char *
 
149
svn_x509_oid_to_string(const unsigned char *oid, apr_size_t oid_len,
 
150
                       apr_pool_t *scratch_pool, apr_pool_t *result_pool)
 
151
{
 
152
  svn_stringbuf_t *out = svn_stringbuf_create_empty(result_pool);
 
153
  const unsigned char *p = oid;
 
154
  const unsigned char *end = p + oid_len;
 
155
  const char *temp;
 
156
 
 
157
  while (p != end) {
 
158
    if (p == oid)
 
159
      {
 
160
        /* Handle decoding the first two values of the OID.  These values
 
161
         * are encoded by taking the first value and adding 40 to it and
 
162
         * adding the result to the second value, then placing this single
 
163
         * value in the first byte of the output.  This is unambiguous since
 
164
         * the first value is apparently limited to 0, 1 or 2 and the second
 
165
         * is limited to 0 to 39. */
 
166
        temp = apr_psprintf(scratch_pool, "%d.%d", *p / 40, *p % 40);
 
167
        p++;
 
168
      }
 
169
    else if (*p < 128)
 
170
      {
 
171
        /* The remaining values if they're less than 128 are just
 
172
         * the number one to one encoded */
 
173
        temp = apr_psprintf(scratch_pool, ".%d", *p);
 
174
        p++;
 
175
      }
 
176
    else
 
177
      {
 
178
        /* Values greater than 128 are encoded as a series of 7 bit values
 
179
         * with the left most bit set to indicate this encoding with the
 
180
         * last octet missing the left most bit to finish out the series.. */
 
181
        unsigned int collector = 0;
 
182
        svn_boolean_t dot = FALSE;
 
183
 
 
184
        do {
 
185
          if (collector == 0 && *p == 0x80)
 
186
            {
 
187
              /* include leading zeros in the string representation
 
188
                 technically not legal, but this seems nicer than just
 
189
                 returning NULL */
 
190
              if (!dot)
 
191
                {
 
192
                  svn_stringbuf_appendbyte(out, '.');
 
193
                  dot = TRUE;
 
194
                }
 
195
              svn_stringbuf_appendbyte(out, '0');
 
196
            }
 
197
          else if (collector > UINT_MAX >> 7)
 
198
            {
 
199
              /* overflow */
 
200
              return NULL;
 
201
            }
 
202
          collector = collector << 7 | (*(p++) & 0x7f);
 
203
        } while (p != end && *p > 127);
 
204
        if (collector > UINT_MAX >> 7)
 
205
          return NULL; /* overflow */
 
206
        collector = collector << 7 | *(p++);
 
207
        temp = apr_psprintf(scratch_pool, "%s%d", dot ? "" : ".", collector);
 
208
      }
 
209
    svn_stringbuf_appendcstr(out, temp);
 
210
  }
 
211
 
 
212
  if (svn_stringbuf_isempty(out))
 
213
    return NULL;
 
214
 
 
215
  return out->data;
 
216
}
 
217
 
 
218
static const asn1_oid *oid_to_asn1_oid(unsigned char *oid, apr_size_t oid_len)
 
219
{
 
220
  const asn1_oid *entry;
 
221
 
 
222
  for (entry = asn1_oids; entry->oid; entry++)
 
223
    {
 
224
      if (oid_len == entry->oid_len &&
 
225
          memcmp(oid, entry->oid, oid_len) == 0)
 
226
        return entry;
 
227
    }
 
228
 
 
229
  return NULL;
 
230
}
 
231
 
 
232
static const char *oid_to_best_label(unsigned char *oid, apr_size_t oid_len,
 
233
                                     apr_pool_t *result_pool)
 
234
{
 
235
  const asn1_oid *entry = oid_to_asn1_oid(oid, oid_len);
 
236
 
 
237
  if (entry)
 
238
    {
 
239
      if (entry->short_label)
 
240
        return entry->short_label;
 
241
 
 
242
      if (entry->long_label)
 
243
        return entry->long_label;
 
244
    }
 
245
  else
 
246
    {
 
247
      const char *oid_string = svn_x509_oid_to_string(oid, oid_len,
 
248
                                                      result_pool, result_pool);
 
249
      if (oid_string)
 
250
        return oid_string;
 
251
    }
 
252
 
 
253
  return "??";
 
254
}
 
255
 
 
256
/*
 
257
 * Store the name from dn in printable form into buf,
 
258
 * using scratch_pool for any temporary allocations.
 
259
 * If CN is not NULL, return any common name in CN
 
260
 */
 
261
static const char *
 
262
get_dn(apr_array_header_t *name,
 
263
       apr_pool_t *result_pool)
 
264
{
 
265
  svn_stringbuf_t *buf = svn_stringbuf_create_empty(result_pool);
 
266
  int n;
 
267
 
 
268
  for (n = 0; n < name->nelts; n++)
 
269
    {
 
270
      const svn_x509_name_attr_t *attr = APR_ARRAY_IDX(name, n, svn_x509_name_attr_t *);
 
271
 
 
272
      if (n > 0)
 
273
        svn_stringbuf_appendcstr(buf, ", ");
 
274
 
 
275
      svn_stringbuf_appendcstr(buf, oid_to_best_label(attr->oid, attr->oid_len, result_pool));
 
276
      svn_stringbuf_appendbyte(buf, '=');
 
277
      svn_stringbuf_appendcstr(buf, attr->utf8_value);
 
278
    }
 
279
 
 
280
  return buf->data;
 
281
}
 
282
 
 
283
const char *
 
284
svn_x509_certinfo_get_subject(const svn_x509_certinfo_t *certinfo,
 
285
                              apr_pool_t *result_pool)
 
286
{
 
287
  return get_dn(certinfo->subject, result_pool);
 
288
}
 
289
 
 
290
const apr_array_header_t *
 
291
svn_x509_certinfo_get_subject_attrs(const svn_x509_certinfo_t *certinfo)
 
292
{
 
293
  return certinfo->subject;
 
294
}
 
295
 
 
296
const char *
 
297
svn_x509_certinfo_get_issuer(const svn_x509_certinfo_t *certinfo,
 
298
                             apr_pool_t *result_pool)
 
299
{
 
300
  return get_dn(certinfo->issuer, result_pool);
 
301
}
 
302
 
 
303
const apr_array_header_t *
 
304
svn_x509_certinfo_get_issuer_attrs(const svn_x509_certinfo_t *certinfo)
 
305
{
 
306
  return certinfo->issuer;
 
307
}
 
308
 
 
309
apr_time_t
 
310
svn_x509_certinfo_get_valid_from(const svn_x509_certinfo_t *certinfo)
 
311
{
 
312
  return certinfo->valid_from;
 
313
}
 
314
 
 
315
const apr_time_t
 
316
svn_x509_certinfo_get_valid_to(const svn_x509_certinfo_t *certinfo)
 
317
{
 
318
  return certinfo->valid_to;
 
319
}
 
320
 
 
321
const svn_checksum_t *
 
322
svn_x509_certinfo_get_digest(const svn_x509_certinfo_t *certinfo)
 
323
{
 
324
  return certinfo->digest;
 
325
}
 
326
 
 
327
const apr_array_header_t *
 
328
svn_x509_certinfo_get_hostnames(const svn_x509_certinfo_t *certinfo)
 
329
{
 
330
  return certinfo->hostnames;
 
331
}
 
332