Coverage Report

Created: 2026-09-03 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/strongswan/src/libstrongswan/utils/identification.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2016 Andreas Steffen
3
 * Copyright (C) 2009-2025 Tobias Brunner
4
 * Copyright (C) 2005-2009 Martin Willi
5
 * Copyright (C) 2005 Jan Hutter
6
 *
7
 * Copyright (C) secunet Security Networks AG
8
 *
9
 * This program is free software; you can redistribute it and/or modify it
10
 * under the terms of the GNU General Public License as published by the
11
 * Free Software Foundation; either version 2 of the License, or (at your
12
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
13
 *
14
 * This program is distributed in the hope that it will be useful, but
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17
 * for more details.
18
 */
19
20
#include <string.h>
21
#include <stdio.h>
22
#include <errno.h>
23
24
#ifdef HAVE_REGEX
25
#include <regex.h>
26
#else
27
/* usually, POSIX regular expressions are supported. for the rare case they are
28
 * not, e.g. when cross-compiling for Windows, we define some stubs to simplify
29
 * the implementation below */
30
typedef void regex_t;
31
static int regexec(const regex_t *restrict preg, const char *restrict string,
32
           size_t nmatch, void *pmatch, int eflags)
33
{
34
  return -1;
35
}
36
37
static void regfree(regex_t *preg)
38
{
39
}
40
#endif /* HAVE_REGEX */
41
42
#include "identification.h"
43
44
#include <utils/utils.h>
45
#include <asn1/oid.h>
46
#include <asn1/asn1.h>
47
#include <crypto/hashers/hasher.h>
48
#include <collections/array.h>
49
50
ENUM_BEGIN(id_match_names, ID_MATCH_NONE, ID_MATCH_MAX_WILDCARDS,
51
  "MATCH_NONE",
52
  "MATCH_ANY",
53
  "MATCH_MAX_WILDCARDS");
54
ENUM_NEXT(id_match_names, ID_MATCH_PERFECT, ID_MATCH_PERFECT, ID_MATCH_MAX_WILDCARDS,
55
  "MATCH_PERFECT");
56
ENUM_END(id_match_names, ID_MATCH_PERFECT);
57
58
ENUM_BEGIN(id_type_names, ID_ANY, ID_KEY_ID,
59
  "ID_ANY",
60
  "ID_IPV4_ADDR",
61
  "ID_FQDN",
62
  "ID_RFC822_ADDR",
63
  "ID_IPV4_ADDR_SUBNET",
64
  "ID_IPV6_ADDR",
65
  "ID_IPV6_ADDR_SUBNET",
66
  "ID_IPV4_ADDR_RANGE",
67
  "ID_IPV6_ADDR_RANGE",
68
  "ID_DER_ASN1_DN",
69
  "ID_DER_ASN1_GN",
70
  "ID_KEY_ID");
71
ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_DER_ASN1_GN_URI, ID_KEY_ID,
72
  "ID_DER_ASN1_GN_URI");
73
ENUM_END(id_type_names, ID_DER_ASN1_GN_URI);
74
75
/**
76
 * coding of X.501 distinguished name
77
 */
78
typedef struct {
79
  const u_char *name;
80
  int oid;
81
  u_char type;
82
} x501rdn_t;
83
84
static const x501rdn_t x501rdns[] = {
85
  {"ND",          OID_NAME_DISTINGUISHER,   ASN1_PRINTABLESTRING},
86
  {"UID",         OID_PILOT_USERID,     ASN1_PRINTABLESTRING},
87
  {"DC",          OID_PILOT_DOMAIN_COMPONENT, ASN1_PRINTABLESTRING},
88
  {"CN",          OID_COMMON_NAME,      ASN1_PRINTABLESTRING},
89
  {"SN",          OID_SURNAME,        ASN1_PRINTABLESTRING},
90
  {"serialNumber",    OID_SERIAL_NUMBER,      ASN1_PRINTABLESTRING},
91
  {"C",           OID_COUNTRY,        ASN1_PRINTABLESTRING},
92
  {"L",           OID_LOCALITY,       ASN1_PRINTABLESTRING},
93
  {"ST",          OID_STATE_OR_PROVINCE,    ASN1_PRINTABLESTRING},
94
  {"STREET",        OID_STREET_ADDRESS,     ASN1_PRINTABLESTRING},
95
  {"O",           OID_ORGANIZATION,     ASN1_PRINTABLESTRING},
96
  {"OU",          OID_ORGANIZATION_UNIT,    ASN1_PRINTABLESTRING},
97
  {"organizationIdentifier",  OID_ORGANIZATION_ID,  ASN1_PRINTABLESTRING},
98
  {"T",           OID_TITLE,          ASN1_PRINTABLESTRING},
99
  {"D",           OID_DESCRIPTION,      ASN1_PRINTABLESTRING},
100
  {"postalAddress",   OID_POSTAL_ADDRESS,     ASN1_PRINTABLESTRING},
101
  {"postalCode",      OID_POSTAL_CODE,      ASN1_PRINTABLESTRING},
102
  {"N",           OID_NAME,         ASN1_PRINTABLESTRING},
103
  {"G",           OID_GIVEN_NAME,       ASN1_PRINTABLESTRING},
104
  {"I",           OID_INITIALS,       ASN1_PRINTABLESTRING},
105
  {"dnQualifier",     OID_DN_QUALIFIER,     ASN1_PRINTABLESTRING},
106
  {"dmdName",       OID_DMD_NAME,       ASN1_PRINTABLESTRING},
107
  {"pseudonym",       OID_PSEUDONYM,        ASN1_PRINTABLESTRING},
108
  {"ID",          OID_UNIQUE_IDENTIFIER,    ASN1_PRINTABLESTRING},
109
  {"EN",          OID_EMPLOYEE_NUMBER,    ASN1_PRINTABLESTRING},
110
  {"employeeNumber",    OID_EMPLOYEE_NUMBER,    ASN1_PRINTABLESTRING},
111
  {"E",         OID_EMAIL_ADDRESS,      ASN1_IA5STRING},
112
  {"Email",         OID_EMAIL_ADDRESS,      ASN1_IA5STRING},
113
  {"emailAddress",    OID_EMAIL_ADDRESS,      ASN1_IA5STRING},
114
  {"UN",          OID_UNSTRUCTURED_NAME,    ASN1_IA5STRING},
115
  {"unstructuredName",  OID_UNSTRUCTURED_NAME,    ASN1_IA5STRING},
116
  {"UA",          OID_UNSTRUCTURED_ADDRESS, ASN1_PRINTABLESTRING},
117
  {"unstructuredAddress", OID_UNSTRUCTURED_ADDRESS, ASN1_PRINTABLESTRING},
118
  {"TCGID",         OID_TCGID,          ASN1_PRINTABLESTRING},
119
};
120
121
/**
122
 * maximum number of RDNs in atodn()
123
 */
124
5.95k
#define RDN_MAX     20
125
126
typedef struct private_identification_t private_identification_t;
127
128
/**
129
 * Private data of an identification_t object.
130
 */
131
struct private_identification_t {
132
  /**
133
   * Public interface.
134
   */
135
  identification_t public;
136
137
  /**
138
   * Encoded representation of this ID.
139
   */
140
  chunk_t encoded;
141
142
  /**
143
   * Type of this ID.
144
   */
145
  id_type_t type;
146
147
  /**
148
   * Pointer if we use regex comparison.
149
   */
150
  regex_t *regex;
151
};
152
153
/**
154
 * Check that neither object uses a regex.
155
 */
156
static inline bool neither_is_regex(private_identification_t *this,
157
                  identification_t *other)
158
12.6k
{
159
12.6k
  private_identification_t *other_priv = (private_identification_t*)other;
160
12.6k
  return !this->regex && !other_priv->regex;
161
12.6k
}
162
163
/**
164
 * Enumerator over RDNs
165
 */
166
typedef struct {
167
  /* implements enumerator interface */
168
  enumerator_t public;
169
  /* next set to parse, if any */
170
  chunk_t sets;
171
  /* next sequence in set, if any */
172
  chunk_t seqs;
173
} rdn_enumerator_t;
174
175
METHOD(enumerator_t, rdn_enumerate, bool,
176
  rdn_enumerator_t *this, va_list args)
177
43.8k
{
178
43.8k
  chunk_t rdn, *oid, *data;
179
43.8k
  u_char *type;
180
181
43.8k
  VA_ARGS_VGET(args, oid, type, data);
182
183
  /* a DN contains one or more SET, each containing one or more SEQUENCES,
184
   * each containing a OID/value RDN */
185
43.8k
  if (!this->seqs.len)
186
37.9k
  {
187
    /* no SEQUENCEs in current SET, parse next SET */
188
37.9k
    if (asn1_unwrap(&this->sets, &this->seqs) != ASN1_SET)
189
2.89k
    {
190
2.89k
      return FALSE;
191
2.89k
    }
192
37.9k
  }
193
40.9k
  if (asn1_unwrap(&this->seqs, &rdn) == ASN1_SEQUENCE &&
194
40.3k
    asn1_unwrap(&rdn, oid) == ASN1_OID)
195
40.1k
  {
196
40.1k
    int t = asn1_unwrap(&rdn, data);
197
198
40.1k
    if (t != ASN1_INVALID)
199
39.9k
    {
200
39.9k
      *type = t;
201
39.9k
      return TRUE;
202
39.9k
    }
203
40.1k
  }
204
989
  return FALSE;
205
40.9k
}
206
207
/**
208
 * Create an enumerator over all RDNs (oid, string type, data) of a DN
209
 */
210
static enumerator_t *create_rdn_enumerator(chunk_t dn)
211
23.7k
{
212
23.7k
  rdn_enumerator_t *e;
213
214
23.7k
  INIT(e,
215
23.7k
    .public = {
216
23.7k
      .enumerate = enumerator_enumerate_default,
217
23.7k
      .venumerate = _rdn_enumerate,
218
23.7k
      .destroy = (void*)free,
219
23.7k
    },
220
23.7k
  );
221
222
  /* a DN is a SEQUENCE, get the first SET of it */
223
23.7k
  if (asn1_unwrap(&dn, &e->sets) == ASN1_SEQUENCE)
224
15.7k
  {
225
15.7k
    e->seqs = chunk_empty;
226
15.7k
    return &e->public;
227
15.7k
  }
228
7.95k
  free(e);
229
7.95k
  return enumerator_create_empty();
230
23.7k
}
231
232
/**
233
 * Part enumerator over RDNs
234
 */
235
typedef struct {
236
  /* implements enumerator interface */
237
  enumerator_t public;
238
  /* inner RDN enumerator */
239
  enumerator_t *inner;
240
} rdn_part_enumerator_t;
241
242
METHOD(enumerator_t, rdn_part_enumerate, bool,
243
  rdn_part_enumerator_t *this, va_list args)
