Coverage Report

Created: 2026-06-30 06:14

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
0
#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
4.31k
{
159
4.31k
  private_identification_t *other_priv = (private_identification_t*)other;
160
4.31k
  return !this->regex && !other_priv->regex;
161
4.31k
}
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
6.43k
{
178
6.43k
  chunk_t rdn, *oid, *data;
179
6.43k
  u_char *type;
180
181
6.43k
  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
6.43k
  if (!this->seqs.len)
186
6.42k
  {
187
    /* no SEQUENCEs in current SET, parse next SET */
188
6.42k
    if (asn1_unwrap(&this->sets, &this->seqs) != ASN1_SET)
189
100
    {
190
100
      return FALSE;
191
100
    }
192
6.42k
  }
193
6.33k
  if (asn1_unwrap(&this->seqs, &rdn) == ASN1_SEQUENCE &&
194
6.29k
    asn1_unwrap(&rdn, oid) == ASN1_OID)
195
6.26k
  {
196
6.26k
    int t = asn1_unwrap(&rdn, data);
197
198
6.26k
    if (t != ASN1_INVALID)
199
6.23k
    {
200
6.23k
      *type = t;
201
6.23k
      return TRUE;
202
6.23k
    }
203
6.26k
  }
204
99
  return FALSE;
205
6.33k
}
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
10.3k
{
212
10.3k
  rdn_enumerator_t *e;
213
214
10.3k
  INIT(e,
215
10.3k
    .public = {
216
10.3k
      .enumerate = enumerator_enumerate_default,
217
10.3k
      .venumerate = _rdn_enumerate,
218
10.3k
      .destroy = (void*)free,
219
10.3k
    },
220
10.3k
  );
221
222
  /* a DN is a SEQUENCE, get the first SET of it */
223
10.3k
  if (asn1_unwrap(&dn, &e->sets) == ASN1_SEQUENCE)
224
5.74k
  {
225
5.74k
    e->seqs = chunk_empty;
226
5.74k
    return &e->public;
227
5.74k
  }
228
4.61k
  free(e);
229
4.61k
  return enumerator_create_empty();
230
10.3k
}
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
0
{
245
0
  int i, known_oid, strtype;
246
0
  chunk_t oid, inner_data, *data;
247
0
  id_part_t *type;
248
0
  static const struct {
249
0
    int oid;
250
0
    id_part_t type;
251
0
  } oid2part[] = {
252
0
    {OID_COMMON_NAME,   ID_PART_RDN_CN},
253
0
    {OID_SURNAME,     ID_PART_RDN_SN},
254
0
    {OID_SERIAL_NUMBER,   ID_PART_RDN_SERIAL_NUMBER},
255
0
    {OID_COUNTRY,     ID_PART_RDN_C},
256
0
    {OID_LOCALITY,     ID_PART_RDN_L},
257
0
    {OID_STATE_OR_PROVINCE, ID_PART_RDN_ST},
258
0
    {OID_ORGANIZATION,   ID_PART_RDN_O},
259
0
    {OID_ORGANIZATION_UNIT, ID_PART_RDN_OU},
260
0
    {OID_TITLE,       ID_PART_RDN_T},
261
0
    {OID_DESCRIPTION,   ID_PART_RDN_D},
262
0
    {OID_NAME,       ID_PART_RDN_N},
263
0
    {OID_GIVEN_NAME,   ID_PART_RDN_G},
264
0
    {OID_INITIALS,     ID_PART_RDN_I},
265
0
    {OID_DN_QUALIFIER,   ID_PART_RDN_DNQ},
266
0
    {OID_DMD_NAME,     ID_PART_RDN_DMDN},
267
0
    {OID_PSEUDONYM,     ID_PART_RDN_PN},
268
0
    {OID_UNIQUE_IDENTIFIER, ID_PART_RDN_ID},
269
0
    {OID_EMAIL_ADDRESS,   ID_PART_RDN_E},
270
0
    {OID_EMPLOYEE_NUMBER, ID_PART_RDN_EN},
271
0
  };
272
273
0
  VA_ARGS_VGET(args, type, data);
274
275
0
  while (this->inner->enumerate(this->inner, &oid, &strtype, &inner_data))
276
0
  {
277
0
    known_oid = asn1_known_oid(oid);
278
0
    for (i = 0; i < countof(oid2part); i++)
279
0
    {
280
0
      if (oid2part[i].oid == known_oid)
281
0
      {
282
0
        *type = oid2part[i].type;
283
0
        *data = inner_data;
284
0
        return TRUE;
285
0
      }
286
0
    }
287
0
  }
288
0
  return FALSE;
289
0
}
290
291
METHOD(enumerator_t, rdn_part_enumerator_destroy, void,
292
  rdn_part_enumerator_t *this)
293
0
{
294
0
  this->inner->destroy(this->inner);
295
0
  free(this);
296
0
}
297
298
METHOD(identification_t, create_part_enumerator, enumerator_t*,
299
  private_identification_t *this)
300
0
{
301
0
  switch (this->type)
302
0
  {
303
0
    case ID_DER_ASN1_DN:
304
0
    {
305
0
      rdn_part_enumerator_t *e;
306
307
0
      INIT(e,
308
0
        .inner = create_rdn_enumerator(this->encoded),
309
0
        .public = {
310
0
          .enumerate = enumerator_enumerate_default,
311
0
          .venumerate = _rdn_part_enumerate,
312
0
          .destroy = _rdn_part_enumerator_destroy,
313
0
        },
314
0
      );
315
0
      return &e->public;
316
0
    }
317
0
    case ID_RFC822_ADDR:
318
      /* TODO */
319
0
    case ID_FQDN:
320
      /* TODO */
321
0
    default:
322
0
      return enumerator_create_empty();
323
0
  }
324
0
}
325
326
/**
327
 * Print a separator between two RDNs
328
 */
