Coverage Report

Created: 2025-03-18 06:55

/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 overwrite_attribute(asn1_node asn, const char *root, unsigned indx,
41
             const gnutls_datum_t *ext_data)
42
0
{
43
0
  char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE];
44
0
  int result;
45
46
0
  snprintf(name, sizeof(name), "%s.?%u", root, indx);
47
48
0
  _gnutls_str_cpy(name2, sizeof(name2), name);
49
0
  _gnutls_str_cat(name2, sizeof(name2), ".values.?LAST");
50
51
0
  result = _gnutls_x509_write_value(asn, name2, ext_data);
52
0
  if (result < 0) {
53
0
    gnutls_assert();
54
0
    return result;
55
0
  }
56
57
0
  return 0;
58
0
}
59
60
/* Parses an Attribute list in the asn1_struct, and searches for the
61
 * given OID. The index indicates the attribute value to be returned.
62
 *
63
 * If raw==0 only printable data are returned, or
64
 * GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE.
65
 *
66
 * asn1_attr_name must be a string in the form
67
 * "certificationRequestInfo.attributes"
68
 *
69
 */
70
int _x509_parse_attribute(asn1_node asn1_struct, const char *attr_name,
71
        const char *given_oid, unsigned indx, int raw,
72
        gnutls_datum_t *out)
73
0
{
74
0
  int k1, result;
75
0
  char tmpbuffer1[MAX_NAME_SIZE];
76
0
  char tmpbuffer3[MAX_NAME_SIZE];
77
0
  char value[200];
78
0
  gnutls_datum_t td;
79
0
  char oid[MAX_OID_SIZE];
80
0
  int len;
81
82
0
  k1 = 0;
83
0
  do {
84
0
    k1++;
85
    /* create a string like "attribute.?1"
86
     */
87
0
    if (attr_name[0] != 0)
88
0
      snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%d",
89
0
         attr_name, k1);
90
0
    else
91
0
      snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%d", k1);
92
93
0
    len = sizeof(value) - 1;
94
0
    result = asn1_read_value(asn1_struct, tmpbuffer1, value, &len);
95
96
0
    if (result == ASN1_ELEMENT_NOT_FOUND) {
97
0
      gnutls_assert();
98
0
      break;
99
0
    }
100
101
0
    if (result != ASN1_VALUE_NOT_FOUND) {
102
0
      gnutls_assert();
103
0
      result = _gnutls_asn2err(result);
104
0
      goto cleanup;
105
0
    }
106
107
    /* Move to the attribute type and values
108
     */
109
    /* Read the OID
110
     */
111
0
    _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer1);
112
0
    _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".type");
113
114
0
    len = sizeof(oid) - 1;
115
0
    result = asn1_read_value(asn1_struct, tmpbuffer3, oid, &len);
116
117
0
    if (result == ASN1_ELEMENT_NOT_FOUND)
118
0
      break;
119
0
    else if (result != ASN1_SUCCESS) {
120
0
      gnutls_assert();
121
0
      result = _gnutls_asn2err(result);
122
0
      goto cleanup;
123
0
    }
124
125
0
    if (strcmp(oid, given_oid) == 0) { /* Found the OID */
126
127
      /* Read the Value
128
       */
129
0
      snprintf(tmpbuffer3, sizeof(tmpbuffer3),
130
0
         "%s.values.?%u", tmpbuffer1, indx + 1);
131
132
0
      len = sizeof(value) - 1;
133
0
      result = _gnutls_x509_read_value(asn1_struct,
134
0
               tmpbuffer3, &td);
135
136
0
      if (result != ASN1_SUCCESS) {
137
0
        gnutls_assert();
138
0
        result = _gnutls_asn2err(result);
139
0
        goto cleanup;
140
0
      }
141
142
0
      if (raw == 0) {
143
0
        result = _gnutls_x509_dn_to_string(
144
0
          oid, td.data, td.size, out);
145
146
0
        _gnutls_free_datum(&td);
147
148
0
        if (result < 0) {
149
0
          gnutls_assert();
150
0
          goto cleanup;
151
0
        }
152
0
        return 0;
153
0
      } else { /* raw!=0 */
154
0
        out->data = td.data;
155
0
        out->size = td.size;
156
157
0
        return 0;
158
0
      }
159
0
    }
