Coverage Report

Created: 2024-02-29 06:05

/src/strongswan/src/libstrongswan/credentials/credential_factory.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2008 Martin Willi
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
#include <stdint.h>
18
19
#include "credential_factory.h"
20
21
#include <utils/debug.h>
22
#include <collections/linked_list.h>
23
#include <threading/thread_value.h>
24
#include <threading/rwlock.h>
25
#include <credentials/certificates/x509.h>
26
#include <credentials/containers/container.h>
27
28
ENUM(credential_type_names, CRED_PRIVATE_KEY, CRED_CONTAINER,
29
  "CRED_PRIVATE_KEY",
30
  "CRED_PUBLIC_KEY",
31
  "CRED_CERTIFICATE",
32
  "CRED_CONTAINER",
33
);
34
35
typedef struct private_credential_factory_t private_credential_factory_t;
36
37
/**
38
 * private data of credential_factory
39
 */
40
struct private_credential_factory_t {
41
42
  /**
43
   * public functions
44
   */
45
  credential_factory_t public;
46
47
  /**
48
   * list with entry_t
49
   */
50
  linked_list_t *constructors;
51
52
  /**
53
   * Thread specific recursiveness counter
54
   */
55
  thread_value_t *recursive;
56
57
  /**
58
   * lock access to builders
59
   */
60
  rwlock_t *lock;
61
};
62
63
typedef struct entry_t entry_t;
64
struct entry_t {
65
  /** kind of credential builder */
66
  credential_type_t type;
67
  /** subtype of credential, e.g. certificate_type_t */
68
  int subtype;
69
  /** registered with final flag? */
70
  bool final;
71
  /** plugin that registered this algorithm */
72
  const char *plugin_name;
73
  /** builder function */
74
  builder_function_t constructor;
75
};
76
77
METHOD(credential_factory_t, add_builder, void,
78
  private_credential_factory_t *this, credential_type_t type, int subtype,
79
  bool final, const char *plugin_name, builder_function_t constructor)
80
98.4k
{
81
98.4k
  entry_t *entry = malloc_thing(entry_t);
82
83
98.4k
  entry->type = type;
84
98.4k
  entry->subtype = subtype;
85
98.4k
  entry->final = final;
86
98.4k
  entry->plugin_name = plugin_name;
87
98.4k
  entry->constructor = constructor;
88
98.4k
  this->lock->write_lock(this->lock);
89
98.4k
  this->constructors->insert_last(this->constructors, entry);
90
98.4k
  this->lock->unlock(this->lock);
91
98.4k
}
92
93
METHOD(credential_factory_t, remove_builder, void,
94
  private_credential_factory_t *this, builder_function_t constructor)
95
98.4k
{
96
98.4k
  enumerator_t *enumerator;
97
98.4k
  entry_t *entry;
98
99
98.4k
  this->lock->write_lock(this->lock);
100
98.4k
  enumerator = this->constructors->create_enumerator(this->constructors);
101
1.41M
  while (enumerator->enumerate(enumerator, &entry))
102
1.31M
  {
103
1.31M
    if (entry->constructor == constructor)
104
98.4k
    {
105
98.4k
      this->constructors->remove_at(this->constructors, enumerator);
106
98.4k
      free(entry);
107
98.4k
    }
108
1.31M
  }
109
98.4k
  enumerator->destroy(enumerator);
110
98.4k
  this->lock->unlock(this->lock);
111
98.4k
}
112
113
METHOD(credential_factory_t, create, void*,
114
  private_credential_factory_t *this, credential_type_t type, int subtype, ...)