329
static inline bool print_separator(char **buf, size_t *len)
330
0
{
331
0
  int written;
332
333
0
  written = snprintf(*buf, *len, ", ");
334
0
  if (written < 0 || written >= *len)
335
0
  {
336
0
    return FALSE;
337
0
  }
338
0
  *buf += written;
339
0
  *len -= written;
340
0
  return TRUE;
341
0
}
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
0
{
348
0
  enumerator_t *e;
349
0
  chunk_t oid_data, data, printable;
350
0
  u_char type;
351
0
  int oid, written;
352
0
  bool finished = FALSE, empty = TRUE;
353
354
0
  e = create_rdn_enumerator(dn);
355
0
  while (e->enumerate(e, &oid_data, &type, &data))
356
0
  {
357
0
    empty = FALSE;
358
359
    /* previous RDN was empty but it wasn't the last one */
360
0
    if (finished && !print_separator(&buf, &len))
361
0
    {
362
0
      break;
363
0
    }
364
0
    finished = FALSE;
365
366
0
    oid = asn1_known_oid(oid_data);
367
0
    if (oid == OID_UNKNOWN)
368
0
    {
369
0
      written = snprintf(buf, len, "%#B=", &oid_data);
370
0
    }
371
0
    else
372
0
    {
373
0
      written = snprintf(buf, len,"%s=", oid_names[oid].name);
374
0
    }
375
0
    if (written < 0 || written >= len)
376
0
    {
377
0
      break;
378
0
    }
379
0
    buf += written;
380
0
    len -= written;
381
382
0
    written = 0;
383
0
    chunk_printable(data, &printable, '?');
384
0
    if (printable.ptr)
385
0
    {
386
0
      written = snprintf(buf, len, "%.*s", (int)printable.len,
387
0
                 printable.ptr);
388
0
    }
389
0
    chunk_free(&printable);
390
0
    if (written < 0 || written >= len)
391
0
    {
392
0
      break;
393
0
    }
394
0
    buf += written;
395
0
    len -= written;
396
397
0
    if (!data.ptr)
398
0
    { /* we can't calculate if we're finished, assume we are */
399
0
      finished = TRUE;
400
0
    }
401
0
    else if (data.ptr + data.len == dn.ptr + dn.len)
402
0
    {
403
0
      finished = TRUE;
404
0
      break;
405
0
    }
406
0
    else if (!print_separator(&buf, &len))
407
0
    {
408
0
      break;
409
0
    }
410
0
  }
411
0
  if (empty)
412
0
  {
413
0
    snprintf(buf, len, "");
414
0
  }
415
0
  else if (!finished)
416
0
  {
417
0
    snprintf(buf, len, "(invalid ID_DER_ASN1_DN)");
418
0
  }
419
0
  e->destroy(e);
420
0
}
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
0
{
428
  /* finite state machine for atodn */
429
0
  typedef enum {
430
0
    SEARCH_OID =  0,
431
0
    READ_OID =    1,
432
0
    SEARCH_NAME = 2,
433
0
    READ_NAME =   3,
434
0
    UNKNOWN_OID = 4
435
0
  } state_t;
436
437
0
  chunk_t oid  = chunk_empty;
438
0
  chunk_t name = chunk_empty;
439
0
  chunk_t rdns[RDN_MAX];
440
0
  int rdn_count = 0;
441
0
  int dn_len = 0;
442
0
  int whitespace = 0;
443
0
  int i = 0;
444
0
  asn1_t rdn_type;
445
0
  state_t state = SEARCH_OID;
446
0
  status_t status = SUCCESS;
447
0
  char sep = '\0';
448
449
0
  do
450
0
  {
451
0
    switch (state)
452
0
    {
453
0
      case SEARCH_OID:
454
0
        if (!sep && *src == '/')
455
0
        { /* use / as separator if the string starts with a slash */
456
0
          sep = '/';
457
0
          break;
458
0
        }
459
0
        if (*src != ' ' && *src != '\0')
460
0
        {
461
0
          if (!sep)
462
0
          { /* use , as separator by default */
463
0
            sep = ',';
464
0
          }
465
0
          oid.ptr = src;
466
0
          oid.len = 1;
467
0
          state = READ_OID;
468
0
        }
469
0
        break;
470
0
      case READ_OID:
471
0
        if (*src != ' ' && *src != '=')
472
0
        {
473
0
          oid.len++;
474
0
        }
475
0
        else
476
0
        {
477
0
          bool found = FALSE;
478
479
0
          for (i = 0; i < countof(x501rdns); i++)
480
0
          {
481
0
            if (strlen(x501rdns[i].name) == oid.len &&
482
0
              strncasecmp(x501rdns[i].name, oid.ptr, oid.len) == 0)
483
0
            {
484
0
              found = TRUE;
485
0
              break;
486
0
            }
487
0
          }
488
0
          if (!found)
489
0
          {
490
0
            status = NOT_SUPPORTED;
491
0
            state = UNKNOWN_OID;
492
0
            break;
493
0
          }
494
          /* reset oid and change state */
495
0
          oid = chunk_empty;
496
0
          state = SEARCH_NAME;
497
0
        }
498
0
        break;
499
0
      case SEARCH_NAME:
500
0
        if (*src == ' ' || *src == '=')
501
0
        {
502
0
          break;
503
0
        }
504
0
        else if (*src != sep && *src != '\0')
505
0
        {
506
0
          name.ptr = src;
507
0
          name.len = 1;
508
0
          whitespace = 0;
509
0
          state = READ_NAME;
510
0
          break;
511
0
        }
512
0
        name = chunk_empty;
513
0
        whitespace = 0;
514
0
        state = READ_NAME;
515
        /* fall-through */
516
0
      case READ_NAME:
517
0
        if (*src != sep && *src != '\0')
518
0
        {
519
0
          name.len++;
520
0
          if (*src == ' ')
521
0
            whitespace++;
522
0
          else
523
0
            whitespace = 0;
524
0
        }
525
0
        else
526
0
        {
527
0
          name.len -= whitespace;
528
0
          rdn_type = (x501rdns[i].type == ASN1_PRINTABLESTRING
529
0
                && !asn1_is_printablestring(name))
530
0
                ? ASN1_UTF8STRING : x501rdns[i].type;
531
532
0
          if (rdn_count < RDN_MAX)
533
0
          {
534
0
            chunk_t rdn_oid;
535
536
0
            rdn_oid = asn1_build_known_oid(x501rdns[i].oid);
537
0
            if (rdn_oid.len)
538
0
            {
539
0
              rdns[rdn_count] =
540
0
                  asn1_wrap(ASN1_SET, "m",
541
0
                    asn1_wrap(ASN1_SEQUENCE, "mm",
542
0
                      rdn_oid,
543
0
                      asn1_wrap(rdn_type, "c", name)
544
0
                    )
545
0
                  );
546
0
              dn_len += rdns[rdn_count++].len;
547
0
            }
548
0
            else
549
0
            {
550
0
              status = INVALID_ARG;
551
0
            }
552
0
          }
553
0
          else
554
0
          {
555
0
            status = OUT_OF_RES;
556
0
          }
557
          /* reset name and change state */
558
0
          name = chunk_empty;
559
0
          state = SEARCH_OID;
560
0
        }
561
0
        break;
562
0
      case UNKNOWN_OID:
563
0
        break;
564
0
    }
565
0
  } while (*src++ != '\0');
566
567
0
  if (state == READ_OID)
568
0
  { /* unterminated OID */
569
0
    status = INVALID_ARG;
570
0
  }
571
572
  /* build the distinguished name sequence */
573
0
  {
574
0
    int i;
575
0
    u_char *pos = asn1_build_object(dn, ASN1_SEQUENCE, dn_len);
576
577
0
    for (i = 0; i < rdn_count; i++)
578
0
    {
579
0
      memcpy(pos, rdns[i].ptr, rdns[i].len);
580
0
      pos += rdns[i].len;
581
0
      free(rdns[i].ptr);
582
0
    }
583
0
  }
584
0
  if (status != SUCCESS)
585
0
  {
586
0
    free(dn->ptr);
587
0
    *dn = chunk_empty;
588
0
  }
589
0
  return status;
590
0
}
591
592
METHOD(identification_t, get_encoding, chunk_t,
593
  private_identification_t *this)