160
161
0
  } while (1);
162
163
0
  gnutls_assert();
164
165
0
  result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
166
167
0
cleanup:
168
0
  return result;
169
0
}
170
171
/* This function will attempt to set the requested attribute in
172
 * the given X509v3 certificate.
173
 *
174
 * Critical will be either 0 or 1.
175
 */
176
static int add_attribute(asn1_node asn, const char *root,
177
       const char *attribute_id,
178
       const gnutls_datum_t *ext_data)
179
0
{
180
0
  int result;
181
0
  char name[MAX_NAME_SIZE];
182
183
0
  snprintf(name, sizeof(name), "%s", root);
184
185
  /* Add a new attribute in the list.
186
   */
187
0
  result = asn1_write_value(asn, name, "NEW", 1);
188
0
  if (result != ASN1_SUCCESS) {
189
0
    gnutls_assert();
190
0
    return _gnutls_asn2err(result);
191
0
  }
192
193
0
  snprintf(name, sizeof(name), "%s.?LAST.type", root);
194
195
0
  result = asn1_write_value(asn, name, attribute_id, 1);
196
0
  if (result != ASN1_SUCCESS) {
197
0
    gnutls_assert();
198
0
    return _gnutls_asn2err(result);
199
0
  }
200
201
0
  snprintf(name, sizeof(name), "%s.?LAST.values", root);
202
203
0
  result = asn1_write_value(asn, name, "NEW", 1);
204
0
  if (result != ASN1_SUCCESS) {
205
0
    gnutls_assert();
206
0
    return _gnutls_asn2err(result);
207
0
  }
208
209
0
  snprintf(name, sizeof(name), "%s.?LAST.values.?LAST", root);
210
211
0
  result = _gnutls_x509_write_value(asn, name, ext_data);
212
0
  if (result < 0) {
213
0
    gnutls_assert();
214
0
    return result;
215
0
  }
216
217
0
  return 0;
218
0
}
219
220
int _x509_set_attribute(asn1_node asn, const char *root, const char *ext_id,
221
      const gnutls_datum_t *ext_data)
222
0
{
223
0
  int result;
224
0
  int k, len;
225
0
  char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE];
226
0
  char extnID[MAX_OID_SIZE];
227
228
  /* Find the index of the given attribute.
229
   */
230
0
  k = 0;
231
0
  do {
232
0
    k++;
233
234
0
    snprintf(name, sizeof(name), "%s.?%d", root, k);
235
236
0
    len = sizeof(extnID) - 1;
237
0
    result = asn1_read_value(asn, name, extnID, &len);
238
239
    /* move to next
240
     */
241
242
0
    if (result == ASN1_ELEMENT_NOT_FOUND) {
243
0
      break;
244
0
    }
245
246
0
    do {
247
0
      _gnutls_str_cpy(name2, sizeof(name2), name);
248
0
      _gnutls_str_cat(name2, sizeof(name2), ".type");
249
250
0
      len = sizeof(extnID) - 1;
251
0
      result = asn1_read_value(asn, name2, extnID, &len);
252
253
0
      if (result == ASN1_ELEMENT_NOT_FOUND) {
254
0
        gnutls_assert();
255
0
        break;
256
0
      } else if (result != ASN1_SUCCESS) {
257
0
        gnutls_assert();
258
0
        return _gnutls_asn2err(result);
259
0
      }
260
261
      /* Handle Extension
262
       */
263
0
      if (strcmp(extnID, ext_id) == 0) {
264
        /* attribute was found
265
         */
266
0
        return overwrite_attribute(asn, root, k,
267
0
                 ext_data);
268
0
      }
269
270
0
    } while (0);
271
0
  } while (1);
272
273
0
  if (result == ASN1_ELEMENT_NOT_FOUND) {
274
0
    return add_attribute(asn, root, ext_id, ext_data);
275
0
  } else {
276
0
    gnutls_assert();
277
0
    return _gnutls_asn2err(result);
278
0
  }
279
280
0
  return 0;
281
0
}