Coverage Report

Created: 2023-03-26 08:33

/src/gnutls/lib/x509/attributes.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2003-2016 Free Software Foundation, Inc.
3
 * Copyright (C) 2012-2016 Nikos Mavrogiannopoulos
4
 * Copyright (C) 2017 Red Hat, Inc.
5
 *
6
 * Author: Nikos Mavrogiannopoulos
7
 *
8
 * This file is part of GnuTLS.
9
 *
10
 * The GnuTLS is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU Lesser General Public License
12
 * as published by the Free Software Foundation; either version 2.1 of
13
 * the License, or (at your option) any later version.
14
 *
15
 * This library is distributed in the hope that it will be useful, but
16
 * WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
 * Lesser General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Lesser General Public License
21
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
22
 *
23
 */
24
25
#include "gnutls_int.h"
26
27
#include <datum.h>
28
#include "errors.h"
29
#include <common.h>
30
#include <x509.h>
31
#include "x509_int.h"
32
#include "attributes.h"
33
34
/* Functions to parse and set the PKIX1 Attributes structure.
35
 */
36
37
/* Overwrite the given attribute (using the index)
38
 * index here starts from one.
39
 */
40
static int
41
overwrite_attribute(asn1_node asn, const char *root, unsigned indx,
42
        const gnutls_datum_t * ext_data)
43
0
{
44
0
  char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE];
45
0
  int result;
46
47
0
  snprintf(name, sizeof(name), "%s.?%u", root, indx);
48
49
0
  _gnutls_str_cpy(name2, sizeof(name2), name);
50
0
  _gnutls_str_cat(name2, sizeof(name2), ".values.?LAST");
51
52
0
  result = _gnutls_x509_write_value(asn, name2, ext_data);
53
0
  if (result < 0) {
54
0
    gnutls_assert();
55
0
    return result;
56
0
  }
57
58
0
  return 0;
59
0
}
60
61
/* Parses an Attribute list in the asn1_struct, and searches for the
62
 * given OID. The index indicates the attribute value to be returned.
63
 *
64
 * If raw==0 only printable data are returned, or
65
 * GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE.
66
 *
67
 * asn1_attr_name must be a string in the form
68
 * "certificationRequestInfo.attributes"
69
 *
70
 */
71
int
72
_x509_parse_attribute(asn1_node asn1_struct,
73
          const char *attr_name, const char *given_oid,
74
          unsigned indx, int raw, gnutls_datum_t * out)
75
0
{
76
0
  int k1, result;
77
0
  char tmpbuffer1[MAX_NAME_SIZE];
78
0
  char tmpbuffer3[MAX_NAME_SIZE];
79
0
  char value[200];
80
0
  gnutls_datum_t td;
81
0
  char oid[MAX_OID_SIZE];
82
0
  int len;
83
84
0
  k1 = 0;
85
0
  do {
86
87
0
    k1++;
88
    /* create a string like "attribute.?1"
89
     */
90
0
    if (attr_name[0] != 0)
91
0
      snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%d",
92
0
         attr_name, k1);
93
0
    else
94
0
      snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%d", k1);
95
96
0
    len = sizeof(value) - 1;
97
0
    result = asn1_read_value(asn1_struct, tmpbuffer1, value, &len);
98
99
0
    if (result == ASN1_ELEMENT_NOT_FOUND) {
100
0
      gnutls_assert();
101
0
      break;
102
0
    }
103
104
0
    if (result != ASN1_VALUE_NOT_FOUND) {
105
0
      gnutls_assert();
106
0
      result = _gnutls_asn2err(result);
107
0
      goto cleanup;
108
0
    }
109
110
    /* Move to the attribute type and values
111
     */
112
    /* Read the OID
113
     */
114
0
    _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer1);
115
0
    _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".type");
116
117
0
    len = sizeof(oid) - 1;
118
0
    result = asn1_read_value(asn1_struct, tmpbuffer3, oid, &len);
119
120
0
    if (result == ASN1_ELEMENT_NOT_FOUND)
121
0
      break;
122
0
    else if (result != ASN1_SUCCESS) {
123
0
      gnutls_assert();
124
0
      result = _gnutls_asn2err(result);
125
0
      goto cleanup;
126
0
    }