594
27.9k
{
595
27.9k
  return this->encoded;
596
27.9k
}
597
598
METHOD(identification_t, get_type, id_type_t,
599
  private_identification_t *this)
600
45.1k
{
601
45.1k
  return this->type;
602
45.1k
}
603
604
/**
605
 * Check if this is a wildcard value
606
 */
607
static inline bool is_wildcard(chunk_t data)
608
360
{
609
360
  return data.len == 1 && data.ptr[0] == '*';
610
360
}
611
612
METHOD(identification_t, contains_wildcards_dn, bool,
613
  private_identification_t *this)
614
0
{
615
0
  enumerator_t *enumerator;
616
0
  bool contains = FALSE;
617
0
  id_part_t type;
618
0
  chunk_t data;
619
620
0
  enumerator = create_part_enumerator(this);
621
0
  while (enumerator->enumerate(enumerator, &type, &data))
622
0
  {
623
0
    if (is_wildcard(data))
624
0
    {
625
0
      contains = TRUE;
626
0
      break;
627
0
    }
628
0
  }
629
0
  enumerator->destroy(enumerator);
630
0
  return contains;
631
0
}
632
633
METHOD(identification_t, contains_wildcards_memchr, bool,
634
  private_identification_t *this)
635
0
{
636
0
  return memchr(this->encoded.ptr, '*', this->encoded.len) != NULL;
637
0
}
638
639
METHOD(identification_t, hash_binary, u_int,
640
  private_identification_t *this, u_int inc)
641
0
{
642
0
  u_int hash;
643
644
0
  hash = chunk_hash_inc(chunk_from_thing(this->type), inc);
645
0
  if (this->type != ID_ANY)
646
0
  {
647
0
    hash = chunk_hash_inc(this->encoded, hash);
648
0
  }
649
0
  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
0
  return hash;
654
0
}
655
656
METHOD(identification_t, equals_binary, bool,
657
  private_identification_t *this, identification_t *other)
658
0
{
659
0
  private_identification_t *other_priv = (private_identification_t*)other;
660
661
0
  if (this->type == other_priv->type &&
662
0
     (neither_is_regex(this, other) || (this->regex && other_priv->regex)))
663
0
  {
664
0
    if (this->type == ID_ANY)
665
0
    {
666
0
      return TRUE;
667
0
    }
668
0
    return chunk_equals(this->encoded, other_priv->encoded);
669
0
  }
670
0
  return FALSE;
671
0
}
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
624
{
679
624
  if (a_type == b_type &&
680
518
    (a_type == ASN1_PRINTABLESTRING ||
681
42
     (a_type == ASN1_IA5STRING &&
682
1
      asn1_known_oid(oid) == OID_EMAIL_ADDRESS)))
683
476
  { /* ignore case for printableStrings and email RDNs */
684
476
    return strncaseeq(a.ptr, b.ptr, a.len);
685
476
  }
686
148
  else
687
148
  { /* respect case and length for everything else */
688
148
    return memeq(a.ptr, b.ptr, a.len);
689
148
  }
690
624
}
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
5.25k
{
843
5.25k
  enumerator_t *t, *o;
844
5.25k
  chunk_t t_oid, o_oid, t_data, o_data;
845
5.25k
  u_char t_type, o_type;
846
5.25k
  bool t_next, o_next, finished = FALSE;
847
848
5.25k
  if (wc)
849
4.93k
  {
850
4.93k
    *wc = 0;
851
4.93k
  }
852
325
  else if (t_dn.len != o_dn.len)
853
47
  {
854
47
    return FALSE;
855
47
  }
856
857
5.20k
  if (chunk_equals(t_dn, o_dn))
858
33
  {
859
33
    return TRUE;
860
33
  }
861
862
5.17k
  t = create_rdn_enumerator(t_dn);
863
5.17k
  o = create_rdn_enumerator(o_dn);
864
5.17k
  while (TRUE)
865
5.52k
  {
866
5.52k
    t_next = t->enumerate(t, &t_oid, &t_type, &t_data);
867
5.52k
    o_next = o->enumerate(o, &o_oid, &o_type, &o_data);
868
869
5.52k
    if (!o_next && !t_next)
870
55
    {
871
55
      break;
872
55
    }
873
5.46k
    finished = FALSE;
874
5.46k
    if (o_next != t_next)
875
4.70k
    {
876
4.70k
      break;
877
4.70k
    }
878
767
    if (!chunk_equals(t_oid, o_oid))
879
84
    {
880
84
      break;
881
84
    }
882
683
    if (wc && is_wildcard(o_data))
883
11
    {
884
11
      (*wc)++;
885
11
    }
886
672
    else
887
672
    {
888
672
      if (t_data.len != o_data.len)
889
48
      {
890
48
        break;
891
48
      }
892
624
      if (!rdn_equals(t_oid, t_type, t_data, o_type, o_data))
893
288
      {
894
288
        break;
895
288
      }
896
624
    }
897
    /* the enumerator returns FALSE on parse error, we are finished
898
     * if we have reached the end of the DN only */
899
347
    if ((t_data.ptr + t_data.len == t_dn.ptr + t_dn.len) &&
900
21
      (o_data.ptr + o_data.len == o_dn.ptr + o_dn.len))
901
18
    {
902
18
      finished = TRUE;
903
18
    }
904
347
  }
905
5.17k
  t->destroy(t);
906
5.17k
  o->destroy(o);
907
5.17k
  return finished;
908
5.20k
}
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
0
{
915
0
  enumerator_t *enumerator;
916
0
  chunk_t oid, data;
917
0
  u_char type;
918
0
  bool finished = FALSE;
919
920
0
  enumerator = create_rdn_enumerator(dn);
921
0
  while (enumerator->enumerate(enumerator, &oid, &type, &data))
922
0
  {
923
    /* the enumerator returns FALSE on parse error, we are finished
924
     * if we have reached the end of the DN only */
925
0
    if ((data.ptr + data.len == dn.ptr + dn.len))
926
0
    {
927
0
      finished = TRUE;
928
0
    }
929
0
  }
930
0
  enumerator->destroy(enumerator);
931
932
0
  return finished;
933
0
}
934
935
METHOD(identification_t, equals_dn, bool,
936
  private_identification_t *this, identification_t *other)