244
8.70k
{
245
8.70k
  int i, known_oid, strtype;
246
8.70k
  chunk_t oid, inner_data, *data;
247
8.70k
  id_part_t *type;
248
8.70k
  static const struct {
249
8.70k
    int oid;
250
8.70k
    id_part_t type;
251
8.70k
  } oid2part[] = {
252
8.70k
    {OID_COMMON_NAME,   ID_PART_RDN_CN},
253
8.70k
    {OID_SURNAME,     ID_PART_RDN_SN},
254
8.70k
    {OID_SERIAL_NUMBER,   ID_PART_RDN_SERIAL_NUMBER},
255
8.70k
    {OID_COUNTRY,     ID_PART_RDN_C},
256
8.70k
    {OID_LOCALITY,     ID_PART_RDN_L},
257
8.70k
    {OID_STATE_OR_PROVINCE, ID_PART_RDN_ST},
258
8.70k
    {OID_ORGANIZATION,   ID_PART_RDN_O},
259
8.70k
    {OID_ORGANIZATION_UNIT, ID_PART_RDN_OU},
260
8.70k
    {OID_TITLE,       ID_PART_RDN_T},
261
8.70k
    {OID_DESCRIPTION,   ID_PART_RDN_D},
262
8.70k
    {OID_NAME,       ID_PART_RDN_N},
263
8.70k
    {OID_GIVEN_NAME,   ID_PART_RDN_G},
264
8.70k
    {OID_INITIALS,     ID_PART_RDN_I},
265
8.70k
    {OID_DN_QUALIFIER,   ID_PART_RDN_DNQ},
266
8.70k
    {OID_DMD_NAME,     ID_PART_RDN_DMDN},
267
8.70k
    {OID_PSEUDONYM,     ID_PART_RDN_PN},
268
8.70k
    {OID_UNIQUE_IDENTIFIER, ID_PART_RDN_ID},
269
8.70k
    {OID_EMAIL_ADDRESS,   ID_PART_RDN_E},
270
8.70k
    {OID_EMPLOYEE_NUMBER, ID_PART_RDN_EN},
271
8.70k
  };
272
273
8.70k
  VA_ARGS_VGET(args, type, data);
274
275
12.4k
  while (this->inner->enumerate(this->inner, &oid, &strtype, &inner_data))
276
11.1k
  {
277
11.1k
    known_oid = asn1_known_oid(oid);
278
195k
    for (i = 0; i < countof(oid2part); i++)
279
191k
    {
280
191k
      if (oid2part[i].oid == known_oid)
281
7.49k
      {
282
7.49k
        *type = oid2part[i].type;
283
7.49k
        *data = inner_data;
284
7.49k
        return TRUE;
285
7.49k
      }
286
191k
    }
287
11.1k
  }
288
1.21k
  return FALSE;
289
8.70k
}
290
291
METHOD(enumerator_t, rdn_part_enumerator_destroy, void,
292
  rdn_part_enumerator_t *this)
293
1.26k
{
294
1.26k
  this->inner->destroy(this->inner);
295
1.26k
  free(this);
296
1.26k
}
297
298
METHOD(identification_t, create_part_enumerator, enumerator_t*,
299
  private_identification_t *this)
300
2.90k
{
301
2.90k
  switch (this->type)
302
2.90k
  {
303
1.26k
    case ID_DER_ASN1_DN:
304
1.26k
    {
305
1.26k
      rdn_part_enumerator_t *e;
306
307
1.26k
      INIT(e,
308
1.26k
        .inner = create_rdn_enumerator(this->encoded),
309
1.26k
        .public = {
310
1.26k
          .enumerate = enumerator_enumerate_default,
311
1.26k
          .venumerate = _rdn_part_enumerate,
312
1.26k
          .destroy = _rdn_part_enumerator_destroy,
313
1.26k
        },
314
1.26k
      );
315
1.26k
      return &e->public;
316
0
    }
317
61
    case ID_RFC822_ADDR:
318
      /* TODO */
319
564
    case ID_FQDN:
320
      /* TODO */
321
1.64k
    default:
322
1.64k
      return enumerator_create_empty();
323
2.90k
  }
324
2.90k
}
325
326
/**
327
 * Print a separator between two RDNs
328
 */
329
static inline bool print_separator(char **buf, size_t *len)
330
6.12k
{
331
6.12k
  int written;
332
333
6.12k
  written = snprintf(*buf, *len, ", ");
334
6.12k
  if (written < 0 || written >= *len)
335
30
  {
336
30
    return FALSE;
337
30
  }
338
6.09k
  *buf += written;
339
6.09k
  *len -= written;
340
6.09k
  return TRUE;
341
6.12k
}
342
343
/**
344
 * Print a DN with all its RDN in a buffer to present it to the user
345
 */
346
static void dntoa(chunk_t dn, char *buf, size_t len)
347
1.27k
{
348
1.27k
  enumerator_t *e;
349
1.27k
  chunk_t oid_data, data, printable;
350
1.27k
  u_char type;
351
1.27k
  int oid, written;
352
1.27k
  bool finished = FALSE, empty = TRUE;
353
354
1.27k
  e = create_rdn_enumerator(dn);
355
7.72k
  while (e->enumerate(e, &oid_data, &type, &data))
356
7.30k
  {
357
7.30k
    empty = FALSE;
358
359
    /* previous RDN was empty but it wasn't the last one */
360
7.30k
    if (finished && !print_separator(&buf, &len))
361
8
    {
362
8
      break;
363
8
    }
364
7.29k
    finished = FALSE;
365
366
7.29k
    oid = asn1_known_oid(oid_data);
367
7.29k
    if (oid == OID_UNKNOWN)
368
2.58k
    {
369
2.58k
      written = snprintf(buf, len, "%#B=", &oid_data);
370
2.58k
    }
371
4.70k
    else
372
4.70k
    {
373
4.70k
      written = snprintf(buf, len,"%s=", oid_names[oid].name);
374
4.70k
    }
375
7.29k
    if (written < 0 || written >= len)
376
50
    {
377
50
      break;
378
50
    }
379
7.24k
    buf += written;
380
7.24k
    len -= written;
381
382
7.24k
    written = 0;
383
7.24k
    chunk_printable(data, &printable, '?');
384
7.24k
    if (printable.ptr)
385
3.95k
    {
386
3.95k
      written = snprintf(buf, len, "%.*s", (int)printable.len,
387
3.95k
                 printable.ptr);
388
3.95k
    }
389
7.24k
    chunk_free(&printable);
390
7.24k
    if (written < 0 || written >= len)
391
422
    {
392
422
      break;
393
422
    }
394
6.82k
    buf += written;
395
6.82k
    len -= written;
396
397
6.82k
    if (!data.ptr)
398
3.08k
    { /* we can't calculate if we're finished, assume we are */
399
3.08k
      finished = TRUE;
400
3.08k
    }
401
3.73k
    else if (data.ptr + data.len == dn.ptr + dn.len)
402
350
    {
403
350
      finished = TRUE;
404
350
      break;
405
350
    }
406
3.38k
    else if (!print_separator(&buf, &len))
407
22
    {
408
22
      break;
409
22
    }
410
6.82k
  }
411
1.27k
  if (empty)
412
52
  {
413
52
    snprintf(buf, len, "");
414
52
  }
415
1.22k
  else if (!finished)
416
522
  {
417
522
    snprintf(buf, len, "(invalid ID_DER_ASN1_DN)");
418
522
  }
419
1.27k
  e->destroy(e);
420
1.27k
}
421
422
/**
423
 * Converts an LDAP-style human-readable ASCII-encoded
424
 * ASN.1 distinguished name into binary DER-encoded format
425
 */
426
static status_t atodn(char *src, chunk_t *dn)
427
779
{
428
  /* finite state machine for atodn */
429
779
  typedef enum {
430
779
    SEARCH_OID =  0,
431
779
    READ_OID =    1,
432
779
    SEARCH_NAME = 2,
433
779
    READ_NAME =   3,
434
779
    UNKNOWN_OID = 4
435
779
  } state_t;
436
437
779
  chunk_t oid  = chunk_empty;
438
779
  chunk_t name = chunk_empty;
439
779
  chunk_t rdns[RDN_MAX];
440
779
  int rdn_count = 0;
441
779
  int dn_len = 0;
442
779
  int whitespace = 0;
443
779
  int i = 0;
444
779
  asn1_t rdn_type;
445
779
  state_t state = SEARCH_OID;
446
779
  status_t status = SUCCESS;
447
779
  char sep = '\0';
448
449
779
  do
450
46.5M
  {
451
46.5M
    switch (state)
452
46.5M
    {
453
6.80k
      case SEARCH_OID:
454
6.80k
        if (!sep && *src == '/')
455
20
        { /* use / as separator if the string starts with a slash */
456
20
          sep = '/';
457
20
          break;
458
20
        }
459
6.78k
        if (*src != ' ' && *src != '\0')
460
6.15k
        {
461
6.15k
          if (!sep)
462
759
          { /* use , as separator by default */
463
759
            sep = ',';
464
759
          }
465
6.15k
          oid.ptr = src;
466
6.15k
          oid.len = 1;
467
6.15k
          state = READ_OID;
468
6.15k
        }
469
6.78k
        break;
470
4.40M
      case READ_OID:
471
4.40M
        if (*src != ' ' && *src != '=')
472
4.40M
        {
473
4.40M
          oid.len++;
474
4.40M
        }
475
6.10k
        else
476
6.10k
        {
477
6.10k
          bool found = FALSE;
478
479
135k
          for (i = 0; i < countof(x501rdns); i++)
480
134k
          {
481
134k
            if (strlen(x501rdns[i].name) == oid.len &&
482
40.0k
              strncasecmp(x501rdns[i].name, oid.ptr, oid.len) == 0)
483
5.95k
            {
484
5.95k
              found = TRUE;
485
5.95k
              break;
486
5.95k
            }
487
134k
          }
488
6.10k
          if (!found)
489
154
          {
490
154
            status = NOT_SUPPORTED;
491
154
            state = UNKNOWN_OID;
492
154
            break;
493
154
          }
494
          /* reset oid and change state */
495
5.95k
          oid = chunk_empty;
496
5.95k
          state = SEARCH_NAME;
497
5.95k
        }
498
4.40M
        break;
499
4.40M
      case SEARCH_NAME:
500
6.92k
        if (*src == ' ' || *src == '=')
501
968
        {
502
968
          break;
503
968
        }
504
5.95k
        else if (*src != sep && *src != '\0')
505
3.13k
        {
506
3.13k
          name.ptr = src;
507
3.13k
          name.len = 1;
508
3.13k
          whitespace = 0;
509
3.13k
          state = READ_NAME;
510
3.13k
          break;
511
3.13k
        }
512
2.81k
        name = chunk_empty;
513
2.81k
        whitespace = 0;
514
2.81k
        state = READ_NAME;
515
        /* fall-through */
516
39.6M
      case READ_NAME:
517
39.6M
        if (*src != sep && *src != '\0')
518
39.6M
        {
519
39.6M
          name.len++;
520
39.6M
          if (*src == ' ')
521
3.40M
            whitespace++;
522
36.2M
          else
523
36.2M
            whitespace = 0;
524
39.6M
        }
525
5.95k
        else
526
5.95k
        {
527
5.95k
          name.len -= whitespace;
528
5.95k
          rdn_type = (x501rdns[i].type == ASN1_PRINTABLESTRING
529
2.82k
                && !asn1_is_printablestring(name))
530
5.95k
                ? ASN1_UTF8STRING : x501rdns[i].type;
531
532
5.95k
          if (rdn_count < RDN_MAX)
533
4.56k
          {
534
4.56k
            chunk_t rdn_oid;
535
536
4.56k
            rdn_oid = asn1_build_known_oid(x501rdns[i].oid);
537
4.56k
            if (rdn_oid.len)
538
4.56k
            {
539
4.56k
              rdns[rdn_count] =
540
4.56k
                  asn1_wrap(ASN1_SET, "m",
541
4.56k
                    asn1_wrap(ASN1_SEQUENCE, "mm",
542
4.56k
                      rdn_oid,
543
4.56k
                      asn1_wrap(rdn_type, "c", name)
544
4.56k
                    )
545
4.56k
                  );
546
4.56k
              dn_len += rdns[rdn_count++].len;
547
4.56k
            }
548
0
            else
549
0
            {
550
0
              status = INVALID_ARG;
551
0
            }
552
4.56k
          }
553
1.38k
          else
554
1.38k
          {
555
1.38k
            status = OUT_OF_RES;
556
1.38k
          }
557
          /* reset name and change state */
558
5.95k
          name = chunk_empty;
559
5.95k
          state = SEARCH_OID;
560
5.95k
        }
561
39.6M
        break;
562
2.42M
      case UNKNOWN_OID:
563
2.42M
        break;
564
46.5M
    }
565
46.5M
  } while (*src++ != '\0');
566
567
779
  if (state == READ_OID)
568
51
  { /* unterminated OID */
569
51
    status = INVALID_ARG;
570
51
  }
571
572
  /* build the distinguished name sequence */
573
779
  {
574
779
    int i;
575
779
    u_char *pos = asn1_build_object(dn, ASN1_SEQUENCE, dn_len);
576
577
5.34k
    for (i = 0; i < rdn_count; i++)
578
4.56k
    {
579
4.56k
      memcpy(pos, rdns[i].ptr, rdns[i].len);
580
4.56k
      pos += rdns[i].len;
581
4.56k
      free(rdns[i].ptr);
582
4.56k
    }
583
779
  }
584
779
  if (status != SUCCESS)
585
232
  {
586
232
    free(dn->ptr);
587
232
    *dn = chunk_empty;
588
232
  }
589
779
  return status;
590
779
}
591
592
METHOD(identification_t, get_encoding, chunk_t,
593
  private_identification_t *this)
