Coverage Report

Created: 2025-08-29 06:48

/src/strongswan/src/libstrongswan/credentials/auth_cfg.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2008-2017 Tobias Brunner
3
 * Copyright (C) 2007-2009 Martin Willi
4
 * Copyright (C) 2016 Andreas Steffen
5
 *
6
 * Copyright (C) secunet Security Networks AG
7
 *
8
 * This program is free software; you can redistribute it and/or modify it
9
 * under the terms of the GNU General Public License as published by the
10
 * Free Software Foundation; either version 2 of the License, or (at your
11
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
12
 *
13
 * This program is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16
 * for more details.
17
 */
18
19
#include "auth_cfg.h"
20
21
#include <library.h>
22
#include <utils/debug.h>
23
#include <collections/array.h>
24
#include <utils/identification.h>
25
#include <eap/eap.h>
26
#include <credentials/certificates/certificate.h>
27
28
ENUM(auth_class_names, AUTH_CLASS_ANY, AUTH_CLASS_XAUTH,
29
  "any",
30
  "public key",
31
  "pre-shared key",
32
  "EAP",
33
  "XAuth",
34
);
35
36
ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_AC_CERT,
37
  "RULE_IDENTITY",
38
  "RULE_IDENTITY_LOOSE",
39
  "RULE_AUTH_CLASS",
40
  "RULE_AAA_IDENTITY",
41
  "RULE_EAP_IDENTITY",
42
  "RULE_EAP_TYPE",
43
  "RULE_EAP_VENDOR",
44
  "RULE_XAUTH_BACKEND",
45
  "RULE_XAUTH_IDENTITY",
46
  "RULE_CA_IDENTITY",
47
  "RULE_CA_CERT",
48
  "RULE_IM_CERT",
49
  "RULE_SUBJECT_CERT",
50
  "RULE_CRL_VALIDATION",
51
  "RULE_OCSP_VALIDATION",
52
  "RULE_CERT_VALIDATION_SUSPENDED",
53
  "RULE_GROUP",
54
  "RULE_RSA_STRENGTH",
55
  "RULE_ECDSA_STRENGTH",
56
  "RULE_SIGNATURE_SCHEME",
57
  "RULE_IKE_SIGNATURE_SCHEME",
58
  "RULE_CERT_POLICY",
59
  "HELPER_IM_CERT",
60
  "HELPER_SUBJECT_CERT",
61
  "HELPER_IM_HASH_URL",
62
  "HELPER_SUBJECT_HASH_URL",
63
  "HELPER_REVOCATION_CERT",
64
  "HELPER_AC_CERT",
65
);
66
67
ENUM(auth_rule_names_lower, AUTH_RULE_IDENTITY, AUTH_HELPER_AC_CERT,
68
  "identity",
69
  "identity_loose",
70
  "auth_class",
71
  "aaa_identity",
72
  "eap_identity",
73
  "eap_type",
74
  "eap_vendor",
75
  "xauth_backend",
76
  "xauth_identity",
77
  "ca_identity",
78
  "ca_cert",
79
  "im_cert",
80
  "subject_cert",
81
  "crl_validation",
82
  "ocsp_validation",
83
  "cert_validation_suspended",
84
  "group",
85
  "rsa_strength",
86
  "ecdsa_strength",
87
  "signature_scheme",
88
  "ike_signature_scheme",
89
  "cert_policy",
90
  "im_cert",
91
  "subject_cert",
92
  "im_hash_url",
93
  "subject_hash_url",
94
  "revocation_cert",
95
  "ac_cert",
96
);
97
98
/**
99
 * Check if the given rule is a rule for which there may be multiple values.
100
 */
101
static inline bool is_multi_value_rule(auth_rule_t type)
102
0
{
103
0
  switch (type)
104
0
  {
105
0
    case AUTH_RULE_AUTH_CLASS:
106
0
    case AUTH_RULE_EAP_TYPE:
107
0
    case AUTH_RULE_EAP_VENDOR:
108
0
    case AUTH_RULE_IDENTITY:
109
0
    case AUTH_RULE_IDENTITY_LOOSE:
110
0
    case AUTH_RULE_EAP_IDENTITY:
111
0
    case AUTH_RULE_AAA_IDENTITY:
112
0
    case AUTH_RULE_XAUTH_IDENTITY:
113
0
    case AUTH_RULE_XAUTH_BACKEND:
114
0
    case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
115
0
    case AUTH_HELPER_SUBJECT_CERT:
116
0
    case AUTH_HELPER_SUBJECT_HASH_URL:
117
0
    case AUTH_RULE_MAX:
118
0
      return FALSE;
119
0
    case AUTH_RULE_OCSP_VALIDATION:
120
0
    case AUTH_RULE_CRL_VALIDATION:
121
0
    case AUTH_RULE_GROUP:
122
0
    case AUTH_RULE_SUBJECT_CERT:
123
0
    case AUTH_RULE_CA_IDENTITY:
124
0
    case AUTH_RULE_CA_CERT:
125
0
    case AUTH_RULE_IM_CERT:
126
0
    case AUTH_RULE_CERT_POLICY:
127
0
    case AUTH_RULE_RSA_STRENGTH:
128
0
    case AUTH_RULE_ECDSA_STRENGTH:
129
0
    case AUTH_RULE_SIGNATURE_SCHEME:
130
0
    case AUTH_RULE_IKE_SIGNATURE_SCHEME:
131
0
    case AUTH_HELPER_IM_CERT:
132
0
    case AUTH_HELPER_IM_HASH_URL:
133
0
    case AUTH_HELPER_REVOCATION_CERT:
134
0
    case AUTH_HELPER_AC_CERT:
135
0
      return TRUE;
136
0
  }
137
0
  return FALSE;
138
0
}
139
140
typedef struct private_auth_cfg_t private_auth_cfg_t;
141
142
/**
143
 * private data of item_set
144
 */
145
struct private_auth_cfg_t {
146
147
  /**
148
   * public functions
149
   */
150
  auth_cfg_t public;
151
152
  /**
153
   * Array of entry_t
154
   */
155
  array_t *entries;
156
};
157
158
typedef struct entry_t entry_t;
159
160
struct entry_t {
161
  /** rule type */
162
  auth_rule_t type;
163
  /** associated value */
164
  void *value;
165
};
166
167
/**
168
 * enumerator for auth_cfg_t.create_enumerator()
169
 */
170
typedef struct {
171
  /** implements enumerator_t */
172
  enumerator_t public;
173
  /** inner enumerator from linked_list_t */
174
  enumerator_t *inner;
175
  /** current entry */
176
  entry_t *current;
177
  /** types we have already enumerated */
178
  bool enumerated[AUTH_RULE_MAX];
179
} entry_enumerator_t;
180
181
METHOD(enumerator_t, enumerate, bool,
182
  entry_enumerator_t *this, va_list args)
183
0
{
184
0
  auth_rule_t *type;
185
0
  entry_t *entry;
186
0
  void **value;
187
188
0
  VA_ARGS_VGET(args, type, value);
189
190
0
  while (this->inner->enumerate(this->inner, &entry))
191
0
  {
192
0
    if (!is_multi_value_rule(entry->type) && this->enumerated[entry->type])
193
0
    {
194
0
      continue;
195
0
    }
196
0
    this->enumerated[entry->type] = TRUE;
197
0
    this->current = entry;
198
0
    if (type)
199
0
    {
200
0
      *type = entry->type;
201
0
    }
202
0
    if (value)
203
0
    {
204
0
      *value = entry->value;
205
0
    }
206
0
    return TRUE;
207
0
  }
208
0
  return FALSE;
209
0
}
210
211
METHOD(enumerator_t, entry_enumerator_destroy, void,
212
  entry_enumerator_t *this)