115
21.5k
{
116
21.5k
  enumerator_t *enumerator;
117
21.5k
  entry_t *entry;
118
21.5k
  va_list args;
119
21.5k
  void *construct = NULL;
120
21.5k
  int failures = 0;
121
21.5k
  uintptr_t level;
122
21.5k
  enum_name_t *names DBG_UNUSED;
123
124
21.5k
  switch (type)
125
21.5k
  {
126
19.3k
    case CRED_CERTIFICATE:
127
19.3k
      names = certificate_type_names;
128
19.3k
      break;
129
0
    case CRED_CONTAINER:
130
0
      names = container_type_names;
131
0
      break;
132
0
    case CRED_PRIVATE_KEY:
133
2.16k
    case CRED_PUBLIC_KEY:
134
2.16k
    default:
135
2.16k
      names = key_type_names;
136
2.16k
      break;
137
21.5k
  }
138
139
21.5k
  level = (uintptr_t)this->recursive->get(this->recursive);
140
21.5k
  this->recursive->set(this->recursive, (void*)level + 1);
141
142
21.5k
  this->lock->read_lock(this->lock);
143
21.5k
  enumerator = this->constructors->create_enumerator(this->constructors);
144
554k
  while (enumerator->enumerate(enumerator, &entry))
145
536k
  {
146
536k
    if (entry->type == type && entry->subtype == subtype)
147
60.2k
    {
148
60.2k
      DBG2(DBG_LIB, "builder L%d %N - %N of plugin '%s'",
149
60.2k
         (int)level, credential_type_names, type, names, subtype,
150
60.2k
         entry->plugin_name);
151
60.2k
      va_start(args, subtype);
152
60.2k
      construct = entry->constructor(subtype, args);
153
60.2k
      va_end(args);
154
60.2k
      if (construct)
155
3.20k
      {
156
3.20k
        break;
157
3.20k
      }
158
57.0k
      failures++;
159
57.0k
    }
160
536k
  }
161
21.5k
  enumerator->destroy(enumerator);
162
21.5k
  this->lock->unlock(this->lock);
163
164
21.5k
  if (!construct && !level)
165
3.18k
  {
166
3.18k
    DBG1(DBG_LIB, "building %N - %N failed, tried %d builders",
167
3.18k
       credential_type_names, type, names, subtype, failures);
168
3.18k
  }
169
21.5k
  this->recursive->set(this->recursive, (void*)level);
170
21.5k
  return construct;
171
21.5k
}
172
173
CALLBACK(builder_filter, bool,
174
  void *null, enumerator_t *orig, va_list args)
175
0
{
176
0
  entry_t *entry;
177
0
  credential_type_t *type;
178
0
  int *subtype;
179
180
0
  VA_ARGS_VGET(args, type, subtype);
181
182
0
  while (orig->enumerate(orig, &entry))
183
0
  {
184
0
    if (entry->final)
185
0
    {
186
0
      *type = entry->type;
187
0
      *subtype = entry->subtype;
188
0
      return TRUE;
189
0
    }
190
0
  }
191
0
  return FALSE;
192
0
}
193
194
METHOD(credential_factory_t, create_builder_enumerator, enumerator_t*,
195
  private_credential_factory_t *this)
196
0
{
197
0
  this->lock->read_lock(this->lock);
198
0
  return enumerator_create_filter(
199
0
        this->constructors->create_enumerator(this->constructors),
200
0
        builder_filter, this->lock, (void*)this->lock->unlock);
201
0
}
202
203
METHOD(credential_factory_t, destroy, void,
204
  private_credential_factory_t *this)
205
3.51k
{
206
3.51k
  this->constructors->destroy_function(this->constructors, free);
207
3.51k
  this->recursive->destroy(this->recursive);
208
3.51k
  this->lock->destroy(this->lock);
209
3.51k
  free(this);
210
3.51k
}
211
212
/*
213
 * see header file
214
 */
215
credential_factory_t *credential_factory_create()
216
3.51k
{
217
3.51k
  private_credential_factory_t *this;
218
219
3.51k
  INIT(this,
220
3.51k
    .public = {
221
3.51k
      .create = _create,
222
3.51k
      .create_builder_enumerator = _create_builder_enumerator,
223
3.51k
      .add_builder = _add_builder,
224
3.51k
      .remove_builder = _remove_builder,
225
3.51k
      .destroy = _destroy,
226
3.51k
    },
227
3.51k
    .constructors = linked_list_create(),
228
3.51k
    .recursive = thread_value_create(NULL),
229
3.51k
    .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
230
3.51k
  );
231
232
3.51k
  return &this->public;
233
3.51k
}
234