594
53.3k
{
595
53.3k
  return this->encoded;
596
53.3k
}
597
598
METHOD(identification_t, get_type, id_type_t,
599
  private_identification_t *this)
600
79.9k
{
601
79.9k
  return this->type;
602
79.9k
}
603
604
/**
605
 * Check if this is a wildcard value
606
 */
607
static inline bool is_wildcard(chunk_t data)
608
3.97k
{
609
3.97k
  return data.len == 1 && data.ptr[0] == '*';
610
3.97k
}
611
612
METHOD(identification_t, contains_wildcards_dn, bool,
613
  private_identification_t *this)
614
630
{
615
630
  enumerator_t *enumerator;
616
630
  bool contains = FALSE;
617
630
  id_part_t type;
618
630
  chunk_t data;
619
620
630
  enumerator = create_part_enumerator(this);
621
4.26k
  while (enumerator->enumerate(enumerator, &type, &data))
622
3.67k
  {
623
3.67k
    if (is_wildcard(data))
624
44
    {
625
44
      contains = TRUE;
626
44
      break;
627
44
    }
628
3.67k
  }
629
630
  enumerator->destroy(enumerator);
630
630
  return contains;
631
630
}
632
633
METHOD(identification_t, contains_wildcards_memchr, bool,
634
  private_identification_t *this)
635
564
{
636
564
  return memchr(this->encoded.ptr, '*', this->encoded.len) != NULL;
637
564
}
638
639
METHOD(identification_t, hash_binary, u_int,
640
  private_identification_t *this, u_int inc)
641
1.64k
{
642
1.64k
  u_int hash;
643
644
1.64k
  hash = chunk_hash_inc(chunk_from_thing(this->type), inc);
645
1.64k
  if (this->type != ID_ANY)
646
1.61k
  {
647
1.61k
    hash = chunk_hash_inc(this->encoded, hash);
648
1.61k
  }
649
1.64k
  if (this->regex)
650
0
  { /* ensure regexes have different hashes even if type/encoding is equal */
651
0
    hash = chunk_hash_inc(chunk_from_chars(0x01), hash);
652
0
  }
653
1.64k
  return hash;
654
1.64k
}
655
656
METHOD(identification_t, equals_binary, bool,
657
  private_identification_t *this, identification_t *other)
658
1.08k
{
659
1.08k
  private_identification_t *other_priv = (private_identification_t*)other;
660
661
1.08k
  if (this->type == other_priv->type &&
662
1.08k
     (neither_is_regex(this, other) || (this->regex && other_priv->regex)))
663
1.08k
  {
664
1.08k
    if (this->type == ID_ANY)
665
33
    {
666
33
      return TRUE;
667
33
    }
668
1.04k
    return chunk_equals(this->encoded, other_priv->encoded);
669
1.08k
  }
670
0
  return FALSE;
671
1.08k
}
672
673
/**
674
 * Compare two RDNs for equality, comparing some string types case insensitive
675
 */
676
static bool rdn_equals(chunk_t oid, u_char a_type, chunk_t a, u_char b_type,
677
             chunk_t b)
678
2.49k
{
679
2.49k
  if (a_type == b_type &&
680
2.08k
    (a_type == ASN1_PRINTABLESTRING ||
681
459
     (a_type == ASN1_IA5STRING &&
682
44
      asn1_known_oid(oid) == OID_EMAIL_ADDRESS)))
683
1.64k
  { /* ignore case for printableStrings and email RDNs */
684
1.64k
    return strncaseeq(a.ptr, b.ptr, a.len);
685
1.64k
  }
686
849
  else
687
849
  { /* respect case and length for everything else */
688
849
    return memeq(a.ptr, b.ptr, a.len);
689
849
  }
690
2.49k
}
691
692
/**
693
 * RDNs when matching DNs
694
 */
695
typedef struct {
696
  chunk_t oid;
697
  u_char type;
698
  chunk_t data;
699
  bool matched;
700
} rdn_t;
701
702
/**
703
 * Match DNs (o_dn may contain wildcards and RDNs in a different order, if
704
 * allow_unmatched is TRUE, t_dn may contain unmatched RDNs)
705
 */
706
static bool match_dn(chunk_t t_dn, chunk_t o_dn, int *wc, bool allow_unmatched)
707
0
{
708
0
  enumerator_t *enumerator;
709
0
  array_t *rdns;
710
0
  rdn_t *rdn, *found;
711
0
  chunk_t oid, data;
712
0
  u_char type;
713
0
  bool finished = FALSE;
714
0
  int i, regular = 0;
715
716
0
  *wc = 0;
717
718
  /* try a binary compare */
719
0
  if (chunk_equals(t_dn, o_dn))
720
0
  {
721
0
    return TRUE;
722
0
  }
723
724
0
  rdns = array_create(0, 8);
725
726
0
  enumerator = create_rdn_enumerator(o_dn);
727
0
  while (TRUE)
728
0
  {
729
0
    if (!enumerator->enumerate(enumerator, &oid, &type, &data))
730
0
    {
731
0
      break;
732
0
    }
733
0
    INIT(rdn,
734
0
      .oid = oid,
735
0
      .type = type,
736
0
      .data = data,
737
0
    );
738
0
    if (is_wildcard(data))
739
0
    {
740
      /* insert wildcards at the end, to perform exact matches first */
741
0
      array_insert(rdns, ARRAY_TAIL, rdn);
742
0
    }
743
0
    else
744
0
    {
745
0
      array_insert(rdns, regular++, rdn);
746
0
    }
747
    /* the enumerator returns FALSE on parse error, we are finished
748
     * if we have reached the end of the DN only */
749
0
    if ((data.ptr + data.len == o_dn.ptr + o_dn.len))
750
0
    {
751
0
      finished = TRUE;
752
0
    }
753
0
  }
754
0
  enumerator->destroy(enumerator);
755
756
0
  if (!finished)
757
0
  { /* invalid DN */
758
0
    array_destroy_function(rdns, (void*)free, NULL);
759
0
    return FALSE;
760
0
  }
761
0
  finished = FALSE;
762
763
0
  enumerator = create_rdn_enumerator(t_dn);
764
0
  while (TRUE)
765
0
  {
766
0
    if (!enumerator->enumerate(enumerator, &oid, &type, &data))
767
0
    {
768
0
      break;
769
0
    }
770
0
    for (i = 0, found = NULL; i < array_count(rdns); i++)
771
0
    {
772
0
      array_get(rdns, i, &rdn);
773
0
      if (!rdn->matched && chunk_equals(rdn->oid, oid))
774
0
      {
775
0
        if (is_wildcard(rdn->data))
776
0
        {
777
0
          (*wc)++;
778
0
        }
779
0
        else if (data.len != rdn->data.len ||
780
0
             !rdn_equals(oid, type, data, rdn->type, rdn->data))
781
0
        {
782
0
          continue;
783
0
        }
784
0
        rdn->matched = TRUE;
785
0
        found = rdn;
786
0
        break;
787
0
      }
788
0
    }
789
0
    if (!found)
790
0
    {
791
      /* treat unmatched RDNs like wildcards if allowed */
792
0
      if (!allow_unmatched)
793
0
      {
794
0
        break;
795
0
      }
796
0
      (*wc)++;
797
0
    }
798
    /* the enumerator returns FALSE on parse error, we are finished
799
     * if we have reached the end of the DN only */
800
0
    if ((data.ptr + data.len == t_dn.ptr + t_dn.len))
801
0
    {
802
0
      finished = TRUE;
803
0
    }
804
0
  }
805
0
  enumerator->destroy(enumerator);
806
807
0
  if (finished)
808
0
  {
809
0
    for (i = 0; i < array_count(rdns); i++)
810
0
    {
811
0
      array_get(rdns, i, &rdn);
812
0
      if (!rdn->matched)
813
0
      {
814
0
        finished = FALSE;
815
0
      }
816
0
    }
817
0
  }
818
0
  array_destroy_function(rdns, (void*)free, NULL);
819
0
  return finished;
820
0
}
821
822
/**
823
 * Reordered RDNs are fine, but match all
824
 */
825
static bool match_dn_reordered(chunk_t t_dn, chunk_t o_dn, int *wc)
826
0
{
827
0
  return match_dn(t_dn, o_dn, wc, FALSE);
828
0
}
829
830
/**
831
 * t_dn may contain more RDNs than o_dn
832
 */
833
static bool match_dn_relaxed(chunk_t t_dn, chunk_t o_dn, int *wc)
834
0
{
835
0
  return match_dn(t_dn, o_dn, wc, TRUE);
836
0
}
837
838
/**
839
 * Compare two DNs, for equality if wc == NULL, with wildcard matching otherwise
840
 */