213
0
{
214
0
  this->inner->destroy(this->inner);
215
0
  free(this);
216
0
}
217
218
METHOD(auth_cfg_t, create_enumerator, enumerator_t*,
219
  private_auth_cfg_t *this)
220
0
{
221
0
  entry_enumerator_t *enumerator;
222
223
0
  INIT(enumerator,
224
0
    .public = {
225
0
      .enumerate = enumerator_enumerate_default,
226
0
      .venumerate = _enumerate,
227
0
      .destroy = _entry_enumerator_destroy,
228
0
    },
229
0
    .inner = array_create_enumerator(this->entries),
230
0
  );
231
0
  return &enumerator->public;
232
0
}
233
234
/**
235
 * Initialize an entry.
236
 */
237
static void init_entry(entry_t *this, auth_rule_t type, va_list args)
238
0
{
239
0
  this->type = type;
240
0
  switch (type)
241
0
  {
242
0
    case AUTH_RULE_IDENTITY_LOOSE:
243
0
    case AUTH_RULE_AUTH_CLASS:
244
0
    case AUTH_RULE_EAP_TYPE:
245
0
    case AUTH_RULE_EAP_VENDOR:
246
0
    case AUTH_RULE_CRL_VALIDATION:
247
0
    case AUTH_RULE_OCSP_VALIDATION:
248
0
    case AUTH_RULE_RSA_STRENGTH:
249
0
    case AUTH_RULE_ECDSA_STRENGTH:
250
0
    case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
251
      /* integer type */
252
0
      this->value = (void*)(uintptr_t)va_arg(args, u_int);
253
0
      break;
254
0
    case AUTH_RULE_IDENTITY:
255
0
    case AUTH_RULE_EAP_IDENTITY:
256
0
    case AUTH_RULE_AAA_IDENTITY:
257
0
    case AUTH_RULE_XAUTH_BACKEND:
258
0
    case AUTH_RULE_XAUTH_IDENTITY:
259
0
    case AUTH_RULE_GROUP:
260
0
    case AUTH_RULE_CA_IDENTITY:
261
0
    case AUTH_RULE_CA_CERT:
262
0
    case AUTH_RULE_IM_CERT:
263
0
    case AUTH_RULE_SUBJECT_CERT:
264
0
    case AUTH_RULE_CERT_POLICY:
265
0
    case AUTH_RULE_SIGNATURE_SCHEME:
266
0
    case AUTH_RULE_IKE_SIGNATURE_SCHEME:
267
0
    case AUTH_HELPER_IM_CERT:
268
0
    case AUTH_HELPER_SUBJECT_CERT:
269
0
    case AUTH_HELPER_IM_HASH_URL:
270
0
    case AUTH_HELPER_SUBJECT_HASH_URL:
271
0
    case AUTH_HELPER_REVOCATION_CERT:
272
0
    case AUTH_HELPER_AC_CERT:
273
      /* pointer type */
274
0
      this->value = va_arg(args, void*);
275
0
      break;
276
0
    case AUTH_RULE_MAX:
277
0
      this->value = NULL;
278
0
      break;
279
0
  }
280
0
}
281
282
/**
283
 * Compare two entries for equality.
284
 */
285
static bool entry_equals(entry_t *e1, entry_t *e2)
286
0
{
287
0
  if (e1->type != e2->type)
288
0
  {
289
0
    return FALSE;
290
0
  }
291
0
  switch (e1->type)
292
0
  {
293
0
    case AUTH_RULE_IDENTITY_LOOSE:
294
0
    case AUTH_RULE_AUTH_CLASS:
295
0
    case AUTH_RULE_EAP_TYPE:
296
0
    case AUTH_RULE_EAP_VENDOR:
297
0
    case AUTH_RULE_CRL_VALIDATION:
298
0
    case AUTH_RULE_OCSP_VALIDATION:
299
0
    case AUTH_RULE_RSA_STRENGTH:
300
0
    case AUTH_RULE_ECDSA_STRENGTH:
301
0
    case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
302
0
    {
303
0
      return e1->value == e2->value;
304
0
    }
305
0
    case AUTH_RULE_CA_CERT:
306
0
    case AUTH_RULE_IM_CERT:
307
0
    case AUTH_RULE_SUBJECT_CERT:
308
0
    case AUTH_HELPER_IM_CERT:
309
0
    case AUTH_HELPER_SUBJECT_CERT:
310
0
    case AUTH_HELPER_REVOCATION_CERT:
311
0
    case AUTH_HELPER_AC_CERT:
312
0
    {
313
0
      certificate_t *c1, *c2;
314
315
0
      c1 = (certificate_t*)e1->value;
316
0
      c2 = (certificate_t*)e2->value;
317
318
0
      return c1->equals(c1, c2);
319
0
    }
320
0
    case AUTH_RULE_IDENTITY:
321
0
    case AUTH_RULE_CA_IDENTITY:
322
0
    case AUTH_RULE_EAP_IDENTITY:
323
0
    case AUTH_RULE_AAA_IDENTITY:
324
0
    case AUTH_RULE_XAUTH_IDENTITY:
325
0
    case AUTH_RULE_GROUP:
326
0
    {
327
0
      identification_t *id1, *id2;
328
329
0
      id1 = (identification_t*)e1->value;
330
0
      id2 = (identification_t*)e2->value;
331
332
0
      return id1->equals(id1, id2);
333
0
    }
334
0
    case AUTH_RULE_SIGNATURE_SCHEME:
335
0
    case AUTH_RULE_IKE_SIGNATURE_SCHEME:
336
0
    {
337
0
      return signature_params_equal(e1->value, e2->value);
338
0
    }
339
0
    case AUTH_RULE_CERT_POLICY:
340
0
    case AUTH_RULE_XAUTH_BACKEND:
341
0
    case AUTH_HELPER_IM_HASH_URL:
342
0
    case AUTH_HELPER_SUBJECT_HASH_URL:
343
0
    {
344
0
      return streq(e1->value, e2->value);
345
0
    }
346
0
    case AUTH_RULE_MAX:
347
0
      break;
348
0
  }
349
0
  return FALSE;
350
0
}
351
352
/**
353
 * Destroy the value associated with an entry
354
 */