937
325
{
938
325
  return neither_is_regex(this, other) &&
939
325
       compare_dn(this->encoded, other->get_encoding(other), NULL);
940
325
}
941
942
METHOD(identification_t, hash_dn, u_int,
943
  private_identification_t *this, u_int inc)
944
0
{
945
0
  enumerator_t *rdns;
946
0
  chunk_t oid, data;
947
0
  u_char type;
948
0
  u_int hash;
949
950
0
  hash = chunk_hash_inc(chunk_from_thing(this->type), inc);
951
0
  rdns = create_rdn_enumerator(this->encoded);
952
0
  while (rdns->enumerate(rdns, &oid, &type, &data))
953
0
  {
954
0
    hash = chunk_hash_inc(data, chunk_hash_inc(oid, hash));
955
0
  }
956
0
  rdns->destroy(rdns);
957
0
  return hash;
958
0
}
959
960
METHOD(identification_t, equals_strcasecmp,  bool,
961
  private_identification_t *this, identification_t *other)
962
3.99k
{
963
3.99k
  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
3.99k
  if (this->type == other->get_type(other) &&
968
3.99k
    neither_is_regex(this, other) &&
969
3.99k
    this->encoded.len == encoded.len &&
970
519
    memchr(this->encoded.ptr, 0, this->encoded.len) == NULL &&
971
508
    memchr(encoded.ptr, 0, encoded.len) == NULL &&
972
508
    strncasecmp(this->encoded.ptr, encoded.ptr, this->encoded.len) == 0)
973
376
  {
974
376
    return TRUE;
975
376
  }
976
3.61k
  return FALSE;
977
3.99k
}
978
979
METHOD(identification_t, matches_binary, id_match_t,
980
  private_identification_t *this, identification_t *other)
981
54
{
982
54
  if (other->get_type(other) == ID_ANY)
983
0
  {
984
0
    return ID_MATCH_ANY;
985
0
  }
986
54
  if (this->type == other->get_type(other) &&
987
0
    chunk_equals(this->encoded, other->get_encoding(other)))
988
0
  {
989
0
    return ID_MATCH_PERFECT;
990
0
  }
991
54
  return ID_MATCH_NONE;
992
54
}
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
10.2k
{
1025
10.2k
  private_identification_t *other_priv = (private_identification_t*)other;
1026
10.2k
  chunk_t encoded = other->get_encoding(other);
1027
10.2k
  u_int len = encoded.len;
1028
1029
10.2k
  if (other->get_type(other) == ID_ANY)
1030
0
  {
1031
0
    return ID_MATCH_ANY;
1032
0
  }
1033
10.2k
  if (this->type != other->get_type(other))
1034
6.21k
  {
1035
6.21k
    return ID_MATCH_NONE;
1036
6.21k
  }
1037
3.99k
  if (other_priv->regex)
1038
0
  {
1039
0
    return matches_regex(this, other_priv);
1040
0
  }
1041
  /* try a equals check first */
1042
3.99k
  if (equals_strcasecmp(this, other))
1043
376
  {
1044
376
    return ID_MATCH_PERFECT;
1045
376
  }
1046
3.61k
  if (len == 0 || this->encoded.len < len)
1047
120
  {
1048
120
    return ID_MATCH_NONE;
1049
120
  }
1050
1051
  /* check for single wildcard at the head of the string */
1052
3.49k
  if (*encoded.ptr == '*')
1053
0
  {
1054
    /* single asterisk matches any string */
1055
0
    if (len-- == 1)
1056
0
    { /* not better than ID_ANY */
1057
0
      return ID_MATCH_ANY;
1058
0
    }
1059
0
    if (strncasecmp(this->encoded.ptr + this->encoded.len - len,
1060
0
            encoded.ptr + 1, len) == 0)
1061
0
    {
1062
0
      return ID_MATCH_ONE_WILDCARD;
1063
0
    }
1064
0
  }
1065
3.49k
  return ID_MATCH_NONE;
1066
3.49k
}
1067
1068
METHOD(identification_t, matches_any, id_match_t,
1069
  private_identification_t *this, identification_t *other)
1070
0
{
1071
0
  if (other->get_type(other) == ID_ANY)
1072
0
  {
1073
0
    return ID_MATCH_ANY;
1074
0
  }
1075
0
  return ID_MATCH_NONE;
1076
0
}
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
5.85k
{
1085
5.85k
  private_identification_t *other_priv = (private_identification_t*)other;
1086
5.85k
  int wc;
1087
1088
5.85k
  if (other->get_type(other) == ID_ANY)
1089
0
  {
1090
0
    return ID_MATCH_ANY;
1091
0
  }
1092
1093
5.85k
  if (this->type == other->get_type(other))
1094
4.93k
  {
1095
4.93k
    if (other_priv->regex)
1096
0
    {
1097
0
      return matches_regex(this, other_priv);
1098
0
    }
1099
4.93k
    else if (match(this->encoded, other->get_encoding(other), &wc))
1100
27
    {
1101
27
      wc = min(wc, ID_MATCH_ONE_WILDCARD - ID_MATCH_MAX_WILDCARDS);
1102
27
      return ID_MATCH_PERFECT - wc;
1103
27
    }
1104
4.93k
  }
1105
5.82k
  return ID_MATCH_NONE;
1106
5.85k
}
1107
1108
METHOD(identification_t, matches_dn, id_match_t,
1109
  private_identification_t *this, identification_t *other)
1110
5.85k
{
1111
5.85k
  return matches_dn_internal(this, other, compare_dn);
1112
5.85k
}
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
32
{
1131
32
  uint8_t i, byte, netbits = 0;
1132
1133
409
  for (i = 0; i < address_size; i++)
1134
388
  {
1135
388
    byte = netmask[i];
1136
1137
388
    if (byte == 0x00)
1138
11
    {
1139
11
      break;
1140
11
    }
1141
377
    if (byte == 0xff)
1142
37
    {
1143
37
      netbits += 8;
1144
37
    }
1145
340
    else
1146
340
    {
1147
674
      while (byte & 0x80)
1148
334
      {
1149
334
        netbits++;
1150
334
        byte <<= 1;
1151
334
      }
1152
340
    }
1153
377
  }
1154
32
  return netbits;
1155
32
}
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
0
{
1332
0
  chunk_t other_encoding;
1333
0
  uint8_t *network, *netmask, *other_network, *other_netmask;
1334
1335
0
  other_encoding = other->get_encoding(other);
1336
0
  if (this->encoded.len != 2 * address_size ||
1337
0
    other_encoding.len != 2 * address_size)
1338
0
  {
1339
0
    return ID_MATCH_NONE;
1340
0
  }
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
0
}
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
0
{
1423
0
  chunk_t other_encoding;
1424
0
  uint8_t *from, *to, *other_from, *other_to;
1425
1426
0
  other_encoding = other->get_encoding(other);
1427
0
  if (this->encoded.len != 2 * address_size ||
1428
0
    other_encoding.len != 2 * address_size)
1429
0
  {
1430
0
    return ID_MATCH_NONE;
1431
0
  }
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
0
}
1438
1439
METHOD(identification_t, matches_range, id_match_t,
1440
  private_identification_t *this, identification_t *other)