841
static bool compare_dn(chunk_t t_dn, chunk_t o_dn, int *wc)
842
11.8k
{
843
11.8k
  enumerator_t *t, *o;
844
11.8k
  chunk_t t_oid, o_oid, t_data, o_data;
845
11.8k
  u_char t_type, o_type;
846
11.8k
  bool t_next, o_next, finished = FALSE;
847
848
11.8k
  if (wc)
849
8.86k
  {
850
8.86k
    *wc = 0;
851
8.86k
  }
852
2.98k
  else if (t_dn.len != o_dn.len)
853
256
  {
854
256
    return FALSE;
855
256
  }
856
857
11.5k
  if (chunk_equals(t_dn, o_dn))
858
1.44k
  {
859
1.44k
    return TRUE;
860
1.44k
  }
861
862
10.1k
  t = create_rdn_enumerator(t_dn);
863
10.1k
  o = create_rdn_enumerator(o_dn);
864
10.1k
  while (TRUE)
865
11.6k
  {
866
11.6k
    t_next = t->enumerate(t, &t_oid, &t_type, &t_data);
867
11.6k
    o_next = o->enumerate(o, &o_oid, &o_type, &o_data);
868
869
11.6k
    if (!o_next && !t_next)
870
587
    {
871
587
      break;
872
587
    }
873
11.0k
    finished = FALSE;
874
11.0k
    if (o_next != t_next)
875
8.15k
    {
876
8.15k
      break;
877
8.15k
    }
878
2.92k
    if (!chunk_equals(t_oid, o_oid))
879
359
    {
880
359
      break;
881
359
    }
882
2.56k
    if (wc && is_wildcard(o_data))
883
10
    {
884
10
      (*wc)++;
885
10
    }
886
2.55k
    else
887
2.55k
    {
888
2.55k
      if (t_data.len != o_data.len)
889
65
      {
890
65
        break;
891
65
      }
892
2.49k
      if (!rdn_equals(t_oid, t_type, t_data, o_type, o_data))
893
985
      {
894
985
        break;
895
985
      }
896
2.49k
    }
897
    /* the enumerator returns FALSE on parse error, we are finished
898
     * if we have reached the end of the DN only */
899
1.51k
    if ((t_data.ptr + t_data.len == t_dn.ptr + t_dn.len) &&
900
115
      (o_data.ptr + o_data.len == o_dn.ptr + o_dn.len))
901
112
    {
902
112
      finished = TRUE;
903
112
    }
904
1.51k
  }
905
10.1k
  t->destroy(t);
906
10.1k
  o->destroy(o);
907
10.1k
  return finished;
908
11.5k
}
909
910
/**
911
 * Check if the data in the given chunk represents a valid DN.
912
 */
913
static bool is_valid_dn(chunk_t dn)
914
236
{
915
236
  enumerator_t *enumerator;
916
236
  chunk_t oid, data;
917
236
  u_char type;
918
236
  bool finished = FALSE;
919
920
236
  enumerator = create_rdn_enumerator(dn);
921
1.81k
  while (enumerator->enumerate(enumerator, &oid, &type, &data))
922
1.57k
  {
923
    /* the enumerator returns FALSE on parse error, we are finished
924
     * if we have reached the end of the DN only */
925
1.57k
    if ((data.ptr + data.len == dn.ptr + dn.len))
926
30
    {
927
30
      finished = TRUE;
928
30
    }
929
1.57k
  }
930
236
  enumerator->destroy(enumerator);
931
932
236
  return finished;
933
236
}
934
935
METHOD(identification_t, equals_dn, bool,
936
  private_identification_t *this, identification_t *other)
937
2.98k
{
938
2.98k
  return neither_is_regex(this, other) &&
939
2.98k
       compare_dn(this->encoded, other->get_encoding(other), NULL);
940
2.98k
}
941
942
METHOD(identification_t, hash_dn, u_int,
943
  private_identification_t *this, u_int inc)
944
630
{
945
630
  enumerator_t *rdns;
946
630
  chunk_t oid, data;
947
630
  u_char type;
948
630
  u_int hash;
949
950
630
  hash = chunk_hash_inc(chunk_from_thing(this->type), inc);
951
630
  rdns = create_rdn_enumerator(this->encoded);
952
6.48k
  while (rdns->enumerate(rdns, &oid, &type, &data))
953
5.85k
  {
954
5.85k
    hash = chunk_hash_inc(data, chunk_hash_inc(oid, hash));
955
5.85k
  }
956
630
  rdns->destroy(rdns);
957
630
  return hash;
958
630
}
959
960
METHOD(identification_t, equals_strcasecmp,  bool,
961
  private_identification_t *this, identification_t *other)
962
8.54k
{
963
8.54k
  chunk_t encoded = other->get_encoding(other);
964
965
  /* we do some extra sanity checks to check for invalid IDs with a
966
   * terminating null in it. */
967
8.54k
  if (this->type == other->get_type(other) &&
968
8.54k
    neither_is_regex(this, other) &&
969
8.54k
    this->encoded.len == encoded.len &&
970
1.67k
    memchr(this->encoded.ptr, 0, this->encoded.len) == NULL &&
971
1.57k
    memchr(encoded.ptr, 0, encoded.len) == NULL &&
972
1.57k
    strncasecmp(this->encoded.ptr, encoded.ptr, this->encoded.len) == 0)
973
1.47k
  {
974
1.47k
    return TRUE;
975
1.47k
  }
976
7.07k
  return FALSE;
977
8.54k
}
978
979
METHOD(identification_t, matches_binary, id_match_t,
980
  private_identification_t *this, identification_t *other)
981
1.33k
{
982
1.33k
  if (other->get_type(other) == ID_ANY)
983
0
  {
984
0
    return ID_MATCH_ANY;
985
0
  }
986
1.33k
  if (this->type == other->get_type(other) &&
987
865
    chunk_equals(this->encoded, other->get_encoding(other)))
988
801
  {
989
801
    return ID_MATCH_PERFECT;
990
801
  }
991
536
  return ID_MATCH_NONE;
992
1.33k
}
993
994
/**
995
 * Matches the regex in other against our own encoding.
996
 */
997
static id_match_t matches_regex(private_identification_t *this,
998
                private_identification_t *other)
999
0
{
1000
0
  char buf[BUF_LEN-1];
1001
0
  int rc;
1002
1003
0
  if (this->regex)
1004
0
  { /* don't match two regex values */
1005
0
    return ID_MATCH_NONE;
1006
0
  }
1007
0
  if (!this->encoded.len)
1008
0
  {
1009
0
    return ID_MATCH_NONE;
1010
0
  }
1011
  /* match against the string representation of the identity */
1012
0
  if (snprintf(buf, sizeof(buf), "%Y", this) >= sizeof(buf))
1013
0
  {
1014
    /* fail if the buffer is too small. note that we use BUF_LEN-1 because
1015
     * the printf hook uses BUF_LEN to print the identity internally */
1016
0
    return ID_MATCH_NONE;
1017
0
  }
1018
0
  rc = regexec(other->regex, buf, 0, NULL, 0);
1019
0
  return rc == 0 ? ID_MATCH_MAX_WILDCARDS : ID_MATCH_NONE;
1020
0
}
1021
1022
METHOD(identification_t, matches_string, id_match_t,
1023
  private_identification_t *this, identification_t *other)
1024
18.0k
{
1025
18.0k
  private_identification_t *other_priv = (private_identification_t*)other;
1026
18.0k
  chunk_t encoded = other->get_encoding(other);
1027
18.0k
  u_int len = encoded.len;
1028
1029
18.0k
  if (other->get_type(other) == ID_ANY)
1030
0
  {
1031
0
    return ID_MATCH_ANY;
1032
0
  }
1033
18.0k
  if (this->type != other->get_type(other))
1034
10.0k
  {
1035
10.0k
    return ID_MATCH_NONE;
1036
10.0k
  }
1037
7.98k
  if (other_priv->regex)
1038
0
  {
1039
0
    return matches_regex(this, other_priv);
1040
0
  }
1041
  /* try a equals check first */
1042
7.98k
  if (equals_strcasecmp(this, other))
1043
953
  {
1044
953
    return ID_MATCH_PERFECT;
1045
953
  }
1046
7.02k
  if (len == 0 || this->encoded.len < len)
1047
261
  {
1048
261
    return ID_MATCH_NONE;
1049
261
  }
1050
1051
  /* check for single wildcard at the head of the string */
1052
6.76k
  if (*encoded.ptr == '*')
1053
18
  {
1054
    /* single asterisk matches any string */
1055
18
    if (len-- == 1)
1056
0
    { /* not better than ID_ANY */
1057
0
      return ID_MATCH_ANY;
1058
0
    }
1059
18
    if (strncasecmp(this->encoded.ptr + this->encoded.len - len,
1060
18
            encoded.ptr + 1, len) == 0)
1061
18
    {
1062
18
      return ID_MATCH_ONE_WILDCARD;
1063
18
    }
1064
18
  }
1065
6.74k
  return ID_MATCH_NONE;
1066
6.76k
}
1067
1068
METHOD(identification_t, matches_any, id_match_t,
1069
  private_identification_t *this, identification_t *other)
1070
33
{
1071
33
  if (other->get_type(other) == ID_ANY)
1072
33
  {
1073
33
    return ID_MATCH_ANY;
1074
33
  }
1075
0
  return ID_MATCH_NONE;
1076
33
}
1077
1078
/**
1079
 * Match DNs given the matching function
1080
 */
1081
static id_match_t matches_dn_internal(private_identification_t *this,
1082
                    identification_t *other,
1083
                    bool (*match)(chunk_t,chunk_t,int*))
1084
9.87k
{
1085
9.87k
  private_identification_t *other_priv = (private_identification_t*)other;
1086
9.87k
  int wc;
1087
1088
9.87k
  if (other->get_type(other) == ID_ANY)
1089
0
  {
1090
0
    return ID_MATCH_ANY;
1091
0
  }
1092
1093
9.87k
  if (this->type == other->get_type(other))
1094
8.86k
  {
1095
8.86k
    if (other_priv->regex)
1096
0
    {
1097
0
      return matches_regex(this, other_priv);
1098
0
    }
1099
8.86k
    else if (match(this->encoded, other->get_encoding(other), &wc))
1100
667
    {
1101
667
      wc = min(wc, ID_MATCH_ONE_WILDCARD - ID_MATCH_MAX_WILDCARDS);
1102
667
      return ID_MATCH_PERFECT - wc;
1103
667
    }
1104
8.86k
  }
1105
9.20k
  return ID_MATCH_NONE;
1106
9.87k
}
1107
1108
METHOD(identification_t, matches_dn, id_match_t,
1109
  private_identification_t *this, identification_t *other)
1110
9.87k
{
1111
9.87k
  return matches_dn_internal(this, other, compare_dn);
1112
9.87k
}
1113
1114
METHOD(identification_t, matches_dn_reordered, id_match_t,
1115
  private_identification_t *this, identification_t *other)
1116
0
{
1117
0
  return matches_dn_internal(this, other, match_dn_reordered);
1118
0
}
1119
1120
METHOD(identification_t, matches_dn_relaxed, id_match_t,
1121
  private_identification_t *this, identification_t *other)
1122
0
{
1123
0
  return matches_dn_internal(this, other, match_dn_relaxed);
1124
0
}
1125
1126
/**
1127
 * Transform netmask to CIDR bits
1128
 */
1129
static uint8_t netmask_to_cidr(char *netmask, uint8_t address_size)
1130
180
{
1131
180
  uint8_t i, byte, netbits = 0;
1132
1133
1.73k
  for (i = 0; i < address_size; i++)
1134
1.61k
  {
1135
1.61k
    byte = netmask[i];
1136
1137
1.61k
    if (byte == 0x00)
1138
60
    {
1139
60
      break;
1140
60
    }
1141
1.55k
    if (byte == 0xff)
1142
485
    {
1143
485
      netbits += 8;
1144
485
    }
1145
1.06k
    else
1146
1.06k
    {
1147
2.54k
      while (byte & 0x80)
1148
1.47k
      {
1149
1.47k
        netbits++;
1150
1.47k
        byte <<= 1;
1151
1.47k
      }
1152
1.06k
    }
1153
1.55k
  }
1154
180
  return netbits;
1155
180
}
1156
1157
/**
1158
 * Converts the given network/netmask to an address range
1159
 */
1160
static void subnet_to_range(chunk_t encoding, uint8_t address_size,
1161
              uint8_t *from, uint8_t *to)