355
static void destroy_entry_value(entry_t *entry)
356
0
{
357
0
  switch (entry->type)
358
0
  {
359
0
    case AUTH_RULE_IDENTITY:
360
0
    case AUTH_RULE_CA_IDENTITY:
361
0
    case AUTH_RULE_EAP_IDENTITY:
362
0
    case AUTH_RULE_AAA_IDENTITY:
363
0
    case AUTH_RULE_GROUP:
364
0
    case AUTH_RULE_XAUTH_IDENTITY:
365
0
    {
366
0
      identification_t *id = (identification_t*)entry->value;
367
0
      id->destroy(id);
368
0
      break;
369
0
    }
370
0
    case AUTH_RULE_CA_CERT:
371
0
    case AUTH_RULE_IM_CERT:
372
0
    case AUTH_RULE_SUBJECT_CERT:
373
0
    case AUTH_HELPER_IM_CERT:
374
0
    case AUTH_HELPER_SUBJECT_CERT:
375
0
    case AUTH_HELPER_REVOCATION_CERT:
376
0
    case AUTH_HELPER_AC_CERT:
377
0
    {
378
0
      certificate_t *cert = (certificate_t*)entry->value;
379
0
      cert->destroy(cert);
380
0
      break;
381
0
    }
382
0
    case AUTH_RULE_CERT_POLICY:
383
0
    case AUTH_RULE_XAUTH_BACKEND:
384
0
    case AUTH_HELPER_IM_HASH_URL:
385
0
    case AUTH_HELPER_SUBJECT_HASH_URL:
386
0
    {
387
0
      free(entry->value);
388
0
      break;
389
0
    }
390
0
    case AUTH_RULE_SIGNATURE_SCHEME:
391
0
    case AUTH_RULE_IKE_SIGNATURE_SCHEME:
392
0
    {
393
0
      signature_params_destroy(entry->value);
394
0
      break;
395
0
    }
396
0
    case AUTH_RULE_IDENTITY_LOOSE:
397
0
    case AUTH_RULE_AUTH_CLASS:
398
0
    case AUTH_RULE_EAP_TYPE:
399
0
    case AUTH_RULE_EAP_VENDOR:
400
0
    case AUTH_RULE_CRL_VALIDATION:
401
0
    case AUTH_RULE_OCSP_VALIDATION:
402
0
    case AUTH_RULE_RSA_STRENGTH:
403
0
    case AUTH_RULE_ECDSA_STRENGTH:
404
0
    case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
405
0
    case AUTH_RULE_MAX:
406
0
      break;
407
0
  }
408
0
}
409
410
/**
411
 * Implementation of auth_cfg_t.replace.
412
 */
413
static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator,
414
          auth_rule_t type, ...)
415
0
{
416
0
  if (enumerator->current)
417
0
  {
418
0
    entry_t *entry;
419
0
    va_list args;
420
421
0
    va_start(args, type);
422
0
    entry = enumerator->current;
423
0
    destroy_entry_value(entry);
424
0
    entry->type = type;
425
0
    switch (type)
426
0
    {
427
0
      case AUTH_RULE_IDENTITY_LOOSE:
428
0
      case AUTH_RULE_AUTH_CLASS:
429
0
      case AUTH_RULE_EAP_TYPE:
430
0
      case AUTH_RULE_EAP_VENDOR:
431
0
      case AUTH_RULE_CRL_VALIDATION:
432
0
      case AUTH_RULE_OCSP_VALIDATION:
433
0
      case AUTH_RULE_RSA_STRENGTH:
434
0
      case AUTH_RULE_ECDSA_STRENGTH:
435
0
      case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
436
        /* integer type */
437
0
        entry->value = (void*)(uintptr_t)va_arg(args, u_int);
438
0
        break;
439
0
      case AUTH_RULE_IDENTITY:
440
0
      case AUTH_RULE_CA_IDENTITY:
441
0
      case AUTH_RULE_EAP_IDENTITY:
442
0
      case AUTH_RULE_AAA_IDENTITY:
443
0
      case AUTH_RULE_XAUTH_BACKEND:
444
0
      case AUTH_RULE_XAUTH_IDENTITY:
445
0
      case AUTH_RULE_GROUP:
446
0
      case AUTH_RULE_CA_CERT:
447
0
      case AUTH_RULE_IM_CERT:
448
0
      case AUTH_RULE_SUBJECT_CERT:
449
0
      case AUTH_RULE_CERT_POLICY:
450
0
      case AUTH_RULE_SIGNATURE_SCHEME:
451
0
      case AUTH_RULE_IKE_SIGNATURE_SCHEME:
452
0
      case AUTH_HELPER_IM_CERT:
453
0
      case AUTH_HELPER_SUBJECT_CERT:
454
0
      case AUTH_HELPER_IM_HASH_URL:
455
0
      case AUTH_HELPER_SUBJECT_HASH_URL:
456
0
      case AUTH_HELPER_REVOCATION_CERT:
457
0
      case AUTH_HELPER_AC_CERT:
458
        /* pointer type */
459
0
        entry->value = va_arg(args, void*);
460
0
        break;
461
0
      case AUTH_RULE_MAX:
462
0
        entry->value = NULL;
463
0
        break;
464
0
    }
465
0
    va_end(args);
466
0
  }
467
0
}
468
469
METHOD(auth_cfg_t, get, void*,
470
  private_auth_cfg_t *this, auth_rule_t type)
471
0
{
472
0
  enumerator_t *enumerator;
473
0
  void *current_value, *best_value = NULL;
474
0
  auth_rule_t current_type;
475
0
  bool found = FALSE;
476
477
0
  enumerator = create_enumerator(this);
478
0
  while (enumerator->enumerate(enumerator, &current_type, &current_value))
479
0
  {
480
0
    if (type == current_type)
481
0
    {
482
0
      if (type == AUTH_RULE_CRL_VALIDATION ||
483
0
        type == AUTH_RULE_OCSP_VALIDATION)
484
0
      { /* for CRL/OCSP validation, always get() the highest value */
485
0
        if (!found || current_value > best_value)
486
0
        {
487
0
          best_value = current_value;
488
0
        }
489
0
        found = TRUE;
490
0
        continue;
491
0
      }
492
0
      best_value = current_value;
493
0
      found = TRUE;
494
0
      break;
495
0
    }
496
0
  }
497
0
  enumerator->destroy(enumerator);
498
0
  if (found)
499
0
  {
500
0
    return best_value;
501
0
  }
502
0
  switch (type)
503
0
  {
504
    /* use some sane defaults if we don't find an entry */
505
0
    case AUTH_RULE_AUTH_CLASS:
506
0
      return (void*)AUTH_CLASS_ANY;
507
0
    case AUTH_RULE_EAP_TYPE:
508
0
      return (void*)EAP_NAK;
509
0
    case AUTH_RULE_EAP_VENDOR:
510
0
    case AUTH_RULE_RSA_STRENGTH:
511
0
    case AUTH_RULE_ECDSA_STRENGTH:
512
0
      return (void*)0;
513
0
    case AUTH_RULE_CRL_VALIDATION:
514
0
    case AUTH_RULE_OCSP_VALIDATION:
515
0
      return (void*)VALIDATION_FAILED;
516
0
    case AUTH_RULE_IDENTITY_LOOSE:
517
0
    case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
518
0
      return (void*)FALSE;
519
0
    case AUTH_RULE_IDENTITY:
520
0
    case AUTH_RULE_CA_IDENTITY:
521
0
    case AUTH_RULE_EAP_IDENTITY:
522
0
    case AUTH_RULE_AAA_IDENTITY:
523
0
    case AUTH_RULE_XAUTH_BACKEND:
524
0
    case AUTH_RULE_XAUTH_IDENTITY:
525
0
    case AUTH_RULE_GROUP:
526
0
    case AUTH_RULE_CA_CERT:
527
0
    case AUTH_RULE_IM_CERT:
528
0
    case AUTH_RULE_SUBJECT_CERT:
529
0
    case AUTH_RULE_CERT_POLICY:
530
0
    case AUTH_RULE_SIGNATURE_SCHEME:
531
0
    case AUTH_RULE_IKE_SIGNATURE_SCHEME:
532
0
    case AUTH_HELPER_IM_CERT:
533
0
    case AUTH_HELPER_SUBJECT_CERT:
534
0
    case AUTH_HELPER_IM_HASH_URL:
535
0
    case AUTH_HELPER_SUBJECT_HASH_URL:
536
0
    case AUTH_HELPER_REVOCATION_CERT:
537
0
    case AUTH_HELPER_AC_CERT:
538
0
    case AUTH_RULE_MAX:
539
0
      break;
540
0
  }
541
0
  return NULL;
542
0
}
543
544
/**
545
 * Implementation of auth_cfg_t.add.
546
 */