1441
165
{
1442
165
  id_type_t other_type;
1443
165
  uint8_t address_size = 0;
1444
1445
165
  other_type = other->get_type(other);
1446
165
  if (other_type == ID_ANY)
1447
0
  {
1448
0
    return ID_MATCH_ANY;
1449
0
  }
1450
165
  if (this->type == other_type &&
1451
0
    chunk_equals(this->encoded, other->get_encoding(other)))
1452
0
  {
1453
0
    return ID_MATCH_PERFECT;
1454
0
  }
1455
165
  if (other_type == ID_IPV4_ADDR &&
1456
0
    (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
165
  else if (other_type == ID_IPV6_ADDR &&
1461
0
      (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
165
  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
165
  if (other_type == ID_IPV4_ADDR_SUBNET &&
1474
0
    (this->type == ID_IPV4_ADDR || this->type == ID_IPV4_ADDR_SUBNET ||
1475
0
     this->type == ID_IPV4_ADDR_RANGE))
1476
0
  {
1477
0
    address_size = sizeof(struct in_addr);
1478
0
  }
1479
165
  else if (other_type == ID_IPV6_ADDR_SUBNET &&
1480
0
      (this->type == ID_IPV6_ADDR || this->type == ID_IPV6_ADDR_SUBNET ||
1481
0
       this->type == ID_IPV6_ADDR_RANGE))
1482
0
  {
1483
0
    address_size = sizeof(struct in6_addr);
1484
0
  }
1485
165
  if (address_size)
1486
0
  {
1487
0
    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
0
    else if (this->type == ID_IPV4_ADDR_SUBNET || this->type == ID_IPV6_ADDR_SUBNET)
1492
0
    {
1493
0
      return matches_subnet_to_subnet(this, other, address_size);
1494
0
    }
1495
0
    return matches_range_to_subnet(this, other, address_size);
1496
0
  }
1497
165
  if (other_type == ID_IPV4_ADDR_RANGE &&
1498
0
    (this->type == ID_IPV4_ADDR || this->type == ID_IPV4_ADDR_SUBNET ||
1499
0
     this->type == ID_IPV4_ADDR_RANGE))
1500
0
  {
1501
0
    address_size = sizeof(struct in_addr);
1502
0
  }
1503
165
  else if (other_type == ID_IPV6_ADDR_RANGE &&
1504
0
      (this->type == ID_IPV6_ADDR || this->type == ID_IPV6_ADDR_SUBNET ||
1505
0
       this->type == ID_IPV6_ADDR_RANGE))
1506
0
  {
1507
0
    address_size = sizeof(struct in6_addr);
1508
0
  }
1509
165
  if (address_size)
1510
0
  {
1511
0
    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
0
    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
0
    return matches_range_to_range(this, other, address_size);
1520
0
  }
1521
165
  return ID_MATCH_NONE;
1522
165
}
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
479
{
1529
479
  chunk_t proper;
1530
479
  char *pos;
1531
479
  uint8_t address_size;
1532
479
  size_t len;
1533
479
  int written;
1534
1535
479
  if (this->regex)
1536
0
  {
1537
0
    snprintf(buf, BUF_LEN, "%s", this->encoded.ptr);
1538
0
    return;
1539
0
  }
1540
1541
479
  switch (this->type)
1542
479
  {
1543
0
    case ID_ANY:
1544
0
      snprintf(buf, BUF_LEN, "%%any");
1545
0
      break;
1546
0
    case ID_IPV4_ADDR:
1547
0
      if (this->encoded.len < sizeof(struct in_addr) ||
1548
0
        inet_ntop(AF_INET, this->encoded.ptr, buf, BUF_LEN) == NULL)
1549
0
      {
1550
0
        snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR)");
1551
0
      }
1552
0
      break;
1553
0
    case ID_IPV4_ADDR_SUBNET:
1554
0
      address_size = sizeof(struct in_addr);
1555
0
      if (this->encoded.len < 2 * address_size ||
1556
0
        inet_ntop(AF_INET, this->encoded.ptr, buf, BUF_LEN) == NULL)
1557
0
      {
1558
0
        snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR_SUBNET)");
1559
0
        break;
1560
0
      }
1561
0
      written = strlen(buf);
1562
0
      snprintf(buf + written, BUF_LEN - written, "/%d",
1563
0
           netmask_to_cidr(this->encoded.ptr + address_size,
1564
0
                             address_size));
1565
0
      break;
1566
0
    case ID_IPV4_ADDR_RANGE:
1567
0
      address_size = sizeof(struct in_addr);
1568
0
      if (this->encoded.len < 2 * address_size ||
1569
0
        inet_ntop(AF_INET, this->encoded.ptr, buf, BUF_LEN) == NULL)
1570
0
      {
1571
0
        snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR_RANGE)");
1572
0
        break;
1573
0
      }
1574
0
      written = strlen(buf);
1575
0
      pos = buf + written;
1576
0
      len = BUF_LEN - written;
1577
0
      written = snprintf(pos, len, "-");
1578
0
      if (written < 0 || written >= len ||
1579
0
          inet_ntop(AF_INET, this->encoded.ptr + address_size,
1580
0
              pos + written, len - written) == NULL)
1581
0
      {
1582
0
        snprintf(buf, BUF_LEN, "(invalid ID_IPV4_ADDR_RANGE)");
1583
0
      }
1584
0
      break;
1585
0
    case ID_IPV6_ADDR:
1586
0
      if (this->encoded.len < sizeof(struct in6_addr) ||
1587
0
        inet_ntop(AF_INET6, this->encoded.ptr, buf, BUF_LEN) == NULL)
1588
0
      {
1589
0
        snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR)");
1590
0
      }
1591
0
      break;
1592
32
    case ID_IPV6_ADDR_SUBNET:
1593
32
      address_size = sizeof(struct in6_addr);
1594
32
      if (this->encoded.len < 2 * address_size ||
1595
32
        inet_ntop(AF_INET6, this->encoded.ptr, buf, BUF_LEN) == NULL)
1596
0
      {
1597
0
        snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR_SUBNET)");
1598
0
      }
1599
32
      else
1600
32
      {
1601
32
        written = strlen(buf);
1602
32
        snprintf(buf + written, BUF_LEN - written, "/%d",
1603
32
             netmask_to_cidr(this->encoded.ptr + address_size,
1604
32
                               address_size));
1605
32
      }
1606
32
      break;
1607
0
    case ID_IPV6_ADDR_RANGE:
1608
0
      address_size = sizeof(struct in6_addr);
1609
0
      if (this->encoded.len < 2 * address_size ||
1610
0
        inet_ntop(AF_INET6, this->encoded.ptr, buf, BUF_LEN) == NULL)
1611
0
      {
1612
0
        snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR_RANGE)");
1613
0
        break;
1614
0
      }
