Coverage Report

Created: 2026-05-30 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/strongswan/src/libimcv/ita/ita_attr_settings.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2012-2014 Andreas Steffen
3
 *
4
 * Copyright (C) secunet Security Networks AG
5
 *
6
 * This program is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU General Public License as published by the
8
 * Free Software Foundation; either version 2 of the License, or (at your
9
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
10
 *
11
 * This program is distributed in the hope that it will be useful, but
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14
 * for more details.
15
 */
16
17
#define _GNU_SOURCE /* for stdndup() */
18
#include <string.h>
19
20
#include "ita_attr.h"
21
#include "ita_attr_settings.h"
22
23
#include <bio/bio_reader.h>
24
#include <bio/bio_writer.h>
25
#include <collections/linked_list.h>
26
#include <pen/pen.h>
27
#include <utils/debug.h>
28
29
typedef struct private_ita_attr_settings_t private_ita_attr_settings_t;
30
typedef struct entry_t entry_t;
31
32
/**
33
 * Contains a settings name/value pair
34
 */
35
struct entry_t {
36
  char *name;
37
  chunk_t value;
38
};
39
40
/**
41
 * Free an entry_t object
42
 */
43
static void free_entry(entry_t *this)
44
96.6k
{
45
96.6k
  free(this->name);
46
96.6k
  free(this->value.ptr);
47
96.6k
  free(this);
48
96.6k
}
49
50
/**
51
 * ITA Settings
52
 *
53
 *             1           2           3
54
 *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
55
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56
 *  |                         Settings Count                        |
57
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58
 *  |        Name Length            |  Name (Variable Length)       ~
59
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60
 *  ~                      Name (Variable Length)                   ~
61
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62
 *  |        Value Length           |  Value (Variable Length)      ~
63
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64
 *  ~                      Value (Variable Length)                  ~
65
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66
 *  |        Name Length            |  Name (Variable Length)       ~
67
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68
 *  ~                      Name (Variable Length)                   ~
69
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70
 *  |        Value Length           |  Value (Variable Length)      ~
71
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72
 *  ~                      Value (Variable Length)                  ~
73
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
74
 *           ...........................
75
 */
76
77
1.52k
#define ITA_SETTINGS_MIN_SIZE 4
78
79
/**
80
 * Private data of an ita_attr_settings_t object.
81
 */
82
struct private_ita_attr_settings_t {
83
84
  /**
85
   * Public members of ita_attr_settings_t
86
   */
87
  ita_attr_settings_t public;
88
89
  /**
90
   * Vendor-specific attribute type
91
   */
92
  pen_type_t type;
93
94
  /**
95
   * Length of attribute value
96
   */
97
  size_t length;
98
99
  /**
100
   * Attribute value or segment
101
   */
102
  chunk_t value;
103
104
  /**
105
   * Noskip flag
106
   */
107
  bool noskip_flag;
108
109
  /**
110
   * List of settings
111
   */
112
  linked_list_t *list;
113
114
  /**
115
   * Reference count
116
   */
117
  refcount_t ref;
118
};
119
120
METHOD(pa_tnc_attr_t, get_type, pen_type_t,
121
  private_ita_attr_settings_t *this)
122
1.04k
{
123
1.04k
  return this->type;
124
1.04k
}
125
126
METHOD(pa_tnc_attr_t, get_value, chunk_t,
127
  private_ita_attr_settings_t *this)
128
765
{
129
765
  return this->value;
130
765
}
131
132
METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
133
  private_ita_attr_settings_t *this)
134
654
{
135
654
  return this->noskip_flag;
136
654
}
137
138
METHOD(pa_tnc_attr_t, set_noskip_flag,void,
139
  private_ita_attr_settings_t *this, bool noskip)
140
0
{
141
0
  this->noskip_flag = noskip;
142
0
}
143
144
METHOD(pa_tnc_attr_t, build, void,
145
  private_ita_attr_settings_t *this)
146
0
{
147
0
  bio_writer_t *writer;
148
0
  enumerator_t *enumerator;
149
0
  entry_t *entry;
150
151
0
  if (this->value.ptr)
152
0
  {
153
0
    return;
154
0
  }
155
0
  writer = bio_writer_create(ITA_SETTINGS_MIN_SIZE);
156
0
  writer->write_uint32(writer, this->list->get_count(this->list));
157
158
0
  enumerator = this->list->create_enumerator(this->list);
159
0
  while (enumerator->enumerate(enumerator, &entry))
160
0
  {
161
0
    writer->write_data16(writer, chunk_create(entry->name,
162
0
                          strlen(entry->name)));
163
0
    writer->write_data16(writer, entry->value);
164
0
  }
165
0
  enumerator->destroy(enumerator);
166
167
0
  this->value = writer->extract_buf(writer);
168
0
  this->length = this->value.len;
169
0
  writer->destroy(writer);
170
0
}
171
172
METHOD(pa_tnc_attr_t, process, status_t,
173
  private_ita_attr_settings_t *this, uint32_t *offset)