547
static void add(private_auth_cfg_t *this, auth_rule_t type, ...)
548
0
{
549
0
  entry_t entry;
550
0
  va_list args;
551
552
0
  va_start(args, type);
553
0
  init_entry(&entry, type, args);
554
0
  va_end(args);
555
556
0
  if (is_multi_value_rule(type))
557
0
  { /* insert rules that may occur multiple times at the end */
558
0
    array_insert(this->entries, ARRAY_TAIL, &entry);
559
0
  }
560
0
  else
561
0
  { /* insert rules we expect only once at the front (get() will return
562
     * the latest value) */
563
0
    array_insert(this->entries, ARRAY_HEAD, &entry);
564
0
  }
565
0
}
566
567
/**
568
 * Create a constraint for RSA/PSS signatures
569
 */
570
static signature_params_t *create_rsa_pss_constraint(char *token)
571
0
{
572
0
  signature_params_t *params = NULL;
573
0
  hash_algorithm_t hash;
574
575
0
  if (enum_from_name(hash_algorithm_short_names, token, &hash))
576
0
  {
577
0
    rsa_pss_params_t pss = {
578
0
      .hash = hash,
579
0
      .mgf1_hash = hash,
580
0
      .salt_len = RSA_PSS_SALT_LEN_DEFAULT,
581
0
    };
582
0
    signature_params_t pss_params = {
583
0
      .scheme = SIGN_RSA_EMSA_PSS,
584
0
      .params = &pss,
585
0
    };
586
0
    rsa_pss_params_set_salt_len(&pss, 0);
587
0
    params = signature_params_clone(&pss_params);
588
0
  }
589
0
  return params;
590
0
}
591
592
METHOD(auth_cfg_t, add_pubkey_constraints, void,
593
  private_auth_cfg_t *this, char* constraints, bool ike)
594
0
{
595
0
  enumerator_t *enumerator;
596
0
  bool ike_added = FALSE, rsa_pss;
597
0
  key_type_t expected_type = -1;
598
0
  auth_rule_t expected_strength = AUTH_RULE_MAX;
599
0
  signature_params_t *params;
600
0
  int strength;
601
0
  char *token, *key_token = NULL;
602
0
  auth_rule_t type;
603
0
  void *value;
604
605
0
  rsa_pss = lib->settings->get_bool(lib->settings, "%s.rsa_pss", FALSE,
606
0
                    lib->ns);
607
608
0
  enumerator = enumerator_create_token(constraints, "-", "");
609
0
  while (enumerator->enumerate(enumerator, &token))
610
0
  {
611
0
    bool found = FALSE;
612
0
    int i;
613
0
    struct {
614
0
      char *name;
615
0
      signature_scheme_t scheme;
616
0
      key_type_t key;
617
0
    } schemes[] = {
618
0
      { "md5",    SIGN_RSA_EMSA_PKCS1_MD5,    KEY_RSA,   },
619
0
      { "sha1",   SIGN_RSA_EMSA_PKCS1_SHA1,   KEY_RSA,   },
620
0
      { "sha224",   SIGN_RSA_EMSA_PKCS1_SHA2_224, KEY_RSA,   },
621
0
      { "sha256",   SIGN_RSA_EMSA_PKCS1_SHA2_256, KEY_RSA,   },
622
0
      { "sha384",   SIGN_RSA_EMSA_PKCS1_SHA2_384, KEY_RSA,   },
623
0
      { "sha512",   SIGN_RSA_EMSA_PKCS1_SHA2_512, KEY_RSA,   },
624
0
      { "sha1",   SIGN_ECDSA_WITH_SHA1_DER,   KEY_ECDSA,   },
625
0
      { "sha256",   SIGN_ECDSA_WITH_SHA256_DER,   KEY_ECDSA,   },
626
0
      { "sha384",   SIGN_ECDSA_WITH_SHA384_DER,   KEY_ECDSA,   },
627
0
      { "sha512",   SIGN_ECDSA_WITH_SHA512_DER,   KEY_ECDSA,   },
628
0
      { "sha256",   SIGN_ECDSA_256,         KEY_ECDSA,   },
629
0
      { "sha384",   SIGN_ECDSA_384,         KEY_ECDSA,   },
630
0
      { "sha512",   SIGN_ECDSA_521,         KEY_ECDSA,   },
631
0
      { "identity", SIGN_ED25519,         KEY_ED25519, },
632
0
      { "identity", SIGN_ED448,           KEY_ED448,   },
633
0
    };
634
635
0
    if (expected_strength != AUTH_RULE_MAX)
636
0
    { /* expecting a key strength token */
637
0
      strength = atoi(token);
638
0
      if (strength)
639
0
      {
640
0
        add(this, expected_strength, (uintptr_t)strength);
641
0
      }
642
0
      expected_strength = AUTH_RULE_MAX;
643
0
      if (strength)
644
0
      {
645
0
        continue;
646
0
      }
647
0
    }
648
0
    if (streq(token, "rsa") || streq(token, "ike:rsa"))
649
0
    {
650
0
      key_token = token;
651
0
      expected_type = KEY_RSA;
652
0
      expected_strength = AUTH_RULE_RSA_STRENGTH;
653
0
      continue;
654
0
    }
655
0
    if (streq(token, "rsa/pss") || streq(token, "ike:rsa/pss"))
656
0
    {
657
0
      key_token = token;
658
0
      expected_type = KEY_RSA;
659
0
      expected_strength = AUTH_RULE_RSA_STRENGTH;
660
0
      continue;
661
0
    }
662
0
    if (streq(token, "ecdsa") || streq(token, "ike:ecdsa"))
663
0
    {
664
0
      key_token = token;
665
0
      expected_type = KEY_ECDSA;
666
0
      expected_strength = AUTH_RULE_ECDSA_STRENGTH;
667
0
      continue;
668
0
    }
669
0
    if (streq(token, "ed25519") || streq(token, "ike:ed25519"))
670
0
    {
671
0
      key_token = token;
672
0
      expected_type = KEY_ED25519;
673
0
      continue;
674
0
    }
675
0
    if (streq(token, "ed448") || streq(token, "ike:ed448"))
676
0
    {
677
0
      key_token = token;
678
0
      expected_type = KEY_ED448;
679
0
      continue;
680
0
    }
681
0
    if (streq(token, "pubkey") || streq(token, "ike:pubkey"))
682
0
    {
683
0
      key_token = token;
684
0
      expected_type = KEY_ANY;
685
0
      continue;
686
0
    }
687
0
    if (key_token && strpfx(key_token, "ike:") && !ike)
688
0
    {
689
0
      continue;
690
0
    }
691
692
0
    if (key_token && streq(key_token + strlen(key_token) - 3, "pss"))
693
0
    {
694
0
      params = create_rsa_pss_constraint(token);
695
0
      if (params)
696
0
      {
697
0
        if (strpfx(key_token, "ike:"))
698
0
        {
699
0
          add(this, AUTH_RULE_IKE_SIGNATURE_SCHEME, params);
700
0
          ike_added = TRUE;
701
0
        }
702
0
        else
703
0
        {
704
0
          add(this, AUTH_RULE_SIGNATURE_SCHEME, params);
705
0
        }
706
0
        found = TRUE;
707
0
      }
708
0
    }
709
0
    else
710
0
    {
711
0
      if (rsa_pss)
712
0
      {
713
0
        if (expected_type == KEY_ANY ||
714
0
          expected_type == KEY_RSA)
715
0
        {
716
0
          params = create_rsa_pss_constraint(token);
717
0
          if (params)
718
0
          {
719
0
            if (strpfx(key_token, "ike:"))
720
0
            {
721
0
              add(this, AUTH_RULE_IKE_SIGNATURE_SCHEME, params);
722
0
              ike_added = TRUE;
723
0
            }
724
0
            else
725
0
            {
726
0
              add(this, AUTH_RULE_SIGNATURE_SCHEME, params);
727
0
            }
728
0
            found = TRUE;
729
0
          }
730
0
        }
731
0
      }
732
0
      for (i = 0; i < countof(schemes); i++)
733
0
      {
734
0
        if (streq(schemes[i].name, token))
735
0
        {
736
0
          if (expected_type == KEY_ANY ||
737
0
            expected_type == schemes[i].key)
738
0
          {
739
0
            INIT(params,
740
0
              .scheme = schemes[i].scheme,
741
0
            );
742
0
            if (strpfx(key_token, "ike:"))
743
0
            {
744
0
              add(this, AUTH_RULE_IKE_SIGNATURE_SCHEME, params);
745
0
              ike_added = TRUE;
746
0
            }
747
0
            else
748
0
            {
749
0
              add(this, AUTH_RULE_SIGNATURE_SCHEME, params);
750
0
            }
751
0
          }
752
0
          found = TRUE;
753
0
        }
754
0
      }
755
0
    }
756
0
    if (!found)
757
0
    {
758
0
      DBG1(DBG_CFG, "ignoring invalid auth token: '%s'", token);
759
0
    }
760
0
  }
761
0
  enumerator->destroy(enumerator);
762
763
  /* if no explicit IKE signature constraints were added we add them for all
764
   * configured signature constraints */
765
0
  if (ike && !ike_added &&
766
0
    lib->settings->get_bool(lib->settings,
767
0
              "%s.signature_authentication_constraints", TRUE,
768
0
              lib->ns))
769
0
  {
770
0
    enumerator = create_enumerator(this);
771
0
    while (enumerator->enumerate(enumerator, &type, &value))
772
0
    {
773
0
      if (type == AUTH_RULE_SIGNATURE_SCHEME)
774
0
      {
775
0
        add(this, AUTH_RULE_IKE_SIGNATURE_SCHEME,
776
0
          signature_params_clone(value));
777
0
      }
778
0
    }
779
0
    enumerator->destroy(enumerator);
780
0
  }
781
0
}
782
783
/**
784
 * Check if signature schemes of a specific type are compliant
785
 */