127
128
0
    if (strcmp(oid, given_oid) == 0) { /* Found the OID */
129
130
      /* Read the Value
131
       */
132
0
      snprintf(tmpbuffer3, sizeof(tmpbuffer3),
133
0
         "%s.values.?%u", tmpbuffer1, indx + 1);
134
135
0
      len = sizeof(value) - 1;
136
0
      result =
137
0
          _gnutls_x509_read_value(asn1_struct,
138
0
                tmpbuffer3, &td);
139
140
0
      if (result != ASN1_SUCCESS) {
141
0
        gnutls_assert();
142
0
        result = _gnutls_asn2err(result);
143
0
        goto cleanup;
144
0
      }
145
146
0
      if (raw == 0) {
147
0
        result =
148
0
            _gnutls_x509_dn_to_string
149
0
            (oid, td.data, td.size, out);
150
151
0
        _gnutls_free_datum(&td);
152
153
0
        if (result < 0) {
154
0
          gnutls_assert();
155
0
          goto cleanup;
156
0
        }
157
0
        return 0;
158
0
      } else { /* raw!=0 */
159
0
        out->data = td.data;
160
0
        out->size = td.size;
161
162
0
        return 0;
163
0
      }
164
0
    }
165
166
0
  }
167
0
  while (1);
168
169
0
  gnutls_assert();
170
171
0
  result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
172
173
0
 cleanup:
174
0
  return result;
175
0
}
176
177
/* This function will attempt to set the requested attribute in
178
 * the given X509v3 certificate.
179
 *
180
 * Critical will be either 0 or 1.
181
 */
182
static int
183
add_attribute(asn1_node asn, const char *root, const char *attribute_id,
184
        const gnutls_datum_t * ext_data)
185
0
{
186
0
  int result;
187
0
  char name[MAX_NAME_SIZE];
188
189
0
  snprintf(name, sizeof(name), "%s", root);
190
191
  /* Add a new attribute in the list.
192
   */
193
0
  result = asn1_write_value(asn, name, "NEW", 1);
194
0
  if (result != ASN1_SUCCESS) {
195
0
    gnutls_assert();
196
0
    return _gnutls_asn2err(result);
197
0
  }
198
199
0
  snprintf(name, sizeof(name), "%s.?LAST.type", root);
200
201
0
  result = asn1_write_value(asn, name, attribute_id, 1);
202
0
  if (result != ASN1_SUCCESS) {
203
0
    gnutls_assert();
204
0
    return _gnutls_asn2err(result);
205
0
  }
206
207
0
  snprintf(name, sizeof(name), "%s.?LAST.values", root);
208
209
0
  result = asn1_write_value(asn, name, "NEW", 1);
210
0
  if (result != ASN1_SUCCESS) {
211
0
    gnutls_assert();
212
0
    return _gnutls_asn2err(result);
213
0
  }
214
215
0
  snprintf(name, sizeof(name), "%s.?LAST.values.?LAST", root);
216
217
0
  result = _gnutls_x509_write_value(asn, name, ext_data);
218
0
  if (result < 0) {
219
0
    gnutls_assert();
220
0
    return result;
221
0
  }
222
223
0
  return 0;
224
0
}
225
226
int
227
_x509_set_attribute(asn1_node asn, const char *root,
228
        const char *ext_id, const gnutls_datum_t * ext_data)
229
0
{
230
0
  int result;
231
0
  int k, len;
232
0
  char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE];
233
0
  char extnID[MAX_OID_SIZE];
234
235
  /* Find the index of the given attribute.
236
   */
237
0
  k = 0;
238
0
  do {
239
0
    k++;
240
241
0
    snprintf(name, sizeof(name), "%s.?%d", root, k);
242
243
0
    len = sizeof(extnID) - 1;
244
0
    result = asn1_read_value(asn, name, extnID, &len);
245
246
    /* move to next
247
     */
248
249
0
    if (result == ASN1_ELEMENT_NOT_FOUND) {
250
0
      break;
251
0
    }
252
253
0
    do {
254
255
0
      _gnutls_str_cpy(name2, sizeof(name2), name);
256
0
      _gnutls_str_cat(name2, sizeof(name2), ".type");
257
258
0
      len = sizeof(extnID) - 1;
259
0
      result = asn1_read_value(asn, name2, extnID, &len);
260
261
0
      if (result == ASN1_ELEMENT_NOT_FOUND) {
262
0
        gnutls_assert();
263
0
        break;
264
0
      } else if (result != ASN1_SUCCESS) {
265
0
        gnutls_assert();
266
0
        return _gnutls_asn2err(result);
267
0
      }
268
269
      /* Handle Extension
270
       */
271
0
      if (strcmp(extnID, ext_id) == 0) {
272
        /* attribute was found
273
         */
274
0
        return overwrite_attribute(asn, root, k,
275
0
                 ext_data);
276
0
      }
277
278
0
    }
279
0
    while (0);
280
0
  }
281
0
  while (1);
282
283
0
  if (result == ASN1_ELEMENT_NOT_FOUND) {
284
0
    return add_attribute(asn, root, ext_id, ext_data);
285
0
  } else {
286
0
    gnutls_assert();
287
0
    return _gnutls_asn2err(result);
288
0
  }
289
290
0
  return 0;
291
0
}