1615
0
      written = strlen(buf);
1616
0
      pos = buf + written;
1617
0
      len = BUF_LEN - written;
1618
0
      written = snprintf(pos, len, "-");
1619
0
      if (written < 0 || written >= len ||
1620
0
          inet_ntop(AF_INET6, this->encoded.ptr + address_size,
1621
0
              pos + written, len - written) == NULL)
1622
0
      {
1623
0
        snprintf(buf, BUF_LEN, "(invalid ID_IPV6_ADDR_RANGE)");
1624
0
      }
1625
0
      break;
1626
16
    case ID_FQDN:
1627
19
    case ID_RFC822_ADDR:
1628
447
    case ID_DER_ASN1_GN_URI:
1629
447
      chunk_printable(this->encoded, &proper, '?');
1630
447
      snprintf(buf, BUF_LEN, "%.*s", (int)proper.len, proper.ptr);
1631
447
      chunk_free(&proper);
1632
447
      break;
1633
0
    case ID_DER_ASN1_DN:
1634
0
      dntoa(this->encoded, buf, BUF_LEN);
1635
0
      break;
1636
0
    case ID_DER_ASN1_GN:
1637
0
      snprintf(buf, BUF_LEN, "(ASN.1 general name)");
1638
0
      break;
1639
0
    case ID_KEY_ID:
1640
0
      if (chunk_printable(this->encoded, NULL, '?') &&
1641
0
        this->encoded.len != HASH_SIZE_SHA1)
1642
0
      { /* fully printable, use ascii version */
1643
0
        snprintf(buf, BUF_LEN, "%.*s", (int)this->encoded.len,
1644
0
             this->encoded.ptr);
1645
0
      }
1646
0
      else
1647
0
      { /* not printable, hex dump */
1648
0
        snprintf(buf, BUF_LEN, "%#B", &this->encoded);
1649
0
      }
1650
0
      break;
1651
0
    default:
1652
0
      snprintf(buf, BUF_LEN, "(unknown ID type: %d)", this->type);
1653
0
      break;
1654
479
  }
1655
479
}
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
479
{
1663
479
  private_identification_t *this = *((private_identification_t**)(args[0]));
1664
479
  char buf[BUF_LEN];
1665
1666
479
  if (!this)
1667
0
  {
1668
0
    return print_in_hook(data, "%*s", spec->width, "(null)");
1669
0
  }
1670
1671
479
  identity_to_string(this, buf);
1672
1673
479
  if (spec->minus)
1674
0
  {
1675
0
    return print_in_hook(data, "%-*s", spec->width, buf);
1676
0
  }
1677
479
  return print_in_hook(data, "%*s", spec->width, buf);
1678
479
}
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
6.38k
{
1716
6.38k
  private_identification_t *clone = malloc_thing(private_identification_t);
1717
1718
6.38k
  memcpy(clone, this, sizeof(private_identification_t));
1719
6.38k
  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
6.38k
  else
1726
6.38k
  {
1727
6.38k
    clone->encoded = chunk_clone(this->encoded);
1728
6.38k
  }
1729
6.38k
  return &clone->public;
1730
6.38k
}
1731
1732
METHOD(identification_t, destroy, void,
1733
  private_identification_t *this)
1734
29.1k
{
1735
29.1k
  chunk_free(&this->encoded);
1736
29.1k
  if (this->regex)
1737
0
  {
1738
0
    regfree(this->regex);
1739
0
    free(this->regex);
1740
0
  }
1741
29.1k
  free(this);
1742
29.1k
}
1743
1744
/**
1745
 * Generic constructor used for the other constructors.
1746
 */