786
static bool complies_scheme(private_auth_cfg_t *this, auth_cfg_t *constraints,
787
              auth_rule_t type, bool log_error)
788
0
{
789
0
  enumerator_t *e1, *e2;
790
0
  auth_rule_t t1, t2;
791
0
  signature_params_t *params, *constraint;
792
0
  bool success = TRUE;
793
794
0
  e2 = create_enumerator(this);
795
0
  while (e2->enumerate(e2, &t2, &params))
796
0
  {
797
0
    if (t2 == type)
798
0
    {
799
0
      success = FALSE;
800
0
      e1 = constraints->create_enumerator(constraints);
801
0
      while (e1->enumerate(e1, &t1, &constraint))
802
0
      {
803
0
        if (t1 == type &&
804
0
          signature_params_comply(constraint, params))
805
0
        {
806
0
          success = TRUE;
807
0
          break;
808
0
        }
809
0
      }
810
0
      e1->destroy(e1);
811
0
      if (!success)
812
0
      {
813
0
        if (log_error)
814
0
        {
815
0
          DBG1(DBG_CFG, "%s signature scheme %N not acceptable",
816
0
             AUTH_RULE_SIGNATURE_SCHEME == type ? "X.509" : "IKE",
817
0
             signature_scheme_names, params->scheme);
818
0
        }
819
0
        break;
820
0
      }
821
0
    }
822
0
  }
823
0
  e2->destroy(e2);
824
0
  return success;
825
0
}
826
827
METHOD(auth_cfg_t, complies, bool,
828
  private_auth_cfg_t *this, auth_cfg_t *constraints, bool log_error)