174
765
{
175
765
  bio_reader_t *reader;
176
765
  uint32_t count;
177
765
  chunk_t name, value;
178
765
  entry_t *entry;
179
765
  status_t status = FAILED;
180
181
765
  *offset = 0;
182
183
765
  if (this->value.len < this->length)
184
0
  {
185
0
    return NEED_MORE;
186
0
  }
187
765
  if (this->value.len < ITA_SETTINGS_MIN_SIZE)
188
10
  {
189
10
    DBG1(DBG_TNC, "insufficient data for ITA Settings attribute");
190
10
    return FAILED;
191
10
  }
192
193
755
  reader = bio_reader_create(this->value);
194
755
  reader->read_uint32(reader, &count);
195
196
755
  *offset = ITA_SETTINGS_MIN_SIZE;
197
198
97.4k
  while (count--)
199
96.7k
  {
200
96.7k
    if (!reader->read_data16(reader, &name))
201
85
    {
202
85
      DBG1(DBG_TNC, "insufficient data for setting name");
203
85
      goto end;
204
85
    }
205
96.6k
    *offset += 2 + name.len;
206
207
96.6k
    if (!reader->read_data16(reader, &value))
208
16
    {
209
16
      DBG1(DBG_TNC, "insufficient data for setting value");
210
16
      goto end;
211
16
    }
212
96.6k
    *offset += 2 + value.len;
213
214
    /* remove a terminating newline character */
215
96.6k
    if (value.len && value.ptr[value.len - 1] == '\n')
216
225
    {
217
225
      value.len--;
218
225
    }
219
96.6k
    entry = malloc_thing(entry_t);
220
96.6k
    entry->name = strndup(name.ptr, name.len);
221
96.6k
    entry->value = chunk_clone(value);
222
96.6k
    this->list->insert_last(this->list, entry);
223
96.6k
  }
224
654
  status = SUCCESS;
225
226
755
end:
227
755
  reader->destroy(reader);
228
755
  return status;
229
654
}
230
231
METHOD(pa_tnc_attr_t, add_segment, void,
232
  private_ita_attr_settings_t *this, chunk_t segment)
233
0
{
234
0
  this->value = chunk_cat("mc", this->value, segment);
235
0
}
236
237
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
238
  private_ita_attr_settings_t *this)
239
0
{
240
0
  ref_get(&this->ref);
241
0
  return &this->public.pa_tnc_attribute;
242
0
}
243
244
METHOD(pa_tnc_attr_t, destroy, void,
245
  private_ita_attr_settings_t *this)
246
765
{
247
765
  if (ref_put(&this->ref))
248
765
  {
249
765
    this->list->destroy_function(this->list, (void*)free_entry);
250
765
    free(this->value.ptr);
251
765
    free(this);
252
765
  }
253
765
}
254
255
METHOD(ita_attr_settings_t, add, void,
256
  private_ita_attr_settings_t *this, char *name, chunk_t value)
257
0
{
258
0
  entry_t *entry;
259
260
0
  entry = malloc_thing(entry_t);
261
0
  entry->name = strdup(name);
262
0
  entry->value = chunk_clone(value);
263
0
  this->list->insert_last(this->list, entry);
264
0
}
265
266
CALLBACK(entry_filter, bool,
267
  void *null, enumerator_t *orig, va_list args)
268
0
{
269
0
  entry_t *entry;
270
0
  chunk_t *value;
271
0
  char **name;
272
273
0
  VA_ARGS_VGET(args, name, value);
274
275
0
  while (orig->enumerate(orig, &entry))
276
0
  {
277
0
    *name = entry->name;
278
0
    *value = entry->value;
279
0
    return TRUE;
280
0
  }
281
0
  return FALSE;
282
0
}
283
284
METHOD(ita_attr_settings_t, create_enumerator, enumerator_t*,
285
  private_ita_attr_settings_t *this)
286
0
{
287
0
  return enumerator_create_filter(this->list->create_enumerator(this->list),
288
0
                  entry_filter, NULL, NULL);
289
0
}
290
291
/**
292
 * Described in header.
293
 */
294
pa_tnc_attr_t *ita_attr_settings_create(void)
295
0
{
296
0
  private_ita_attr_settings_t *this;
297
298
0
  INIT(this,
299
0
    .public = {
300
0
      .pa_tnc_attribute = {
301
0
        .get_type = _get_type,
302
0
        .get_value = _get_value,
303
0
        .get_noskip_flag = _get_noskip_flag,
304
0
        .set_noskip_flag = _set_noskip_flag,
305
0
        .build = _build,
306
0
        .process = _process,
307
0
        .add_segment = _add_segment,
308
0
        .get_ref = _get_ref,
309
0
        .destroy = _destroy,
310
0
      },
311
0
      .add = _add,
312
0
      .create_enumerator = _create_enumerator,
313
0
    },
314
0
    .type = { PEN_ITA, ITA_ATTR_SETTINGS },
315
0
    .list = linked_list_create(),
316
0
    .ref = 1,
317
0
  );
318
319
0
  return &this->public.pa_tnc_attribute;
320
0
}
321
322
/**
323
 * Described in header.
324
 */
325
pa_tnc_attr_t *ita_attr_settings_create_from_data(size_t length, chunk_t data)
326
765
{
327
765
  private_ita_attr_settings_t *this;
328
329
765
  INIT(this,
330
765
    .public = {
331
765
      .pa_tnc_attribute = {
332
765
        .get_type = _get_type,
333
765
        .get_value = _get_value,
334
765
        .get_noskip_flag = _get_noskip_flag,
335
765
        .set_noskip_flag = _set_noskip_flag,
336
765
        .build = _build,
337
765
        .process = _process,
338
765
        .add_segment = _add_segment,
339
765
        .get_ref = _get_ref,
340
765
        .destroy = _destroy,
341
765
      },
342
765
      .add = _add,
343
765
      .create_enumerator = _create_enumerator,
344
765
    },
345
765
    .type = { PEN_ITA, ITA_ATTR_SETTINGS },
346
765
    .length = length,
347
765
    .value = chunk_clone(data),
348
765
    .list = linked_list_create(),
349
765
    .ref = 1,
350
765
  );
351
352
765
  return &this->public.pa_tnc_attribute;
353
765
}
354
355