1162
0
{
1163
0
  uint8_t *network, *netmask, netbits, mask, i;
1164
1165
0
  network = encoding.ptr;
1166
0
  netmask = encoding.ptr + address_size;
1167
0
  netbits = netmask_to_cidr(netmask, address_size);
1168
1169
0
  memcpy(from, network, address_size);
1170
0
  memcpy(to, network, address_size);
1171
1172
0
  i = netbits / 8;
1173
0
  if (i < address_size)
1174
0
  {
1175
0
    mask = 0xff << (8 - netbits % 8);
1176
0
    from[i] = from[i] & mask;
1177
0
    to[i] = to[i] | ~mask;
1178
0
    memset(&from[i+1], 0, address_size - i - 1);
1179
0
    memset(&to[i+1], 0xff, address_size - i - 1);
1180
0
  }
1181
0
}
1182
1183
/**
1184
 * Matches one subnet (or address if netmask is NULL) against another
1185
 */
1186
static id_match_t match_subnets(uint8_t *network, uint8_t *netmask,
1187
                uint8_t *other_network, uint8_t *other_netmask,
1188
                uint8_t address_size)
1189
0
{
1190
0
  uint8_t netbits, other_netbits, i;
1191
1192
0
  other_netbits = other_netmask ? netmask_to_cidr(other_netmask, address_size)
1193
0
                  : 8 * address_size;
1194
0
  if (!other_netbits)
1195
0
  {
1196
0
    return ID_MATCH_MAX_WILDCARDS;
1197
0
  }
1198
1199
0
  netbits = netmask ? netmask_to_cidr(netmask, address_size) : 8 * address_size;
1200
1201
0
  if (netbits == other_netbits)
1202
0
  {
1203
0
    return memeq(network, other_network, address_size) ? ID_MATCH_PERFECT
1204
0
                               : ID_MATCH_NONE;
1205
0
  }
1206
0
  else if (netbits < other_netbits)
1207
0
  {
1208
0
    return ID_MATCH_NONE;
1209
0
  }
1210
1211
0
  for (i = 0; i < (other_netbits + 7)/8; i++)
1212
0
  {
1213
0
    if ((network[i] ^ other_network[i]) & other_netmask[i])
1214
0
    {
1215
0
      return ID_MATCH_NONE;
1216
0
    }
1217
0
  }
1218
0
  return ID_MATCH_ONE_WILDCARD;
1219
0
}
1220
1221
/**
1222
 * Matches two address ranges against each other
1223
 */
1224
static id_match_t match_ranges(uint8_t *from, uint8_t *to,
1225
                 uint8_t *other_from, uint8_t *other_to,
1226
                 uint8_t address_size)
1227
0
{
1228
0
  const uint8_t zeroes[16] = { 0 };
1229
0
  const uint8_t ones[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1230
0
                 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
1231
0
  int match_from, match_to;
1232
1233
0
  if (memcmp(to, from, address_size) < 0 ||
1234
0
    memcmp(other_to, other_from, address_size) < 0)
1235
0
  {
1236
    /* to is smaller than from in one of the ranges */
1237
0
    return ID_MATCH_NONE;
1238
0
  }
1239
0
  else if (memeq(other_from, zeroes, address_size) &&
1240
0
       memeq(other_to, ones, address_size))
1241
0
  {
1242
0
    return ID_MATCH_MAX_WILDCARDS;
1243
0
  }
1244
1245
0
  match_from = memcmp(from, other_from, address_size);
1246
0
  match_to = memcmp(to, other_to, address_size);
1247
1248
0
  if (!match_from && !match_to)
1249
0
  {
1250
0
    return ID_MATCH_PERFECT;
1251
0
  }
1252
0
  else if (match_from >= 0 && match_to <= 0)
1253
0
  {
1254
0
    return ID_MATCH_ONE_WILDCARD;
1255
0
  }
1256
0
  return ID_MATCH_NONE;
1257
0
}
1258
1259
/**
1260
 * Match a subnet to an address
1261
 */
1262
static id_match_t matches_subnet_to_addr(private_identification_t *this,
1263
                     identification_t *other,
1264
                     uint8_t address_size)
1265
0
{
1266
0
  chunk_t other_encoding;
1267
0
  uint8_t *network, *netmask, *address;
1268
1269
0
  other_encoding = other->get_encoding(other);
1270
0
  if (this->encoded.len != 2 * address_size ||
1271
0
    other_encoding.len != address_size)
1272
0
  {
1273
0
    return ID_MATCH_NONE;
1274
0
  }
1275
0
  network = this->encoded.ptr;
1276
0
  netmask = this->encoded.ptr + address_size;
1277
0
  address = other_encoding.ptr;
1278
0
  return match_subnets(network, netmask, address, NULL, address_size);
1279
0
}
1280
1281
/**
1282
 * Match a subnet to an address
1283
 */
1284
static id_match_t matches_range_to_addr(private_identification_t *this,
1285
                     identification_t *other,
1286
                     uint8_t address_size)
1287
0
{
1288
0
  chunk_t other_encoding;
1289
0
  uint8_t *from, *to, *address;
1290
1291
0
  other_encoding = other->get_encoding(other);
1292
0
  if (this->encoded.len != 2 * address_size ||
1293
0
    other_encoding.len != address_size)
1294
0
  {
1295
0
    return ID_MATCH_NONE;
1296
0
  }
1297
0
  from = this->encoded.ptr;
1298
0
  to = this->encoded.ptr + address_size;
1299
0
  address = other_encoding.ptr;
1300
0
  return match_ranges(from, to, address, address, address_size);
1301
0
}
1302
1303
/**
1304
 * Matches an address to a subnet
1305
 */
1306
static id_match_t matches_addr_to_subnet(private_identification_t *this,
1307
                     identification_t *other,
1308
                     uint8_t address_size)
1309
0
{
1310
0
  chunk_t other_encoding;
1311
0
  uint8_t *address, *network, *netmask;
1312
1313
0
  other_encoding = other->get_encoding(other);
1314
0
  if (this->encoded.len != address_size ||
1315
0
    other_encoding.len != 2 * address_size)
1316
0
  {
1317
0
    return ID_MATCH_NONE;
1318
0
  }
1319
0
  address = this->encoded.ptr;
1320
0
  network = other_encoding.ptr;
1321
0
  netmask = other_encoding.ptr + address_size;
1322
0
  return match_subnets(address, NULL, network, netmask, address_size);
1323
0
}
1324
1325
/**
1326
 * Matches a subnet to a subnet
1327
 */
1328
static id_match_t matches_subnet_to_subnet(private_identification_t *this,
1329
                       identification_t *other,
1330
                       uint8_t address_size)
1331
4
{
1332
4
  chunk_t other_encoding;
1333
4
  uint8_t *network, *netmask, *other_network, *other_netmask;
1334
1335
4
  other_encoding = other->get_encoding(other);
1336
4
  if (this->encoded.len != 2 * address_size ||
1337
0
    other_encoding.len != 2 * address_size)
1338
4
  {
1339
4
    return ID_MATCH_NONE;
1340
4
  }
1341
0
  network = this->encoded.ptr;
1342
0
  netmask = this->encoded.ptr + address_size;
1343
0
  other_network = other_encoding.ptr;
1344
0
  other_netmask = other_encoding.ptr + address_size;
1345
0
  return match_subnets(network, netmask, other_network, other_netmask,
1346
0
             address_size);
1347
4
}
1348
1349
/**
1350
 * Matches a range to a subnet
1351
 */
1352
static id_match_t matches_range_to_subnet(private_identification_t *this,
1353
                      identification_t *other,
1354
                      uint8_t address_size)
1355
0
{
1356
0
  chunk_t other_encoding;
1357
0
  uint8_t *from, *to, other_from[address_size], other_to[address_size];
1358
1359
0
  other_encoding = other->get_encoding(other);
1360
0
  if (this->encoded.len != 2 * address_size ||
1361
0
    other_encoding.len != 2 * address_size)
1362
0
  {
1363
0
    return ID_MATCH_NONE;
1364
0
  }
1365
1366
0
  from = this->encoded.ptr;
1367
0
  to = this->encoded.ptr + address_size;
1368
0
  subnet_to_range(other_encoding, address_size, other_from, other_to);
1369
0
  return match_ranges(from, to, other_from, other_to, address_size);
1370
0
}
1371
1372
/**
1373
 * Match an address to a range
1374
 */
1375
static id_match_t matches_addr_to_range(private_identification_t *this,
1376
                    identification_t *other,
1377
                    uint8_t address_size)
1378
0
{
1379
0
  chunk_t other_encoding;
1380
0
  uint8_t *address, *from, *to;
1381
1382
0
  other_encoding = other->get_encoding(other);
1383
0
  if (this->encoded.len != address_size ||
1384
0
    other_encoding.len != 2 * address_size)
1385
0
  {
1386
0
    return ID_MATCH_NONE;
1387
0
  }
1388
0
  address = this->encoded.ptr;
1389
0
  from = other_encoding.ptr;
1390
0
  to = other_encoding.ptr + address_size;
1391
0
  return match_ranges(address, address, from, to, address_size);
1392
0
}
1393
1394
/**
1395
 * Match a subnet to a range
1396
 */
1397
static id_match_t matches_subnet_to_range(private_identification_t *this,
1398
                      identification_t *other,
1399
                      uint8_t address_size)
1400
0
{
1401
0
  chunk_t other_encoding;
1402
0
  uint8_t from[address_size], to[address_size], *other_from, *other_to;
1403
1404
0
  other_encoding = other->get_encoding(other);
1405
0
  if (this->encoded.len != 2 * address_size ||
1406
0
    other_encoding.len != 2 * address_size)
1407
0
  {
1408
0
    return ID_MATCH_NONE;
1409
0
  }
1410
0
  subnet_to_range(this->encoded, address_size, from, to);
1411
0
  other_from = other_encoding.ptr;
1412
0
  other_to = other_encoding.ptr + address_size;
1413
0
  return match_ranges(from, to, other_from, other_to, address_size);
1414
0
}
1415
1416
/**
1417
 * Match a range to a range
1418
 */
1419
static id_match_t matches_range_to_range(private_identification_t *this,
1420
                     identification_t *other,
1421
                     uint8_t address_size)
1422
3
{
1423
3
  chunk_t other_encoding;
1424
3
  uint8_t *from, *to, *other_from, *other_to;
1425
1426
3
  other_encoding = other->get_encoding(other);
1427
3
  if (this->encoded.len != 2 * address_size ||
1428
0
    other_encoding.len != 2 * address_size)
1429
3
  {
1430
3
    return ID_MATCH_NONE;
1431
3
  }
1432
0
  from = this->encoded.ptr;
1433
0
  to = this->encoded.ptr + address_size;
1434
0
  other_from = other_encoding.ptr;
1435
0
  other_to = other_encoding.ptr + address_size;
1436
0
  return match_ranges(from, to, other_from, other_to, address_size);
1437
3
}
1438
1439
METHOD(identification_t, matches_range, id_match_t,
1440
  private_identification_t *this, identification_t *other)
1441
414
{
1442
414
  id_type_t other_type;
1443
414
  uint8_t address_size = 0;
1444
1445
414
  other_type = other->get_type(other);
1446
414
  if (other_type == ID_ANY)
1447
0
  {
1448
0
    return ID_MATCH_ANY;
1449
0
  }
1450
414
  if (this->type == other_type &&
1451
182
    chunk_equals(this->encoded, other->get_encoding(other)))
1452
171
  {
1453
171
    return ID_MATCH_PERFECT;
1454
171
  }
1455
243
  if (other_type == ID_IPV4_ADDR &&
1456
2
    (this->type == ID_IPV4_ADDR_SUBNET || this->type == ID_IPV4_ADDR_RANGE))
1457
0
  {
1458
0
    address_size = sizeof(struct in_addr);
1459
0
  }
1460
243
  else if (other_type == ID_IPV6_ADDR &&
1461
2
      (this->type == ID_IPV6_ADDR_SUBNET || this->type == ID_IPV6_ADDR_RANGE))
1462
0
  {
1463
0
    address_size = sizeof(struct in6_addr);
1464
0
  }
1465
243
  if (address_size)
1466
0
  {
1467
0
    if (this->type == ID_IPV4_ADDR_SUBNET || this->type == ID_IPV6_ADDR_SUBNET)
1468
0
    {
1469
0
      return matches_subnet_to_addr(this, other, address_size);
1470
0
    }
1471
0
    return matches_range_to_addr(this, other, address_size);
1472
0
  }
1473
243
  if (other_type == ID_IPV4_ADDR_SUBNET &&
1474
2
    (this->type == ID_IPV4_ADDR || this->type == ID_IPV4_ADDR_SUBNET ||
1475
0
     this->type == ID_IPV4_ADDR_RANGE))
1476
2
  {
1477
2
    address_size = sizeof(struct in_addr);
1478
2
  }
1479
241
  else if (other_type == ID_IPV6_ADDR_SUBNET &&
1480
2
      (this->type == ID_IPV6_ADDR || this->type == ID_IPV6_ADDR_SUBNET ||
1481
0
       this->type == ID_IPV6_ADDR_RANGE))
1482
2
  {
1483
2
    address_size = sizeof(struct in6_addr);
1484
2
  }
1485
243
  if (address_size)
1486
4
  {
1487
4
    if (this->type == ID_IPV4_ADDR || this->type == ID_IPV6_ADDR)
1488
0
    {
1489
0
      return matches_addr_to_subnet(this, other, address_size);
1490
0
    }
1491
4
    else if (this->type == ID_IPV4_ADDR_SUBNET || this->type == ID_IPV6_ADDR_SUBNET)
1492
4
    {
1493
4
      return matches_subnet_to_subnet(this, other, address_size);
1494
4
    }
1495
0
    return matches_range_to_subnet(this, other, address_size);
1496
4
  }
1497
239
  if (other_type == ID_IPV4_ADDR_RANGE &&
1498
2
    (this->type == ID_IPV4_ADDR || this->type == ID_IPV4_ADDR_SUBNET ||
1499
2
     this->type == ID_IPV4_ADDR_RANGE))
1500
2
  {
1501
2
    address_size = sizeof(struct in_addr);
1502
2
  }
1503
237
  else if (other_type == ID_IPV6_ADDR_RANGE &&
1504
1
      (this->type == ID_IPV6_ADDR || this->type == ID_IPV6_ADDR_SUBNET ||
1505
1
       this->type == ID_IPV6_ADDR_RANGE))
1506
1
  {
1507
1
    address_size = sizeof(struct in6_addr);
1508
1
  }
1509
239
  if (address_size)
1510
3
  {
1511
3
    if (this->type == ID_IPV4_ADDR || this->type == ID_IPV6_ADDR)
1512
0
    {
1513
0
      return matches_addr_to_range(this, other, address_size);
1514
0
    }
1515
3
    else if (this->type == ID_IPV4_ADDR_SUBNET || this->type == ID_IPV6_ADDR_SUBNET)
1516
0
    {
1517
0
      return matches_subnet_to_range(this, other, address_size);
1518
0
    }
1519
3
    return matches_range_to_range(this, other, address_size);
1520
3
  }
1521
236
  return ID_MATCH_NONE;
1522
239
}
1523
1524
/**
1525
 * Convert the given identity to a string depending on its type.
1526
 */
1527
static void identity_to_string(private_identification_t *this, char buf[BUF_LEN])
1528
5.01k
{
1529
5.01k
  chunk_t proper;
1530
5.01k
  char *pos;
1531
5.01k
  uint8_t address_size;
1532
5.01k
  size_t len;
1533
5.01k
  int written;
1534
1535
5.01k
  if (this->regex)
1536
0
  {
1537
0
    snprintf(buf, BUF_LEN, "%s", this->encoded.ptr);
1538
0
    return;
1539
0
  }
1540
1541
5.01k
  switch (this->type)
1542
5.01k
  {
1543
66
    case ID_ANY:
1544
66
      snprintf(buf, BUF_LEN, "%%any");
1545
66
      break;
1546
50
    case ID_IPV4_ADDR:
1547
50
      if (this->encoded.len < sizeof(struct in_addr) ||
1548
42
        inet_ntop(AF_INET, this->encoded.ptr, buf, BUF_LEN) == NULL)
1549
8
      {
1550
8
        snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR)");
1551
8
      }
1552
50
      break;
1553
76
    case ID_IPV4_ADDR_SUBNET:
1554
76
      address_size = sizeof(struct in_addr);
1555
76
      if (this->encoded.len < 2 * address_size ||
1556
64
        inet_ntop(AF_INET, this->encoded.ptr, buf, BUF_LEN) == NULL)
1557
12
      {
1558
12
        snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR_SUBNET)");
1559
12
        break;
1560
12
      }
1561
64
      written = strlen(buf);
1562
64
      snprintf(buf + written, BUF_LEN - written, "/%d",
1563
64
           netmask_to_cidr(this->encoded.ptr + address_size,
1564
64
                             address_size));
1565
64
      break;
1566
12
    case ID_IPV4_ADDR_RANGE:
1567
12
      address_size = sizeof(struct in_addr);
1568
12
      if (this->encoded.len < 2 * address_size ||
1569
8
        inet_ntop(AF_INET, this->encoded.ptr, buf, BUF_LEN) == NULL)
1570
4
      {
1571
4
        snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR_RANGE)");
1572
4
        break;
1573
4
      }