829
0
{
830
0
  enumerator_t *e1, *e2;
831
0
  bool success = TRUE, group_match = FALSE;
832
0
  bool ca_match = FALSE, cert_match = FALSE;
833
0
  identification_t *require_group = NULL, *require_ca = NULL;
834
0
  certificate_t *require_cert = NULL;
835
0
  signature_params_t *ike_scheme = NULL, *scheme = NULL;
836
0
  u_int strength = 0;
837
0
  auth_rule_t t1, t2;
838
0
  void *value;
839
840
0
  e1 = constraints->create_enumerator(constraints);
841
0
  while (e1->enumerate(e1, &t1, &value))
842
0
  {
843
0
    switch (t1)
844
0
    {
845
0
      case AUTH_RULE_CA_CERT:
846
0
      case AUTH_RULE_IM_CERT:
847
0
      {
848
0
        certificate_t *cert, *ca;
849
850
        /* for CA certs, a match of a single cert is sufficient */
851
0
        ca = (certificate_t*)value;
852
0
        require_ca = ca->get_subject(ca);
853
854
0
        e2 = create_enumerator(this);
855
0
        while (e2->enumerate(e2, &t2, &cert))
856
0
        {
857
0
          if ((t2 == AUTH_RULE_CA_CERT || t2 == AUTH_RULE_IM_CERT) &&
858
0
            cert->equals(cert, ca))
859
0
          {
860
0
            ca_match = TRUE;
861
0
          }
862
0
        }
863
0
        e2->destroy(e2);
864
0
        break;
865
0
      }
866
0
      case AUTH_RULE_CA_IDENTITY:
867
0
      {
868
0
        certificate_t *cert;
869
870
0
        require_ca = (identification_t*)value;
871
872
0
        e2 = create_enumerator(this);
873
0
        while (e2->enumerate(e2, &t2, &cert))
874
0
        {
875
0
          if ((t2 == AUTH_RULE_CA_CERT || t2 == AUTH_RULE_IM_CERT) &&
876
0
            cert->has_subject(cert, require_ca))
877
0
          {
878
0
            ca_match = TRUE;
879
0
          }
880
0
        }
881
0
        e2->destroy(e2);
882
0
        break;
883
0
      }
884
0
      case AUTH_RULE_SUBJECT_CERT:
885
0
      {
886
0
        certificate_t *cert;
887
888
        /* for certs, a match of a single cert is sufficient */
889
0
        require_cert = (certificate_t*)value;
890
891
0
        e2 = create_enumerator(this);
892
0
        while (e2->enumerate(e2, &t2, &cert))
893
0
        {
894
0
          if (t2 == AUTH_RULE_SUBJECT_CERT &&
895
0
            cert->equals(cert, require_cert))
896
0
          {
897
0
            cert_match = TRUE;
898
0
          }
899
0
        }
900
0
        e2->destroy(e2);
901
0
        break;
902
0
      }
903
0
      case AUTH_RULE_CRL_VALIDATION:
904
0
      case AUTH_RULE_OCSP_VALIDATION:
905
0
      {
906
0
        uintptr_t validated;
907
908
0
        if (get(this, AUTH_RULE_CERT_VALIDATION_SUSPENDED))
909
0
        { /* skip validation, may happen later */
910
0
          break;
911
0
        }
912
913
0
        e2 = create_enumerator(this);
914
0
        while (e2->enumerate(e2, &t2, &validated))
915
0
        {
916
0
          if (t2 == t1)
917
0
          {
918
0
            switch ((uintptr_t)value)
919
0
            {
920
0
              case VALIDATION_FAILED:
921
                /* no constraint */
922
0
                break;
923
0
              case VALIDATION_SKIPPED:
924
0
                if (validated == VALIDATION_SKIPPED)
925
0
                {
926
0
                  break;
927
0
                }
928
                /* FALL */
929
0
              case VALIDATION_GOOD:
930
0
                if (validated == VALIDATION_GOOD)
931
0
                {
932
0
                  break;
933
0
                }
934
                /* FALL */
935
0
              default:
936
0
                success = FALSE;
937
0
                if (log_error)
938
0
                {
939
0
                  DBG1(DBG_CFG, "constraint check failed: "
940
0
                     "%N is %N, but requires at least %N",
941
0
                     auth_rule_names, t1,
942
0
                     cert_validation_names, validated,
943
0
                     cert_validation_names, (uintptr_t)value);
944
0
                }
945
0
                break;
946
0
            }
947
0
          }
948
0
        }
949
0
        e2->destroy(e2);
950
0
        break;
951
0
      }
952
0
      case AUTH_RULE_IDENTITY:
953
0
      case AUTH_RULE_EAP_IDENTITY:
954
0
      case AUTH_RULE_AAA_IDENTITY:
955
0
      case AUTH_RULE_XAUTH_IDENTITY:
956
0
      {
957
0
        identification_t *id1, *id2;
958
959
0
        id1 = (identification_t*)value;
960
0
        id2 = get(this, t1);
961
0
        if (!id2 || !id2->matches(id2, id1))
962
0
        {
963
0
          if (t1 == AUTH_RULE_IDENTITY &&
964
0
            constraints->get(constraints, AUTH_RULE_IDENTITY_LOOSE))
965
0
          { /* also verify identity against subjectAltNames */
966
0
            certificate_t *cert;
967
968
0
            cert = get(this, AUTH_RULE_SUBJECT_CERT);
969
0
            if (cert && cert->has_subject(cert, id1))
970
0
            {
971
0
              break;
972
0
            }
973
0
            if (log_error)
974
0
            {
975
0
              DBG1(DBG_CFG, "constraint check failed: certificate"
976
0
                 " does not confirm identity '%Y' (%N)",
977
0
                 id1, id_type_names, id1->get_type(id1));
978
0
            }
979
0
            success = FALSE;
980
0
            break;
981
0
          }
982
0
          success = FALSE;
983
0
          if (!log_error)
984
0
          {
985
0
            break;
986
0
            }
987
0
          if (id2)
988
0
          {
989
0
            DBG1(DBG_CFG, "constraint check failed: %sidentity '%Y'"
990
0
               " (%N) required, not matched by '%Y' (%N)",
991
0
               t1 == AUTH_RULE_IDENTITY ? "" : "EAP ",
992
0
               id1, id_type_names, id1->get_type(id1),
993
0
               id2, id_type_names, id2->get_type(id2));
994
0
          }
995
0
          else
996
0
          {
997
0
            DBG1(DBG_CFG, "constraint check failed: %sidentity '%Y'"
998
0
               " (%N) required",
999
0
               t1 == AUTH_RULE_IDENTITY ? "" : "EAP ",
1000
0
               id1, id_type_names, id1->get_type(id1));
1001
0
          }
1002
0
        }
1003
0
        break;
1004
0
      }
1005
0
      case AUTH_RULE_AUTH_CLASS:
1006
0
      {
1007
0
        if ((uintptr_t)value != AUTH_CLASS_ANY &&
1008
0
          (uintptr_t)value != (uintptr_t)get(this, t1))
1009
0
        {
1010
0
          success = FALSE;
1011
0
          if (log_error)
1012
0
          {
1013
0
            DBG1(DBG_CFG, "constraint requires %N authentication, "
1014
0
               "but %N was used", auth_class_names, (uintptr_t)value,
1015
0
               auth_class_names, (uintptr_t)get(this, t1));
1016
0
          }
1017
0
        }
1018
0
        break;
1019
0
      }
1020
0
      case AUTH_RULE_EAP_TYPE:
1021
0
      {
1022
0
        if ((uintptr_t)value != (uintptr_t)get(this, t1) &&
1023
0
          (uintptr_t)value != EAP_DYNAMIC &&
1024
0
          (uintptr_t)value != EAP_RADIUS)
1025
0
        {
1026
0
          success = FALSE;
1027
0
          if (log_error)
1028
0
          {
1029
0
            DBG1(DBG_CFG, "constraint requires %N, "
1030
0
               "but %N was used", eap_type_names, (uintptr_t)value,
1031
0
               eap_type_names,  (uintptr_t)get(this, t1));
1032
0
          }
1033
0
        }
1034
0
        break;
1035
0
      }
1036
0
      case AUTH_RULE_EAP_VENDOR:
1037
0
      {
1038
0
        if ((uintptr_t)value != (uintptr_t)get(this, t1))
1039
0
        {
1040
0
          success = FALSE;
1041
0
          if (log_error)
1042
0
          {
1043
0
            DBG1(DBG_CFG, "constraint requires EAP vendor %d, "
1044
0
               "but %d was used", (uintptr_t)value,
1045
0
               (uintptr_t)get(this, t1));
1046
0
          }
1047
0
        }
1048
0
        break;
1049
0
      }
1050
0
      case AUTH_RULE_GROUP:
1051
0
      {
1052
0
        identification_t *group;
1053
1054
        /* for groups, a match of a single group is sufficient */
1055
0
        require_group = (identification_t*)value;
1056
0
        e2 = create_enumerator(this);
1057
0
        while (e2->enumerate(e2, &t2, &group))
1058
0
        {
1059
0
          if (t2 == AUTH_RULE_GROUP &&
1060
0
            group->matches(group, require_group))
1061
0
          {
1062
0
            group_match = TRUE;
1063
0
          }
1064
0
        }
1065
0
        e2->destroy(e2);
1066
0
        break;
1067
0
      }
1068
0
      case AUTH_RULE_RSA_STRENGTH:
1069
0
      case AUTH_RULE_ECDSA_STRENGTH:
1070
0
      {
1071
0
        strength = (uintptr_t)value;
1072
0
        break;
1073
0
      }
1074
0
      case AUTH_RULE_IKE_SIGNATURE_SCHEME:
1075
0
      {
1076
0
        ike_scheme = value;
1077
0
        break;
1078
0
      }
1079
0
      case AUTH_RULE_SIGNATURE_SCHEME:
1080
0
      {
1081
0
        scheme = value;
1082
0
        break;
1083
0
      }
1084
0
      case AUTH_RULE_CERT_POLICY:
1085
0
      {
1086
0
        char *oid1, *oid2;
1087
1088
0
        oid1 = (char*)value;
1089
0
        success = FALSE;
1090
0
        e2 = create_enumerator(this);
1091
0
        while (e2->enumerate(e2, &t2, &oid2))
1092
0
        {
1093
0
          if (t2 == t1 && streq(oid1, oid2))
1094
0
          {
1095
0
            success = TRUE;
1096
0
            break;
1097
0
          }
1098
0
        }
1099
0
        e2->destroy(e2);
1100
0
        if (!success && log_error)
1101
0
        {
1102
0
          DBG1(DBG_CFG, "constraint requires cert policy %s", oid1);
1103
0
        }
1104
0
        break;
1105
0
      }
1106
0
      case AUTH_RULE_IDENTITY_LOOSE:
1107
        /* just an indication when verifying AUTH_RULE_IDENTITY */
1108
0
      case AUTH_RULE_XAUTH_BACKEND:
1109
        /* not enforced, just a hint for local authentication */
1110
0
      case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
1111
        /* not a constraint */
1112
0
      case AUTH_HELPER_IM_CERT:
1113
0
      case AUTH_HELPER_SUBJECT_CERT:
1114
0
      case AUTH_HELPER_IM_HASH_URL:
1115
0
      case AUTH_HELPER_SUBJECT_HASH_URL:
1116
0
      case AUTH_HELPER_REVOCATION_CERT:
1117
0
      case AUTH_HELPER_AC_CERT:
1118
0
      case AUTH_RULE_MAX:
1119
        /* skip helpers */
1120
0
        continue;
1121
0
    }
1122
0
    if (!success)
1123
0
    {
1124
0
      break;
1125
0
    }
1126
0
  }
1127
0
  e1->destroy(e1);
1128
1129
  /* Check if we have a matching constraint (or none at all) for used
1130
   * signature schemes. */
1131
0
  if (success && scheme)
1132
0
  {
1133
0
    success = complies_scheme(this, constraints,
1134
0
                  AUTH_RULE_SIGNATURE_SCHEME, log_error);
1135
0
  }
1136
0
  if (success && ike_scheme)
1137
0
  {
1138
0
    success = complies_scheme(this, constraints,
1139
0
                  AUTH_RULE_IKE_SIGNATURE_SCHEME, log_error);
1140
0
  }
1141
1142
  /* Check if we have a matching constraint (or none at all) for used
1143
   * public key strength */
1144
0
  if (success && strength)
1145
0
  {
1146
0
    char *key_type DBG_UNUSED;
1147
1148
0
    e2 = create_enumerator(this);
1149
0
    while (e2->enumerate(e2, &t2, &strength))
1150
0
    {
1151
0
      switch (t2)
1152
0
      {
1153
0
        default:
1154
0
          continue;
1155
0
        case AUTH_RULE_RSA_STRENGTH:
1156
0
          key_type = "RSA";
1157
0
          break;
1158
0
        case AUTH_RULE_ECDSA_STRENGTH:
1159
0
          key_type = "ECDSA";
1160
0
          break;
1161
0
      }
1162
0
      success = FALSE;
1163
0
      e1 = constraints->create_enumerator(constraints);
1164
0
      while (e1->enumerate(e1, &t1, &value))
1165
0
      {
1166
0
        if (t1 == t2 && (uintptr_t)value <= strength)
1167
0
        {
1168
0
          success = TRUE;
1169
0
          break;
1170
0
        }
1171
0
      }
1172
0
      e1->destroy(e1);
1173
0
      if (!success)
1174
0
      {
1175
0
        if (log_error)
1176
0
        {
1177
0
          DBG1(DBG_CFG, "%s-%d signatures not acceptable",
1178
0
             key_type, strength);
1179
0
        }
1180
0
        break;
1181
0
      }
1182
0
    }
1183
0
    e2->destroy(e2);
1184
0
  }
1185
1186
0
  if (require_group && !group_match)
1187
0
  {
1188
0
    if (log_error)
1189
0
    {
1190
0
      DBG1(DBG_CFG, "constraint check failed: group membership to "
1191
0
         "'%Y' required", require_group);
1192
0
    }
1193
0
    return FALSE;
1194
0
  }
1195
0
  if (require_ca && !ca_match)
1196
0
  {
1197
0
    if (log_error)
1198
0
    {
1199
0
      DBG1(DBG_CFG, "constraint check failed: peer not "
1200
0
         "authenticated by CA '%Y'", require_ca);
1201
0
    }
1202
0
    return FALSE;
1203
0
  }
1204
0
  if (require_cert && !cert_match)
1205
0
  {
1206
0
    if (log_error)
1207
0
    {
1208
0
      DBG1(DBG_CFG, "constraint check failed: peer not "
1209
0
         "authenticated with peer cert '%Y'",
1210
0
         require_cert->get_subject(require_cert));
1211
0
    }
1212
0
    return FALSE;
1213
0
  }
1214
0
  return success;
1215
0
}
1216
1217
/**
1218
 * Implementation of auth_cfg_t.merge.
1219
 */