1747
static private_identification_t *identification_create(id_type_t type)
1748
22.7k
{
1749
22.7k
  private_identification_t *this;
1750
22.7k
  char *rdn_matching;
1751
1752
22.7k
  INIT(this,
1753
22.7k
    .public = {
1754
22.7k
      .get_encoding = _get_encoding,
1755
22.7k
      .get_type = _get_type,
1756
22.7k
      .create_part_enumerator = _create_part_enumerator,
1757
22.7k
      .clone = _clone_,
1758
22.7k
      .destroy = _destroy,
1759
22.7k
    },
1760
22.7k
    .type = type,
1761
22.7k
  );
1762
1763
22.7k
  switch (type)
1764
22.7k
  {
1765
0
    case ID_ANY:
1766
0
      this->public.hash = _hash_binary;
1767
0
      this->public.equals = _equals_binary;
1768
0
      this->public.matches = _matches_any;
1769
0
      this->public.contains_wildcards = (void*)return_true;
1770
0
      break;
1771
10.9k
    case ID_FQDN:
1772
10.9k
    case ID_RFC822_ADDR:
1773
10.9k
      this->public.hash = _hash_binary;
1774
10.9k
      this->public.equals = _equals_strcasecmp;
1775
10.9k
      this->public.matches = _matches_string;
1776
10.9k
      this->public.contains_wildcards = _contains_wildcards_memchr;
1777
10.9k
      break;
1778
10.0k
    case ID_DER_ASN1_DN:
1779
10.0k
      this->public.hash = _hash_dn;
1780
10.0k
      this->public.equals = _equals_dn;
1781
10.0k
      this->public.matches = _matches_dn;
1782
10.0k
      this->public.contains_wildcards = _contains_wildcards_dn;
1783
      /* check for more relaxed matching config */
1784
10.0k
      rdn_matching = lib->settings->get_str(lib->settings,
1785
10.0k
                      "%s.rdn_matching", NULL, lib->ns);
1786
10.0k
      if (streq("reordered", rdn_matching))
1787
0
      {
1788
0
        this->public.matches = _matches_dn_reordered;
1789
0
      }
1790
10.0k
      else if (streq("relaxed", rdn_matching))
1791
0
      {
1792
0
        this->public.matches = _matches_dn_relaxed;
1793
0
      }
1794
10.0k
      break;
1795
166
    case ID_IPV4_ADDR:
1796
186
    case ID_IPV6_ADDR:
1797
189
    case ID_IPV4_ADDR_SUBNET:
1798
261
    case ID_IPV6_ADDR_SUBNET:
1799
261
    case ID_IPV4_ADDR_RANGE:
1800
261
    case ID_IPV6_ADDR_RANGE:
1801
261
      this->public.hash = _hash_binary;
1802
261
      this->public.equals = _equals_binary;
1803
261
      this->public.matches = _matches_range;
1804
261
      this->public.contains_wildcards = (void*)return_false;
1805
261
      break;
1806
1.59k
    default:
1807
1.59k
      this->public.hash = _hash_binary;
1808
1.59k
      this->public.equals = _equals_binary;
1809
1.59k
      this->public.matches = _matches_binary;
1810
1.59k
      this->public.contains_wildcards = (void*)return_false;
1811
1.59k
      break;
1812
22.7k
  }
1813
22.7k
  return this;
1814
22.7k
}
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
6.38k
{
1847
6.38k
  private_identification_t *this;
1848
6.38k
  int i;
1849
1850
108k
  for (i = 0; i < countof(prefixes); i++)
1851
102k
  {
1852
102k
    if (strcasepfx(str, prefixes[i].str))
1853
0
    {
1854
0
      this = identification_create(prefixes[i].type);
1855
0
      str += strlen(prefixes[i].str);
1856
1857
0
      if (*str == '#')
1858
0
      {
1859
0
        this->encoded = chunk_from_hex(chunk_from_str(str + 1), NULL);
1860
0
      }
1861
0
      else
1862
0
      {
1863
0
        this->encoded = chunk_clone(chunk_from_str(str));
1864
0
      }
1865
1866
0
      if (prefixes[i].type == ID_DER_ASN1_GN &&
1867
0
        strcasepfx(prefixes[i].str, "xmppaddr:"))
1868
0
      {
1869
0
        this->encoded = asn1_wrap(ASN1_CONTEXT_C_0, "mm",
1870
0
                  asn1_build_known_oid(OID_XMPP_ADDR),
1871
0
                  asn1_wrap(ASN1_CONTEXT_C_0, "m",
1872
0
                    asn1_wrap(ASN1_UTF8STRING, "m",
1873
0
                      this->encoded)));
1874
0
      }
1875
0
      return this;
1876
0
    }
1877
102k
  }
1878
6.38k
  return NULL;
1879
6.38k
}
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
6.38k
{
1889
6.38k
  private_identification_t *this;
1890
6.38k
  u_long type;
1891
1892
6.38k
  if (*str++ != '{')
1893
6.38k
  {
1894
6.38k
    return NULL;
1895
6.38k
  }
1896
6.38k
  errno = 0;
1897
0
  type = strtoul(str, &str, 0);
1898
0
  if (errno || *str++ != '}' || *str++ != ':')
1899
0
  {
1900
0
    return NULL;
1901
0
  }
1902
0
  this = identification_create(type);
1903
0
  if (*str == '#')
1904
0
  {
1905
0
    this->encoded = chunk_from_hex(chunk_from_str(str + 1), NULL);
1906
0
  }
1907
0
  else
1908
0
  {
1909
0
    this->encoded = chunk_clone(chunk_from_str(str));
1910
0
  }
1911
0
  return this;
1912
0
}
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
6.38k
{
1920
6.38k
  private_identification_t *this;
1921
6.38k
  uint8_t encoding[32];
1922
6.38k
  uint8_t *str, *pos, *address, *to_address, *netmask;
1923
6.38k
  size_t address_size;
1924
6.38k
  int bits, bytes, i;
1925
6.38k
  bool has_subnet = FALSE, has_range = FALSE;
1926
1927
6.38k
  address = encoding;
1928
6.38k
  address_size = is_ipv4 ? sizeof(struct in_addr) : sizeof(struct in6_addr);
1929
1930
6.38k
  str = strdup(string);
1931
6.38k
  pos = strchr(str, '/');
1932
6.38k
  if (pos)
1933
0
  { /* separate IP address from optional netmask */
1934
1935
0
    *pos = '\0';
1936
0
    has_subnet = TRUE;
1937
0
  }
1938
6.38k
  else
1939
6.38k
  {
1940
6.38k
    pos = strchr(str, '-');
1941
6.38k
    if (pos)
1942
0
    { /* separate lower address from upper address of IP range */
1943
0
      *pos = '\0';
1944
0
      has_range = TRUE;
1945
0
    }
1946
6.38k
  }
1947
1948
6.38k
  if (inet_pton(is_ipv4 ? AF_INET : AF_INET6, str, address) != 1)
1949
6.38k
  {
1950
6.38k
    free(str);
1951
6.38k
    return NULL;
1952
6.38k
  }
1953
1954
0
  if (has_subnet)
1955
0
  { /* is IP subnet */
1956
0
    bits = atoi(pos + 1);
1957
0
    if (bits > 8 * address_size)
1958
0
    {
1959
0
      free(str);
1960
0
      return NULL;
1961
0
    }
1962
0
    bytes = bits / 8;
1963
0
    bits -= 8 * bytes;
1964
0
    netmask = encoding + address_size;
1965
1966
0
    for (i = 0; i < address_size; i++)
1967
0
    {
1968
0
      if (bytes)
1969
0
      {
1970
0
        *netmask = 0xff;
1971
0
        bytes--;
1972
0
      }
1973
0
      else if (bits)
1974
0
      {
1975
0
        *netmask = 0xff << (8 - bits);
1976
0
        bits = 0;
1977
0
      }
1978
0
      else
1979
0
      {
1980
0
        *netmask = 0x00;
1981
0
      }
1982
0
      *address++ &= *netmask++;
1983
0
    }
1984
0
    this = identification_create(is_ipv4 ? ID_IPV4_ADDR_SUBNET :
1985
0
                         ID_IPV6_ADDR_SUBNET);
1986
0
    this->encoded = chunk_clone(chunk_create(encoding, 2 * address_size));
1987
0
  }
1988
0
  else if (has_range)
1989
0
  { /* is IP range */
1990
0
    to_address = encoding + address_size;
1991
1992
0
    if (inet_pton(is_ipv4 ? AF_INET : AF_INET6, pos + 1, to_address) != 1)
1993
0
    {
1994
0
      free(str);
1995
0
      return NULL;
1996
0
    }
1997
0
    for (i = 0; i < address_size; i++)
1998
0
    {
1999
0
      if (address[i] != to_address[i])
2000
0
      {
2001
0
        if (address[i] > to_address[i])
2002
0
        {
2003
0
          free(str);
2004
0
          return NULL;
2005
0
        }
2006
0
        break;
2007
0
      }
2008
0
    }
2009
0
    this = identification_create(is_ipv4 ? ID_IPV4_ADDR_RANGE :
2010
0
                         ID_IPV6_ADDR_RANGE);
2011
0
    this->encoded = chunk_clone(chunk_create(encoding, 2 * address_size));
2012
0
  }
2013
0
  else
2014
0
  { /* is IP host address */
2015
0
    this = identification_create(is_ipv4 ? ID_IPV4_ADDR : ID_IPV6_ADDR);
2016
0
    this->encoded = chunk_clone(chunk_create(encoding, address_size));
2017
0
  }
2018
0
  free(str);
2019
2020
0
  return this;
2021
0
}
2022
2023
/*
2024
 * Described in header.
2025
 */