1574
8
      written = strlen(buf);
1575
8
      pos = buf + written;
1576
8
      len = BUF_LEN - written;
1577
8
      written = snprintf(pos, len, "-");
1578
8
      if (written < 0 || written >= len ||
1579
8
          inet_ntop(AF_INET, this->encoded.ptr + address_size,
1580
8
              pos + written, len - written) == NULL)
1581
0
      {
1582
0
        snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR_RANGE)");
1583
0
      }
1584
8
      break;
1585
60
    case ID_IPV6_ADDR:
1586
60
      if (this->encoded.len < sizeof(struct in6_addr) ||
1587
44
        inet_ntop(AF_INET6, this->encoded.ptr, buf, BUF_LEN) == NULL)
1588
16
      {
1589
16
        snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR)");
1590
16
      }
1591
60
      break;
1592
136
    case ID_IPV6_ADDR_SUBNET:
1593
136
      address_size = sizeof(struct in6_addr);
1594
136
      if (this->encoded.len < 2 * address_size ||
1595
116
        inet_ntop(AF_INET6, this->encoded.ptr, buf, BUF_LEN) == NULL)
1596
20
      {
1597
20
        snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR_SUBNET)");
1598
20
      }
1599
116
      else
1600
116
      {
1601
116
        written = strlen(buf);
1602
116
        snprintf(buf + written, BUF_LEN - written, "/%d",
1603
116
             netmask_to_cidr(this->encoded.ptr + address_size,
1604
116
                               address_size));
1605
116
      }
1606
136
      break;
1607
58
    case ID_IPV6_ADDR_RANGE:
1608
58
      address_size = sizeof(struct in6_addr);
1609
58
      if (this->encoded.len < 2 * address_size ||
1610
40
        inet_ntop(AF_INET6, this->encoded.ptr, buf, BUF_LEN) == NULL)
1611
18
      {
1612
18
        snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR_RANGE)");
1613
18
        break;
1614
18
      }
1615
40
      written = strlen(buf);
1616
40
      pos = buf + written;
1617
40
      len = BUF_LEN - written;
1618
40
      written = snprintf(pos, len, "-");
1619
40
      if (written < 0 || written >= len ||
1620
40
          inet_ntop(AF_INET6, this->encoded.ptr + address_size,
1621
40
              pos + written, len - written) == NULL)
1622
0
      {
1623
0
        snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR_RANGE)");
1624
0
      }
1625
40
      break;
1626
1.05k
    case ID_FQDN:
1627
1.19k
    case ID_RFC822_ADDR:
1628
1.57k
    case ID_DER_ASN1_GN_URI:
1629
1.57k
      chunk_printable(this->encoded, &proper, '?');
1630
1.57k
      snprintf(buf, BUF_LEN, "%.*s", (int)proper.len, proper.ptr);
1631
1.57k
      chunk_free(&proper);
1632
1.57k
      break;
1633
1.27k
    case ID_DER_ASN1_DN:
1634
1.27k
      dntoa(this->encoded, buf, BUF_LEN);
1635
1.27k
      break;
1636
34
    case ID_DER_ASN1_GN:
1637
34
      snprintf(buf, BUF_LEN, "(ASN.1 general name)");
1638
34
      break;
1639
1.55k
    case ID_KEY_ID:
1640
1.55k
      if (chunk_printable(this->encoded, NULL, '?') &&
1641
464
        this->encoded.len != HASH_SIZE_SHA1)
1642
462
      { /* fully printable, use ascii version */
1643
462
        snprintf(buf, BUF_LEN, "%.*s", (int)this->encoded.len,
1644
462
             this->encoded.ptr);
1645
462
      }
1646
1.09k
      else
1647
1.09k
      { /* not printable, hex dump */
1648
1.09k
        snprintf(buf, BUF_LEN, "%#B", &this->encoded);
1649
1.09k
      }
1650
1.55k
      break;
1651
122
    default:
1652
122
      snprintf(buf, BUF_LEN, "(unknown ID type: %d)", this->type);
1653
122
      break;
1654
5.01k
  }
1655
5.01k
}
1656
1657
/**
1658
 * Described in header.
1659
 */
1660
int identification_printf_hook(printf_hook_data_t *data,
1661
              printf_hook_spec_t *spec, const void *const *args)
1662
5.01k
{
1663
5.01k
  private_identification_t *this = *((private_identification_t**)(args[0]));
1664
5.01k
  char buf[BUF_LEN];
1665
1666
5.01k
  if (!this)
1667
0
  {
1668
0
    return print_in_hook(data, "%*s", spec->width, "(null)");
1669
0
  }
1670
1671
5.01k
  identity_to_string(this, buf);
1672
1673
5.01k
  if (spec->minus)
1674
0
  {
1675
0
    return print_in_hook(data, "%-*s", spec->width, buf);
1676
0
  }
1677
5.01k
  return print_in_hook(data, "%*s", spec->width, buf);
1678
5.01k
}
1679
1680
#ifdef HAVE_REGEX
1681
1682
/**
1683
 * Compile the encoded regular expression.
1684
 */