1220
static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy)
1221
0
{
1222
0
  if (!other)
1223
0
  { /* nothing to merge */
1224
0
    return;
1225
0
  }
1226
0
  if (copy)
1227
0
  {
1228
0
    enumerator_t *enumerator;
1229
0
    auth_rule_t type;
1230
0
    void *value;
1231
1232
    /* this enumerator skips duplicates for rules we expect only once */
1233
0
    enumerator = create_enumerator(other);
1234
0
    while (enumerator->enumerate(enumerator, &type, &value))
1235
0
    {
1236
0
      switch (type)
1237
0
      {
1238
0
        case AUTH_RULE_CA_CERT:
1239
0
        case AUTH_RULE_IM_CERT:
1240
0
        case AUTH_RULE_SUBJECT_CERT:
1241
0
        case AUTH_HELPER_IM_CERT:
1242
0
        case AUTH_HELPER_SUBJECT_CERT:
1243
0
        case AUTH_HELPER_REVOCATION_CERT:
1244
0
        case AUTH_HELPER_AC_CERT:
1245
0
        {
1246
0
          certificate_t *cert = (certificate_t*)value;
1247
1248
0
          add(this, type, cert->get_ref(cert));
1249
0
          break;
1250
0
        }
1251
0
        case AUTH_RULE_IDENTITY_LOOSE:
1252
0
        case AUTH_RULE_CRL_VALIDATION:
1253
0
        case AUTH_RULE_OCSP_VALIDATION:
1254
0
        case AUTH_RULE_AUTH_CLASS:
1255
0
        case AUTH_RULE_EAP_TYPE:
1256
0
        case AUTH_RULE_EAP_VENDOR:
1257
0
        case AUTH_RULE_RSA_STRENGTH:
1258
0
        case AUTH_RULE_ECDSA_STRENGTH:
1259
0
        case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
1260
0
        {
1261
0
          add(this, type, (uintptr_t)value);
1262
0
          break;
1263
0
        }
1264
0
        case AUTH_RULE_IDENTITY:
1265
0
        case AUTH_RULE_CA_IDENTITY:
1266
0
        case AUTH_RULE_EAP_IDENTITY:
1267
0
        case AUTH_RULE_AAA_IDENTITY:
1268
0
        case AUTH_RULE_GROUP:
1269
0
        case AUTH_RULE_XAUTH_IDENTITY:
1270
0
        {
1271
0
          identification_t *id = (identification_t*)value;
1272
1273
0
          add(this, type, id->clone(id));
1274
0
          break;
1275
0
        }
1276
0
        case AUTH_RULE_SIGNATURE_SCHEME:
1277
0
        case AUTH_RULE_IKE_SIGNATURE_SCHEME:
1278
0
        {
1279
0
          add(this, type, signature_params_clone(value));
1280
0
          break;
1281
0
        }
1282
0
        case AUTH_RULE_XAUTH_BACKEND:
1283
0
        case AUTH_RULE_CERT_POLICY:
1284
0
        case AUTH_HELPER_IM_HASH_URL:
1285
0
        case AUTH_HELPER_SUBJECT_HASH_URL:
1286
0
        {
1287
0
          add(this, type, strdup((char*)value));
1288
0
          break;
1289
0
        }
1290
0
        case AUTH_RULE_MAX:
1291
0
          break;
1292
0
      }
1293
0
    }
1294
0
    enumerator->destroy(enumerator);
1295
0
  }
1296
0
  else
1297
0
  {
1298
0
    entry_t entry;
1299
1300
0
    while (array_remove(other->entries, ARRAY_TAIL, &entry))
1301
0
    { /* keep order but prefer new values (esp. for single valued ones) */
1302
0
      array_insert(this->entries, ARRAY_HEAD, &entry);
1303
0
    }
1304
0
    array_compress(other->entries);
1305
0
  }
1306
0
}
1307
1308
/**
1309
 * Compare two auth_cfg_t objects for equality.
1310
 */