2026
identification_t *identification_create_from_string(char *string)
2027
6.38k
{
2028
6.38k
  private_identification_t *this;
2029
6.38k
  chunk_t encoded;
2030
2031
6.38k
  if (string == NULL)
2032
0
  {
2033
0
    string = "%any";
2034
0
  }
2035
6.38k
  this = create_from_string_with_prefix_type(string);
2036
6.38k
  if (this)
2037
0
  {
2038
0
    return &this->public;
2039
0
  }
2040
6.38k
  this = create_from_string_with_num_type(string);
2041
6.38k
  if (this)
2042
0
  {
2043
0
    return &this->public;
2044
0
  }
2045
6.38k
  if (strchr(string, '=') != NULL)
2046
0
  {
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
0
    if (atodn(string, &encoded) == SUCCESS)
2051
0
    {
2052
0
      this = identification_create(ID_DER_ASN1_DN);
2053
0
      this->encoded = encoded;
2054
0
    }
2055
0
    else
2056
0
    {
2057
0
      this = identification_create(ID_KEY_ID);
2058
0
      this->encoded = chunk_clone(chunk_from_str(string));
2059
0
    }
2060
0
    return &this->public;
2061
0
  }
2062
6.38k
  else if (strchr(string, '@') == NULL)
2063
6.38k
  {
2064
6.38k
    if (streq(string, "")
2065
6.38k
    ||  streq(string, "%any")
2066
6.38k
    ||  streq(string, "%any6")
2067
6.38k
    ||  streq(string, "0.0.0.0")
2068
6.38k
    ||  streq(string, "*")
2069
6.38k
    ||  streq(string, "::")
2070
6.38k
    ||  streq(string, "0::0"))
2071
0
    {
2072
      /* any ID will be accepted */
2073
0
      this = identification_create(ID_ANY);
2074
0
      return &this->public;
2075
0
    }
2076
6.38k
    else
2077
6.38k
    {
2078
6.38k
      if (strchr(string, ':') == NULL)
2079
6.38k
      {
2080
        /* IPv4 address or subnet */
2081
6.38k
        this = create_ip_address_from_string(string, TRUE);
2082
6.38k
        if (!this)
2083
6.38k
        { /* not IPv4, mostly FQDN */
2084
6.38k
          this = identification_create(ID_FQDN);
2085
6.38k
          this->encoded = chunk_clone(chunk_from_str(string));
2086
6.38k
        }
2087
6.38k
        return &this->public;
2088
6.38k
      }
2089
0
      else
2090
0
      {
2091
        /* IPv6 address or subnet */
2092
0
        this = create_ip_address_from_string(string, FALSE);
2093
0
        if (!this)
2094
0
        { /* not IPv4/6 fallback to KEY_ID */
2095
0
          this = identification_create(ID_KEY_ID);
2096
0
          this->encoded = chunk_clone(chunk_from_str(string));
2097
0
        }
2098
0
        return &this->public;
2099
0
      }
2100
6.38k
    }
2101
6.38k
  }
2102
0
  else
2103
0
  {
2104
0
    if (*string == '@')
2105
0
    {
2106
0
      string++;
2107
0
      if (*string == '#')
2108
0
      {
2109
0
        this = identification_create(ID_KEY_ID);
2110
0
        this->encoded = chunk_from_hex(chunk_from_str(string + 1), NULL);
2111
0
        return &this->public;
2112
0
      }
2113
0
      else if (*string == '@')
2114
0
      {
2115
0
        this = identification_create(ID_RFC822_ADDR);
2116
0
        this->encoded = chunk_clone(chunk_from_str(string + 1));
2117
0
        return &this->public;
2118
0
      }
2119
0
      else
2120
0
      {
2121
0
        this = identification_create(ID_FQDN);
2122
0
        this->encoded = chunk_clone(chunk_from_str(string));
2123
0
        return &this->public;
2124
0
      }
2125
0
    }
2126
0
    else
2127
0
    {
2128
0
      this = identification_create(ID_RFC822_ADDR);
2129
0
      this->encoded = chunk_clone(chunk_from_str(string));
2130
0
      return &this->public;
2131
0
    }
2132
0
  }
2133
6.38k
}
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
0
{
2199
0
  char buf[data.len + 1];
2200
2201
0
  if (is_asn1(data) && is_valid_dn(data))
2202
0
  {
2203
0
    return identification_create_from_encoding(ID_DER_ASN1_DN, data);
2204
0
  }
2205
0
  else
2206
0
  {
2207
    /* use string constructor */
2208
0
    snprintf(buf, sizeof(buf), "%.*s", (int)data.len, data.ptr);
2209
0
    return identification_create_from_string(buf);
2210
0
  }
2211
0
}
2212
2213
/*
2214
 * Described in header.
2215
 */
2216
identification_t *identification_create_from_encoding(id_type_t type,
2217
                            chunk_t encoded)
2218
16.4k
{
2219
16.4k
  private_identification_t *this = identification_create(type);
2220
2221
  /* apply encoded chunk */
2222
16.4k
  if (type != ID_ANY)
2223
16.4k
  {
2224
16.4k
    this->encoded = chunk_clone(encoded);
2225
16.4k
  }
2226
16.4k
  return &(this->public);
2227
16.4k
}
2228
2229
/*
2230
 * Described in header.
2231
 */
2232
identification_t *identification_create_from_sockaddr(sockaddr_t *sockaddr)
2233
0
{
2234
0
  switch (sockaddr->sa_family)
2235
0
  {
2236
0
    case AF_INET:
2237
0
    {
2238
0
      struct in_addr *addr = &(((struct sockaddr_in*)sockaddr)->sin_addr);
2239
2240
0
      return identification_create_from_encoding(ID_IPV4_ADDR,
2241
0
          chunk_create((u_char*)addr, sizeof(struct in_addr)));
2242
0
    }
2243
0
    case AF_INET6:
2244
0
    {
2245
0
      struct in6_addr *addr = &(((struct sockaddr_in6*)sockaddr)->sin6_addr);
2246
2247
0
      return identification_create_from_encoding(ID_IPV6_ADDR,
2248
0
          chunk_create((u_char*)addr, sizeof(struct in6_addr)));
2249
0
    }
2250
0
    default:
2251
0
    {
2252
0
      private_identification_t *this = identification_create(ID_ANY);
2253
2254
0
      return &(this->public);
2255
0
    }
2256
0
  }
2257
0
}