1685
static bool compile_regex(private_identification_t *this)
1686
0
{
1687
0
  char buf[BUF_LEN];
1688
0
  int err = 0;
1689
1690
0
  this->regex = malloc(sizeof(*this->regex));
1691
0
  err = regcomp(this->regex, this->encoded.ptr,
1692
0
          REG_EXTENDED | REG_ICASE | REG_NOSUB);
1693
0
  if (err != 0)
1694
0
  {
1695
0
    regerror(err, NULL, buf, sizeof(buf));
1696
0
    DBG1(DBG_LIB, "invalid regular expression '%s': %s",
1697
0
       this->encoded.ptr, buf);
1698
0
    return FALSE;
1699
0
  }
1700
0
  return TRUE;
1701
0
}
1702
1703
#else /* HAVE_REGEX */
1704
1705
static bool compile_regex(private_identification_t *this)
1706
{
1707
  DBG1(DBG_LIB, "regular expressions are not supported");
1708
  return FALSE;
1709
}
1710
1711
#endif /* HAVE_REGEX */
1712
1713
METHOD(identification_t, clone_, identification_t*,
1714
  private_identification_t *this)
1715
9.52k
{
1716
9.52k
  private_identification_t *clone = malloc_thing(private_identification_t);
1717
1718
9.52k
  memcpy(clone, this, sizeof(private_identification_t));
1719
9.52k
  if (this->regex)
1720
0
  {
1721
    /* make sure we have the full encoding cloned */
1722
0
    clone->encoded = chunk_from_str(strdup(this->encoded.ptr));
1723
0
    compile_regex(clone);
1724
0
  }
1725
9.52k
  else
1726
9.52k
  {
1727
9.52k
    clone->encoded = chunk_clone(this->encoded);
1728
9.52k
  }
1729
9.52k
  return &clone->public;
1730
9.52k
}
1731
1732
METHOD(identification_t, destroy, void,
1733
  private_identification_t *this)
1734
84.8k
{
1735
84.8k
  chunk_free(&this->encoded);
1736
84.8k
  if (this->regex)
1737
0
  {
1738
0
    regfree(this->regex);
1739
0
    free(this->regex);
1740
0
  }
1741
84.8k
  free(this);
1742
84.8k
}
1743
1744
/**
1745
 * Generic constructor used for the other constructors.
1746
 */
1747
static private_identification_t *identification_create(id_type_t type)
1748
75.3k
{
1749
75.3k
  private_identification_t *this;
1750
75.3k
  char *rdn_matching;
1751
1752
75.3k
  INIT(this,
1753
75.3k
    .public = {
1754
75.3k
      .get_encoding = _get_encoding,
1755
75.3k
      .get_type = _get_type,
1756
75.3k
      .create_part_enumerator = _create_part_enumerator,
1757
75.3k
      .clone = _clone_,
1758
75.3k
      .destroy = _destroy,
1759
75.3k
    },
1760
75.3k
    .type = type,
1761
75.3k
  );
1762
1763
75.3k
  switch (type)
1764
75.3k
  {
1765
33
    case ID_ANY:
1766
33
      this->public.hash = _hash_binary;
1767
33
      this->public.equals = _equals_binary;
1768
33
      this->public.matches = _matches_any;
1769
33
      this->public.contains_wildcards = (void*)return_true;
1770
33
      break;
1771
27.0k
    case ID_FQDN:
1772
27.9k
    case ID_RFC822_ADDR:
1773
27.9k
      this->public.hash = _hash_binary;
1774
27.9k
      this->public.equals = _equals_strcasecmp;
1775
27.9k
      this->public.matches = _matches_string;
1776
27.9k
      this->public.contains_wildcards = _contains_wildcards_memchr;
1777
27.9k
      break;
1778
37.5k
    case ID_DER_ASN1_DN:
1779
37.5k
      this->public.hash = _hash_dn;
1780
37.5k
      this->public.equals = _equals_dn;
1781
37.5k
      this->public.matches = _matches_dn;
1782
37.5k
      this->public.contains_wildcards = _contains_wildcards_dn;
1783
      /* check for more relaxed matching config */
1784
37.5k
      rdn_matching = lib->settings->get_str(lib->settings,
1785
37.5k
                      "%s.rdn_matching", NULL, lib->ns);
1786
37.5k
      if (streq("reordered", rdn_matching))
1787
0
      {
1788
0
        this->public.matches = _matches_dn_reordered;
1789
0
      }
1790
37.5k
      else if (streq("relaxed", rdn_matching))
1791
0
      {
1792
0
        this->public.matches = _matches_dn_relaxed;
1793
0
      }
1794
37.5k
      break;
1795
863
    case ID_IPV4_ADDR:
1796
1.16k
    case ID_IPV6_ADDR:
1797
1.24k
    case ID_IPV4_ADDR_SUBNET:
1798
1.40k
    case ID_IPV6_ADDR_SUBNET:
1799
1.40k
    case ID_IPV4_ADDR_RANGE:
1800
1.43k
    case ID_IPV6_ADDR_RANGE:
1801
1.43k
      this->public.hash = _hash_binary;
1802
1.43k
      this->public.equals = _equals_binary;
1803
1.43k
      this->public.matches = _matches_range;
1804
1.43k
      this->public.contains_wildcards = (void*)return_false;
1805
1.43k
      break;
1806
8.36k
    default:
1807
8.36k
      this->public.hash = _hash_binary;
1808
8.36k
      this->public.equals = _equals_binary;
1809
8.36k
      this->public.matches = _matches_binary;
1810
8.36k
      this->public.contains_wildcards = (void*)return_false;
1811
8.36k
      break;
1812
75.3k
  }
1813
75.3k
  return this;
1814
75.3k
}
1815
1816
/**
1817
 * Prefixes used when parsing identities.
1818
 */
1819
static const struct {
1820
  const char *str;
1821
  id_type_t type;
1822
  bool regex;
1823
} prefixes[] = {
1824
  { "ipv4:",      ID_IPV4_ADDR,     FALSE},
1825
  { "ipv6:",      ID_IPV6_ADDR,     FALSE},
1826
  { "ipv4net:",   ID_IPV4_ADDR_SUBNET,  FALSE},
1827
  { "ipv6net:",   ID_IPV6_ADDR_SUBNET,  FALSE},
1828
  { "ipv4range:",   ID_IPV4_ADDR_RANGE,   FALSE},
1829
  { "ipv6range:",   ID_IPV6_ADDR_RANGE,   FALSE},
1830
  { "rfc822:",    ID_RFC822_ADDR,     TRUE},
1831
  { "email:",     ID_RFC822_ADDR,     TRUE},
1832
  { "userfqdn:",    ID_RFC822_ADDR,     TRUE},
1833
  { "fqdn:",      ID_FQDN,        TRUE},
1834
  { "dns:",     ID_FQDN,        TRUE},
1835
  { "asn1dn:",    ID_DER_ASN1_DN,     TRUE},
1836
  { "asn1gn:",    ID_DER_ASN1_GN,     FALSE},
1837
  { "xmppaddr:",    ID_DER_ASN1_GN,         FALSE},
1838
  { "keyid:",     ID_KEY_ID,        FALSE},
1839
  { "uri:",     ID_DER_ASN1_GN_URI,   FALSE},
1840
};
1841
1842
/**
1843
 * Create an identity for a specific type, determined by prefix
1844
 */
1845
static private_identification_t *create_from_string_with_prefix_type(char *str)
1846
9.18k
{
1847
9.18k
  private_identification_t *this;
1848
9.18k
  int i;
1849
1850
155k
  for (i = 0; i < countof(prefixes); i++)
1851
146k
  {
1852
146k
    if (strcasepfx(str, prefixes[i].str))
1853
151
    {
1854
151
      this = identification_create(prefixes[i].type);
1855
151
      str += strlen(prefixes[i].str);
1856
1857
151
      if (*str == '#')
1858
47
      {
1859
47
        this->encoded = chunk_from_hex(chunk_from_str(str + 1), NULL);
1860
47
      }
1861
104
      else
1862
104
      {
1863
104
        this->encoded = chunk_clone(chunk_from_str(str));
1864
104
      }
1865
1866
151
      if (prefixes[i].type == ID_DER_ASN1_GN &&
1867
16
        strcasepfx(prefixes[i].str, "xmppaddr:"))
1868
14
      {
1869
14
        this->encoded = asn1_wrap(ASN1_CONTEXT_C_0, "mm",
1870
14
                  asn1_build_known_oid(OID_XMPP_ADDR),
1871
14
                  asn1_wrap(ASN1_CONTEXT_C_0, "m",
1872
14
                    asn1_wrap(ASN1_UTF8STRING, "m",
1873
14
                      this->encoded)));
1874
14
      }
1875
151
      return this;
1876
151
    }
1877
146k
  }
1878
9.03k
  return NULL;
1879
9.18k
}
1880
1881
/**
1882
 * Create an identity for a specific type, determined by a numerical prefix
1883
 *
1884
 * The prefix is of the form "{x}:", where x denotes the numerical identity
1885
 * type.
1886
 */
1887
static private_identification_t *create_from_string_with_num_type(char *str)
1888
9.03k
{
1889
9.03k
  private_identification_t *this;
1890
9.03k
  u_long type;
1891
1892
9.03k
  if (*str++ != '{')
1893
8.79k
  {
1894
8.79k
    return NULL;
1895
8.79k
  }
1896
9.03k
  errno = 0;
1897
243
  type = strtoul(str, &str, 0);
1898
243
  if (errno || *str++ != '}' || *str++ != ':')
1899
24
  {
1900
24
    return NULL;
1901
24
  }
1902
219
  this = identification_create(type);
1903
219
  if (*str == '#')
1904
4
  {
1905
4
    this->encoded = chunk_from_hex(chunk_from_str(str + 1), NULL);
1906
4
  }
1907
215
  else
1908
215
  {
1909
215
    this->encoded = chunk_clone(chunk_from_str(str));
1910
215
  }
1911
219
  return this;
1912
243
}
1913
1914
/**
1915
 * Convert to an IPv4/IPv6 host address, subnet or address range
1916
 */
1917
static private_identification_t *create_ip_address_from_string(char *string,
1918
                                 bool is_ipv4)