1311
static bool auth_cfg_equals(private_auth_cfg_t *this, private_auth_cfg_t *other)
1312
0
{
1313
0
  enumerator_t *e1, *e2;
1314
0
  entry_t *i1, *i2;
1315
0
  bool equal = TRUE, found;
1316
1317
  /* the rule count does not have to be equal for the two, as we only compare
1318
   * the first value found for some rules */
1319
0
  e1 = array_create_enumerator(this->entries);
1320
0
  while (e1->enumerate(e1, &i1))
1321
0
  {
1322
0
    found = FALSE;
1323
1324
0
    e2 = array_create_enumerator(other->entries);
1325
0
    while (e2->enumerate(e2, &i2))
1326
0
    {
1327
0
      if (entry_equals(i1, i2))
1328
0
      {
1329
0
        found = TRUE;
1330
0
        break;
1331
0
      }
1332
0
      else if (i1->type == i2->type && !is_multi_value_rule(i1->type))
1333
0
      { /* we continue our search, only for multi valued rules */
1334
0
        break;
1335
0
      }
1336
0
    }
1337
0
    e2->destroy(e2);
1338
0
    if (!found)
1339
0
    {
1340
0
      equal = FALSE;
1341
0
      break;
1342
0
    }
1343
0
  }
1344
0
  e1->destroy(e1);
1345
0
  return equal;
1346
0
}
1347
1348
/**
1349
 * Implementation of auth_cfg_t.equals.
1350
 */
1351
static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other)
1352
0
{
1353
0
  if (auth_cfg_equals(this, other))
1354
0
  {
1355
    /* as 'other' might contain entries that 'this' doesn't we also check
1356
     * the other way around */
1357
0
    return auth_cfg_equals(other, this);
1358
0
  }
1359
0
  return FALSE;
1360
0
}
1361
1362
METHOD(auth_cfg_t, purge, void,
1363
  private_auth_cfg_t *this, bool keep_ca)
1364
0
{
1365
0
  enumerator_t *enumerator;
1366
0
  entry_t *entry;
1367
1368
0
  enumerator = array_create_enumerator(this->entries);
1369
0
  while (enumerator->enumerate(enumerator, &entry))
1370
0
  {
1371
0
    if (!keep_ca || entry->type != AUTH_RULE_CA_CERT)
1372
0
    {
1373
0
      destroy_entry_value(entry);
1374
0
      array_remove_at(this->entries, enumerator);
1375
0
    }
1376
0
  }
1377
0
  enumerator->destroy(enumerator);
1378
1379
0
  array_compress(this->entries);
1380
0
}
1381
1382
METHOD(auth_cfg_t, clone_, auth_cfg_t*,
1383
  private_auth_cfg_t *this)
1384
0
{
1385
0
  enumerator_t *enumerator;
1386
0
  auth_cfg_t *clone;
1387
0
  auth_rule_t type;
1388
0
  void *value;
1389
1390
0
  clone = auth_cfg_create();
1391
  /* this enumerator skips duplicates for rules we expect only once */
1392
0
  enumerator = create_enumerator(this);
1393
0
  while (enumerator->enumerate(enumerator, &type, &value))
1394
0
  {
1395
0
    switch (type)
1396
0
    {
1397
0
      case AUTH_RULE_IDENTITY:
1398
0
      case AUTH_RULE_CA_IDENTITY:
1399
0
      case AUTH_RULE_EAP_IDENTITY:
1400
0
      case AUTH_RULE_AAA_IDENTITY:
1401
0
      case AUTH_RULE_GROUP:
1402
0
      case AUTH_RULE_XAUTH_IDENTITY:
1403
0
      {
1404
0
        identification_t *id = (identification_t*)value;
1405
0
        clone->add(clone, type, id->clone(id));
1406
0
        break;
1407
0
      }
1408
0
      case AUTH_RULE_CA_CERT:
1409
0
      case AUTH_RULE_IM_CERT:
1410
0
      case AUTH_RULE_SUBJECT_CERT:
1411
0
      case AUTH_HELPER_IM_CERT:
1412
0
      case AUTH_HELPER_SUBJECT_CERT:
1413
0
      case AUTH_HELPER_REVOCATION_CERT:
1414
0
      case AUTH_HELPER_AC_CERT:
1415
0
      {
1416
0
        certificate_t *cert = (certificate_t*)value;
1417
0
        clone->add(clone, type, cert->get_ref(cert));
1418
0
        break;
1419
0
      }
1420
0
      case AUTH_RULE_XAUTH_BACKEND:
1421
0
      case AUTH_RULE_CERT_POLICY:
1422
0
      case AUTH_HELPER_IM_HASH_URL:
1423
0
      case AUTH_HELPER_SUBJECT_HASH_URL:
1424
0
      {
1425
0
        clone->add(clone, type, strdup(value));
1426
0
        break;
1427
0
      }
1428
0
      case AUTH_RULE_IDENTITY_LOOSE:
1429
0
      case AUTH_RULE_AUTH_CLASS:
1430
0
      case AUTH_RULE_EAP_TYPE:
1431
0
      case AUTH_RULE_EAP_VENDOR:
1432
0
      case AUTH_RULE_CRL_VALIDATION:
1433
0
      case AUTH_RULE_OCSP_VALIDATION:
1434
0
      case AUTH_RULE_RSA_STRENGTH:
1435
0
      case AUTH_RULE_ECDSA_STRENGTH:
1436
0
      case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
1437
0
        clone->add(clone, type, (uintptr_t)value);
1438
0
        break;
1439
0
      case AUTH_RULE_SIGNATURE_SCHEME:
1440
0
      case AUTH_RULE_IKE_SIGNATURE_SCHEME:
1441
0
      {
1442
0
        clone->add(clone, type, signature_params_clone(value));
1443
0
        break;
1444
0
      }
1445
0
      case AUTH_RULE_MAX:
1446
0
        break;
1447
0
    }
1448
0
  }
1449
0
  enumerator->destroy(enumerator);
1450
0
  return clone;
1451
0
}
1452
1453
METHOD(auth_cfg_t, destroy, void,
1454
  private_auth_cfg_t *this)
1455
0
{
1456
0
  purge(this, FALSE);
1457
0
  array_destroy(this->entries);
1458
0
  free(this);
1459
0
}
1460
1461
/*
1462
 * see header file
1463
 */
1464
auth_cfg_t *auth_cfg_create()
1465
0
{
1466
0
  private_auth_cfg_t *this;
1467
1468
0
  INIT(this,
1469
0
    .public = {
1470
0
      .add = (void(*)(auth_cfg_t*, auth_rule_t type, ...))add,
1471
0
      .add_pubkey_constraints = _add_pubkey_constraints,
1472
0
      .get = _get,
1473
0
      .create_enumerator = _create_enumerator,
1474
0
      .replace = (void(*)(auth_cfg_t*,enumerator_t*,auth_rule_t,...))replace,
1475
0
      .complies = _complies,
1476
0
      .merge = (void(*)(auth_cfg_t*,auth_cfg_t*,bool))merge,
1477
0
      .purge = _purge,
1478
0
      .equals = (bool(*)(auth_cfg_t*,auth_cfg_t*))equals,
1479
0
      .clone = _clone_,
1480
0
      .destroy = _destroy,
1481
0
    },
1482
0
    .entries = array_create(sizeof(entry_t), 0),
1483
0
  );
1484
1485
0
  return &this->public;
1486
0
}