1919
7.75k
{
1920
7.75k
  private_identification_t *this;
1921
7.75k
  uint8_t encoding[32];
1922
7.75k
  uint8_t *str, *pos, *address, *to_address, *netmask;
1923
7.75k
  size_t address_size;
1924
7.75k
  int bits, bytes, i;
1925
7.75k
  bool has_subnet = FALSE, has_range = FALSE;
1926
1927
7.75k
  address = encoding;
1928
7.75k
  address_size = is_ipv4 ? sizeof(struct in_addr) : sizeof(struct in6_addr);
1929
1930
7.75k
  str = strdup(string);
1931
7.75k
  pos = strchr(str, '/');
1932
7.75k
  if (pos)
1933
118
  { /* separate IP address from optional netmask */
1934
1935
118
    *pos = '\0';
1936
118
    has_subnet = TRUE;
1937
118
  }
1938
7.64k
  else
1939
7.64k
  {
1940
7.64k
    pos = strchr(str, '-');
1941
7.64k
    if (pos)
1942
23
    { /* separate lower address from upper address of IP range */
1943
23
      *pos = '\0';
1944
23
      has_range = TRUE;
1945
23
    }
1946
7.64k
  }
1947
1948
7.75k
  if (inet_pton(is_ipv4 ? AF_INET : AF_INET6, str, address) != 1)
1949
7.63k
  {
1950
7.63k
    free(str);
1951
7.63k
    return NULL;
1952
7.63k
  }
1953
1954
126
  if (has_subnet)
1955
101
  { /* is IP subnet */
1956
101
    bits = atoi(pos + 1);
1957
101
    if (bits > 8 * address_size)
1958
70
    {
1959
70
      free(str);
1960
70
      return NULL;
1961
70
    }
1962
31
    bytes = bits / 8;
1963
31
    bits -= 8 * bytes;
1964
31
    netmask = encoding + address_size;
1965
1966
407
    for (i = 0; i < address_size; i++)
1967
376
    {
1968
376
      if (bytes)
1969
134
      {
1970
134
        *netmask = 0xff;
1971
134
        bytes--;
1972
134
      }
1973
242
      else if (bits)
1974
26
      {
1975
26
        *netmask = 0xff << (8 - bits);
1976
26
        bits = 0;
1977
26
      }
1978
216
      else
1979
216
      {
1980
216
        *netmask = 0x00;
1981
216
      }
1982
376
      *address++ &= *netmask++;
1983
376
    }
1984
31
    this = identification_create(is_ipv4 ? ID_IPV4_ADDR_SUBNET :
1985
31
                         ID_IPV6_ADDR_SUBNET);
1986
31
    this->encoded = chunk_clone(chunk_create(encoding, 2 * address_size));
1987
31
  }
1988
25
  else if (has_range)
1989
18
  { /* is IP range */
1990
18
    to_address = encoding + address_size;
1991
1992
18
    if (inet_pton(is_ipv4 ? AF_INET : AF_INET6, pos + 1, to_address) != 1)
1993
1
    {
1994
1
      free(str);
1995
1
      return NULL;
1996
1
    }
1997
168
    for (i = 0; i < address_size; i++)
1998
167
    {
1999
167
      if (address[i] != to_address[i])
2000
16
      {
2001
16
        if (address[i] > to_address[i])
2002
12
        {
2003
12
          free(str);
2004
12
          return NULL;
2005
12
        }
2006
4
        break;
2007
16
      }
2008
167
    }
2009
5
    this = identification_create(is_ipv4 ? ID_IPV4_ADDR_RANGE :
2010
5
                         ID_IPV6_ADDR_RANGE);
2011
5
    this->encoded = chunk_clone(chunk_create(encoding, 2 * address_size));
2012
5
  }
2013
7
  else
2014
7
  { /* is IP host address */
2015
7
    this = identification_create(is_ipv4 ? ID_IPV4_ADDR : ID_IPV6_ADDR);
2016
7
    this->encoded = chunk_clone(chunk_create(encoding, address_size));
2017
7
  }
2018
43
  free(str);
2019
2020
43
  return this;
2021
126
}
2022
2023
/*
2024
 * Described in header.
2025
 */
2026
identification_t *identification_create_from_string(char *string)
2027
9.18k
{
2028
9.18k
  private_identification_t *this;
2029
9.18k
  chunk_t encoded;
2030
2031
9.18k
  if (string == NULL)
2032
0
  {
2033
0
    string = "%any";
2034
0
  }
2035
9.18k
  this = create_from_string_with_prefix_type(string);
2036
9.18k
  if (this)
2037
151
  {
2038
151
    return &this->public;
2039
151
  }
2040
9.03k
  this = create_from_string_with_num_type(string);
2041
9.03k
  if (this)
2042
219
  {
2043
219
    return &this->public;
2044
219
  }
2045
8.81k
  if (strchr(string, '=') != NULL)
2046
779
  {
2047
    /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN.
2048
     * convert from LDAP style or openssl x509 -subject style to ASN.1 DN
2049
     */
2050
779
    if (atodn(string, &encoded) == SUCCESS)
2051
547
    {
2052
547
      this = identification_create(ID_DER_ASN1_DN);
2053
547
      this->encoded = encoded;
2054
547
    }
2055
232
    else
2056
232
    {
2057
232
      this = identification_create(ID_KEY_ID);
2058
232
      this->encoded = chunk_clone(chunk_from_str(string));
2059
232
    }
2060
779
    return &this->public;
2061
779
  }
2062
8.03k
  else if (strchr(string, '@') == NULL)
2063
7.76k
  {
2064
7.76k
    if (streq(string, "")
2065
7.76k
    ||  streq(string, "%any")
2066
7.76k
    ||  streq(string, "%any6")
2067
7.76k
    ||  streq(string, "0.0.0.0")
2068
7.76k
    ||  streq(string, "*")
2069
7.76k
    ||  streq(string, "::")
2070
7.76k
    ||  streq(string, "0::0"))
2071
6
    {
2072
      /* any ID will be accepted */
2073
6
      this = identification_create(ID_ANY);
2074
6
      return &this->public;
2075
6
    }
2076
7.75k
    else
2077
7.75k
    {
2078
7.75k
      if (strchr(string, ':') == NULL)
2079
7.59k
      {
2080
        /* IPv4 address or subnet */
2081
7.59k
        this = create_ip_address_from_string(string, TRUE);
2082
7.59k
        if (!this)
2083
7.58k
        { /* not IPv4, mostly FQDN */
2084
7.58k
          this = identification_create(ID_FQDN);
2085
7.58k
          this->encoded = chunk_clone(chunk_from_str(string));
2086
7.58k
        }
2087
7.59k
        return &this->public;
2088
7.59k
      }
2089
167
      else
2090
167
      {
2091
        /* IPv6 address or subnet */
2092
167
        this = create_ip_address_from_string(string, FALSE);
2093
167
        if (!this)
2094
136
        { /* not IPv4/6 fallback to KEY_ID */
2095
136
          this = identification_create(ID_KEY_ID);
2096
136
          this->encoded = chunk_clone(chunk_from_str(string));
2097
136
        }
2098
167
        return &this->public;
2099
167
      }
2100
7.75k
    }
2101
7.76k
  }
2102
271
  else
2103
271
  {
2104
271
    if (*string == '@')
2105
234
    {
2106
234
      string++;
2107
234
      if (*string == '#')
2108
181
      {
2109
181
        this = identification_create(ID_KEY_ID);
2110
181
        this->encoded = chunk_from_hex(chunk_from_str(string + 1), NULL);
2111
181
        return &this->public;
2112
181
      }
2113
53
      else if (*string == '@')
2114
20
      {
2115
20
        this = identification_create(ID_RFC822_ADDR);
2116
20
        this->encoded = chunk_clone(chunk_from_str(string + 1));
2117
20
        return &this->public;
2118
20
      }
2119
33
      else
2120
33
      {
2121
33
        this = identification_create(ID_FQDN);
2122
33
        this->encoded = chunk_clone(chunk_from_str(string));
2123
33
        return &this->public;
2124
33
      }
2125
234
    }
2126
37
    else
2127
37
    {
2128
37
      this = identification_create(ID_RFC822_ADDR);
2129
37
      this->encoded = chunk_clone(chunk_from_str(string));
2130
37
      return &this->public;
2131
37
    }
2132
271
  }
2133
8.81k
}
2134
2135
/**
2136
 * Check if the given string should be parsed as regular expression identity.
2137
 * If so, it modifies the string and returns the identity type, otherwise,
2138
 * ID_ANY is returned.
2139
 */
2140
static id_type_t is_regex_identity(char **string)
2141
0
{
2142
0
  char *regex;
2143
0
  int i;
2144
2145
0
  for (i = 0; i < countof(prefixes); i++)
2146
0
  {
2147
0
    if (strcasepfx(*string, prefixes[i].str))
2148
0
    {
2149
0
      regex = *string + strlen(prefixes[i].str);
2150
2151
0
      if (prefixes[i].regex &&
2152
0
        *regex == '^' && *(regex + strlen(regex) - 1) == '$')
2153
0
      {
2154
0
        *string = regex;
2155
0
        return prefixes[i].type;
2156
0
      }
2157
0
      break;
2158
0
    }
2159
0
  }
2160
0
  return ID_ANY;
2161
0
}
2162
2163
/*
2164
 * Described in header.
2165
 */
2166
identification_t *identification_create_from_string_with_regex(char *string)
2167
0
{
2168
0
  private_identification_t *this;
2169
0
  id_type_t type;
2170
2171
0
  type = is_regex_identity(&string);
2172
0
  if (type != ID_ANY)
2173
0
  {
2174
0
    this = identification_create(type);
2175
2176
0
    this->public.hash = _hash_binary;
2177
0
    this->public.equals = _equals_binary;
2178
0
    this->public.matches = _matches_any;
2179
0
    this->public.contains_wildcards = (void*)return_true;
2180
2181
    /* this encoding explicitly includes the null-terminator so we can
2182
     * directly use it to compile the regex and printing */
2183
0
    this->encoded = chunk_from_str(strdup(string));
2184
0
    if (!compile_regex(this))
2185
0
    {
2186
0
      destroy(this);
2187
0
      return NULL;
2188
0
    }
2189
0
    return &this->public;
2190
0
  }
2191
0
  return identification_create_from_string(string);
2192
0
}
2193
2194
/*
2195
 * Described in header.
2196
 */
2197
identification_t *identification_create_from_data(chunk_t data)
2198
2.27k
{
2199
2.27k
  identification_t *id;
2200
2201
2.27k
  if (is_asn1(data) && is_valid_dn(data))
2202
30
  {
2203
30
    id = identification_create_from_encoding(ID_DER_ASN1_DN, data);
2204
30
  }
2205
2.24k
  else if (data.len && memchr(data.ptr, '\0', data.len))
2206
227
  {
2207
    /* treat identities that would get truncated below as opaque blobs */
2208
227
    id = identification_create_from_encoding(ID_KEY_ID, data);
2209
227
  }
2210
2.01k
  else
2211
2.01k
  {
2212
2.01k
    char *str;
2213
2214
2.01k
    str = strndup(data.ptr, data.len);
2215
2.01k
    id = identification_create_from_string(str);
2216
2.01k
    free(str);
2217
2.01k
  }
2218
2.27k
  return id;
2219
2.27k
}
2220
2221
/*
2222
 * Described in header.
2223
 */
2224
identification_t *identification_create_from_encoding(id_type_t type,
2225
                            chunk_t encoded)
2226
66.1k
{
2227
66.1k
  private_identification_t *this = identification_create(type);
2228
2229
  /* apply encoded chunk */
2230
66.1k
  if (type != ID_ANY)
2231
66.1k
  {
2232
66.1k
    this->encoded = chunk_clone(encoded);
2233
66.1k
  }
2234
66.1k
  return &(this->public);
2235
66.1k
}
2236
2237
/*
2238
 * Described in header.
2239
 */
2240
identification_t *identification_create_from_sockaddr(sockaddr_t *sockaddr)
2241
0
{
2242
0
  switch (sockaddr->sa_family)
2243
0
  {
2244
0
    case AF_INET:
2245
0
    {
2246
0
      struct in_addr *addr = &(((struct sockaddr_in*)sockaddr)->sin_addr);
2247
2248
0
      return identification_create_from_encoding(ID_IPV4_ADDR,
2249
0
          chunk_create((u_char*)addr, sizeof(struct in_addr)));
2250
0
    }
2251
0
    case AF_INET6:
2252
0
    {
2253
0
      struct in6_addr *addr = &(((struct sockaddr_in6*)sockaddr)->sin6_addr);
2254
2255
0
      return identification_create_from_encoding(ID_IPV6_ADDR,
2256
0
          chunk_create((u_char*)addr, sizeof(struct in6_addr)));
2257
0
    }
2258
0
    default:
2259
0
    {
2260
0
      private_identification_t *this = identification_create(ID_ANY);
2261
2262
0
      return &(this->public);
2263
0
    }
2264
0
  }
2265
0
}