The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
util.c
Go to the documentation of this file.
1 /*
2  * This program is is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or (at
5  * your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: 9eb629a2fd782018dad9fbf70467a9dc29a9a742 $
19  * @file lib/ldap/util.c
20  * @brief Utility functions to escape and parse DNs
21  *
22  * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23  * @copyright 2017 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
24  * @copyright 2017 The FreeRADIUS Server Project.
25  */
26 RCSID("$Id: 9eb629a2fd782018dad9fbf70467a9dc29a9a742 $")
27 
29 
30 #include <freeradius-devel/ldap/base.h>
31 #include <freeradius-devel/util/base16.h>
32 
33 #include <stdarg.h>
34 #include <ctype.h>
35 
36 static const char specials[] = ",+\"\\<>;*=()";
37 static const char hextab[] = "0123456789abcdef";
38 static const bool escapes[UINT8_MAX + 1] = {
39  [' '] = true,
40  ['#'] = true,
41  ['='] = true,
42  ['"'] = true,
43  ['+'] = true,
44  [','] = true,
45  [';'] = true,
46  ['<'] = true,
47  ['>'] = true,
48  ['\''] = true
49 };
50 
51 /** Converts "bad" strings into ones which are safe for LDAP
52  *
53  * @note RFC 4515 says filter strings can only use the @verbatim <hex><hex> @endverbatim
54  * format, whereas RFC 4514 indicates that some chars in DNs, may be escaped simply
55  * with a backslash. For simplicity, we always use the hex escape sequences.
56  * In other areas where we're doing DN comparison, the DNs need to be normalised first
57  * so that they both use only hex escape sequences.
58  *
59  * @note This is a callback for xlat operations.
60  *
61  * Will escape any characters in input strings that would cause the string to be interpreted
62  * as part of a DN and or filter. Escape sequence is @verbatim <hex><hex> @endverbatim.
63  *
64  * @param request The current request.
65  * @param out Pointer to output buffer.
66  * @param outlen Size of the output buffer.
67  * @param in Raw unescaped string.
68  * @param arg Any additional arguments (unused).
69  */
70 size_t fr_ldap_uri_escape_func(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
71 {
72  size_t left = outlen;
73 
74  if ((*in == ' ') || (*in == '#')) goto encode;
75 
76  while (*in) {
77  /*
78  * Encode unsafe characters.
79  */
80  if (memchr(specials, *in, sizeof(specials) - 1)) {
81  encode:
82  /*
83  * Only 3 or less bytes available.
84  */
85  if (left <= 3) break;
86 
87  *out++ = '\\';
88  *out++ = hextab[(*in >> 4) & 0x0f];
89  *out++ = hextab[*in & 0x0f];
90  in++;
91  left -= 3;
92 
93  continue;
94  }
95 
96  if (left <= 1) break;
97 
98  /*
99  * Doesn't need encoding
100  */
101  *out++ = *in++;
102  left--;
103  }
104 
105  *out = '\0';
106 
107  return outlen - left;
108 }
109 
111 {
112  fr_sbuff_t sbuff;
113  fr_sbuff_uctx_talloc_t sbuff_ctx;
114  size_t len;
115  fr_value_box_entry_t entry;
116 
117  if (fr_value_box_is_safe_for(vb, fr_ldap_box_escape)) return 0;
118 
119  if ((vb->type != FR_TYPE_STRING) && (fr_value_box_cast_in_place(vb, vb, FR_TYPE_STRING, NULL) < 0)) {
121  return -1;
122  }
123 
124  if (!fr_sbuff_init_talloc(vb, &sbuff, &sbuff_ctx, vb->vb_length * 3, vb->vb_length * 3)) {
125  fr_strerror_printf_push("Failed to allocate buffer for escaped filter");
126  return -1;
127  }
128 
129  len = fr_ldap_uri_escape_func(NULL, fr_sbuff_buff(&sbuff), vb->vb_length * 3 + 1, vb->vb_strvalue, NULL);
130 
131  /*
132  * If the returned length is unchanged, the value was already safe
133  */
134  if (len == vb->vb_length) {
135  talloc_free(fr_sbuff_buff(&sbuff));
136  } else {
137  entry = vb->entry;
138  fr_sbuff_trim_talloc(&sbuff, len);
140  fr_value_box_strdup_shallow(vb, NULL, fr_sbuff_buff(&sbuff), vb->tainted);
141  vb->entry = entry;
142  }
143 
145 
146  return 0;
147 }
148 
149 /** Converts escaped DNs and filter strings into normal
150  *
151  * @note RFC 4515 says filter strings can only use the @verbatim <hex><hex> @endverbatim
152  * format, whereas RFC 4514 indicates that some chars in DNs, may be escaped simply
153  * with a backslash..
154  *
155  * Will unescape any special characters in strings, or @verbatim <hex><hex> @endverbatim
156  * sequences.
157  *
158  * @param request The current request.
159  * @param out Pointer to output buffer.
160  * @param outlen Size of the output buffer.
161  * @param in Escaped string string.
162  * @param arg Any additional arguments (unused).
163  */
164 size_t fr_ldap_uri_unescape_func(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
165 {
166  char const *p;
167  char *c1, *c2, c3;
168  size_t freespace = outlen;
169 
170  if (outlen <= 1) return 0;
171 
172  p = in;
173  while (*p && (--freespace > 0)) {
174  if (*p != '\\') {
175  next:
176  *out++ = *p++;
177  continue;
178  }
179 
180  p++;
181 
182  /* It's an escaped special, just remove the slash */
183  if (memchr(specials, *p, sizeof(specials) - 1)) {
184  *out++ = *p++;
185  continue;
186  }
187 
188  /* Is a hex sequence */
189  if (!(c1 = memchr(hextab, tolower(p[0]), 16)) ||
190  !(c2 = memchr(hextab, tolower(p[1]), 16))) goto next;
191  c3 = ((c1 - hextab) << 4) + (c2 - hextab);
192 
193  *out++ = c3;
194  p += 2;
195  }
196 
197  *out = '\0';
198 
199  return outlen - freespace;
200 }
201 
202 
203 /** Check whether a string looks like a DN
204  *
205  * @param[in] in Str to check.
206  * @param[in] inlen Length of string to check.
207  * @return
208  * - true if string looks like a DN.
209  * - false if string does not look like DN.
210  */
211 bool fr_ldap_util_is_dn(char const *in, size_t inlen)
212 {
213  char const *p;
214 
215  char want = '=';
216  bool too_soon = true;
217  int comp = 1;
218 
219  for (p = in; inlen > 0; p++, inlen--) {
220  if (p[0] == '\\') {
221  char c;
222 
223  too_soon = false;
224 
225  /*
226  * Invalid escape sequence, not a DN
227  */
228  if (inlen < 2) return false;
229 
230  /*
231  * Double backslash, consume two chars
232  */
233  if (p[1] == '\\') {
234  inlen--;
235  p++;
236  continue;
237  }
238 
239  /*
240  * Special, consume two chars
241  */
242  if (escapes[(uint8_t) p[1]]) {
243  inlen -= 1;
244  p += 1;
245  continue;
246  }
247 
248  /*
249  * Invalid escape sequence, not a DN
250  */
251  if (inlen < 3) return false;
252 
253  /*
254  * Hex encoding, consume three chars
255  */
256  if (fr_base16_decode(NULL, &FR_DBUFF_TMP((uint8_t *) &c, 1), &FR_SBUFF_IN(p + 1, 2), false) == 1) {
257  inlen -= 2;
258  p += 2;
259  continue;
260  }
261 
262  /*
263  * Invalid escape sequence, not a DN
264  */
265  return false;
266  }
267 
268  switch (*p) {
269  case '=':
270  if (too_soon || (*p != want)) return false; /* Too soon after last , or = */
271  want = ',';
272  too_soon = true;
273  break;
274 
275  case ',':
276  if (too_soon || (*p != want)) return false; /* Too soon after last , or = */
277  want = '=';
278  too_soon = true;
279  comp++;
280  break;
281 
282  default:
283  too_soon = false;
284  break;
285  }
286  }
287 
288  /*
289  * If the string ended with , or =, or the number
290  * of components was less than 2
291  *
292  * i.e. we don't have <attr>=<val>,<attr>=<val>
293  */
294  if (too_soon || (comp < 2)) return false;
295 
296  return true;
297 }
298 
299 /** Parse a subset (just server side sort for now) of LDAP URL extensions
300  *
301  * @param[out] sss Array of LDAPControl * pointers to add controls to.
302  * @param[in] sss_len How many elements remain in the sss array.
303  * @param[in] extensions A NULL terminated array of extensions.
304  * @return
305  * - >0 the number of controls added.
306  * - 0 if no controls added.
307  * - -1 on failure.
308  */
309 int fr_ldap_parse_url_extensions(LDAPControl **sss, size_t sss_len, char *extensions[])
310 {
311  LDAPControl **sss_p = sss, **sss_end = sss_p + sss_len;
312  int i;
313 
314  if (!extensions) {
315  *sss_p = NULL;
316  return 0;
317  }
318 
319  /*
320  * Parse extensions in the LDAP URL
321  */
322  for (i = 0; extensions[i]; i++) {
323  char *p;
324  bool is_critical = false;
325 
326  p = extensions[i];
327  if (*p == '!') {
328  is_critical = true;
329  p++;
330  }
331 
332  /*
333  * Server side sort control
334  */
335  if (strncmp(p, "sss", 3) == 0) {
336  LDAPSortKey **keys;
337  int ret;
338 
339  p += 3;
340  p = strchr(p, '=');
341  if (!p) {
342  fr_strerror_const("Server side sort extension must be "
343  "in the format \"[!]sss=<key>[,key]\"");
344  return -1;
345  }
346  p++;
347 
348  ret = ldap_create_sort_keylist(&keys, p);
349  if (ret != LDAP_SUCCESS) {
350  fr_strerror_printf("Invalid server side sort value \"%s\": %s",
351  p, ldap_err2string(ret));
352  return -1;
353  }
354 
355  if (*sss_p) ldap_control_free(*sss_p);
356 
357  ret = ldap_create_sort_control(fr_ldap_handle_thread_local(), keys, is_critical ? 1 : 0, sss_p);
358  ldap_free_sort_keylist(keys);
359  if (ret != LDAP_SUCCESS) {
360  fr_strerror_printf("Failed creating server sort control: %s",
361  ldap_err2string(ret));
362  return -1;
363  }
364  sss_p++;
365 
366  continue;
367  }
368 
369  fr_strerror_printf("URL extension \"%s\" not supported", p);
370  return -1;
371  }
372 
373  *sss_p = NULL; /* Terminate */
374 
375  return (sss_end - sss_p);
376 }
377 
378 /** Convert a berval to a talloced string
379  *
380  * The ldap_get_values function is deprecated, and ldap_get_values_len
381  * does not guarantee the berval buffers it returns are \0 terminated.
382  *
383  * For some cases this is fine, for others we require a \0 terminated
384  * buffer (feeding DNs back into libldap for example).
385  *
386  * @param ctx to allocate in.
387  * @param in Berval to copy.
388  * @return \0 terminated buffer containing in->bv_val.
389  */
390 char *fr_ldap_berval_to_string(TALLOC_CTX *ctx, struct berval const *in)
391 {
392  char *out;
393 
394  out = talloc_array(ctx, char, in->bv_len + 1);
395  if (!out) return NULL;
396 
397  memcpy(out, in->bv_val, in->bv_len);
398  out[in->bv_len] = '\0';
399 
400  return out;
401 }
402 
403 /** Convert a berval to a talloced buffer
404  *
405  * @param ctx to allocate in.
406  * @param in Berval to copy.
407  * @return buffer containing in->bv_val.
408  */
409 uint8_t *fr_ldap_berval_to_bin(TALLOC_CTX *ctx, struct berval const *in)
410 {
411  uint8_t *out;
412 
413  out = talloc_array(ctx, uint8_t, in->bv_len);
414  if (!out) return NULL;
415 
416  memcpy(out, in->bv_val, in->bv_len);
417 
418  return out;
419 }
420 
421 /** Normalise escape sequences in a DN
422  *
423  * Characters in a DN can either be escaped as
424  * @verbatim <hex><hex> @endverbatim or @verbatim <special> @endverbatim
425  *
426  * The LDAP directory chooses how characters are escaped, which can make
427  * local comparisons of DNs difficult.
428  *
429  * Here we search for hex sequences that match special chars, and convert
430  * them to the @verbatim <special> @endverbatim form.
431  *
432  * @note the resulting output string will only ever be shorter than the
433  * input, so it's fine to use the same buffer for both out and in.
434  *
435  * @param out Where to write the normalised DN.
436  * @param in The input DN.
437  * @return The number of bytes written to out.
438  */
439 size_t fr_ldap_util_normalise_dn(char *out, char const *in)
440 {
441  char const *p;
442  char *o = out;
443 
444  for (p = in; *p != '\0'; p++) {
445  if (p[0] == '\\') {
446  char c = '\0';
447 
448  /*
449  * Double backslashes get processed specially
450  */
451  if (p[1] == '\\') {
452  p += 1;
453  *o++ = p[0];
454  *o++ = p[1];
455  continue;
456  }
457 
458  /*
459  * Hex encodings that have an alternative
460  * special encoding, get rewritten to the
461  * special encoding.
462  */
463  if (fr_base16_decode(NULL, &FR_DBUFF_TMP((uint8_t *) &c, 1), &FR_SBUFF_IN(p + 1, 2), false) == 1 &&
464  escapes[(uint8_t) c]) {
465  *o++ = '\\';
466  *o++ = c;
467  p += 2;
468  continue;
469  }
470  }
471  *o++ = *p;
472  }
473  *o = '\0';
474 
475  return o - out;
476 }
477 
478 /** Find the place at which the two DN strings diverge
479  *
480  * Returns the length of the non matching string in full.
481  *
482  * @param full DN.
483  * @param part Partial DN as returned by ldap_parse_result.
484  * @return
485  * - Length of the portion of full which wasn't matched
486  * - -1 on failure.
487  */
488 size_t fr_ldap_common_dn(char const *full, char const *part)
489 {
490  size_t f_len, p_len, i;
491 
492  if (!full) return -1;
493 
494  f_len = strlen(full);
495 
496  if (!part) return -1;
497 
498  p_len = strlen(part);
499  if (!p_len) return f_len;
500 
501  if ((f_len < p_len) || !f_len) return -1;
502 
503  for (i = 0; i < p_len; i++) if (part[p_len - i] != full[f_len - i]) return -1;
504 
505  return f_len - p_len;
506 }
507 
508 /** Combine filters and tokenize to a tmpl
509  *
510  * @param ctx To allocate combined filter in
511  * @param t_rules Rules for parsing combined filter.
512  * @param sub Array of subfilters (may contain NULLs).
513  * @param sublen Number of potential subfilters in array.
514  * @param out Where to write a pointer to the resulting tmpl.
515  * @return length of combined data.
516  */
517 int fr_ldap_filter_to_tmpl(TALLOC_CTX *ctx, tmpl_rules_t const *t_rules, char const **sub, size_t sublen, tmpl_t **out)
518 {
519  char *buffer = NULL;
520  char const *in = NULL;
521  ssize_t len = 0;
522  size_t i;
523  int cnt = 0;
524  tmpl_t *parsed;
525 
526  *out = NULL;
527 
528  /*
529  * Figure out how many filter elements we need to integrate
530  */
531  for (i = 0; i < sublen; i++) {
532  if (sub[i] && *sub[i]) {
533  in = sub[i];
534  cnt++;
535  len += strlen(sub[i]);
536  }
537  }
538 
539  if (!cnt) return 0;
540 
541  if (cnt > 1) {
542  /*
543  * Allocate a buffer large enough, allowing for (& ... ) plus trailing '\0'
544  */
545  buffer = talloc_array(ctx, char, len + 4);
546 
547  strcpy(buffer, "(&");
548  for (i = 0; i < sublen; i++) {
549  if (sub[i] && (*sub[i] != '\0')) {
550  strcat(buffer, sub[i]);
551  }
552  }
553  strcat(buffer, ")");
554  in = buffer;
555  }
556 
557  len = tmpl_afrom_substr(ctx, &parsed, &FR_SBUFF_IN(in, strlen(in)), T_DOUBLE_QUOTED_STRING, NULL, t_rules);
558 
560 
561  if (len < 0) {
562  EMARKER(in, -len, fr_strerror());
563  return -1;
564  }
565 
566  *out = parsed;
567  return 0;
568 }
569 
570 /** Check that a particular attribute is included in an attribute list
571  *
572  * @param[in] attrs list to check
573  * @param[in] attr to look for
574  * @return
575  * - 1 if attr is in list
576  * - 0 if attr is missing
577  * - -1 if checks not possible
578  */
579 int fr_ldap_attrs_check(char const **attrs, char const *attr)
580 {
581  size_t len, i;
582 
583  if (!attr) return -1;
584 
585  len = talloc_array_length(attrs);
586 
587  for (i = 0; i < len; i++) {
588  if (!attrs[i]) continue;
589  if (strcasecmp(attrs[i], attr) == 0) return 1;
590  if (strcasecmp(attrs[i], "*") == 0) return 1;
591  }
592 
593  return 0;
594 }
595 
596 /** Check an LDAP server entry in URL format is valid
597  *
598  * @param[in,out] handle_config LDAP handle config being built
599  * @param[in] server string to parse
600  * @param[in] cs in which the server is defined
601  * @return
602  * - 0 for valid server definition
603  * - -1 for invalid server definition
604  */
605 int fr_ldap_server_url_check(fr_ldap_config_t *handle_config, char const *server, CONF_SECTION const *cs)
606 {
607  LDAPURLDesc *ldap_url;
608  bool set_port_maybe = true;
609  int default_port = LDAP_PORT;
610  char *p, *url;
611  CONF_ITEM *ci = (CONF_ITEM *)cf_pair_find(cs, "server");
612 
613  if (ldap_url_parse(server, &ldap_url)) {
614  cf_log_err(ci, "Parsing LDAP URL \"%s\" failed", server);
615  ldap_url_error:
616  ldap_free_urldesc(ldap_url);
617  return -1;
618  }
619 
620  if (ldap_url->lud_dn && (ldap_url->lud_dn[0] != '\0')) {
621  cf_log_err(ci, "Base DN cannot be specified via server URL");
622  goto ldap_url_error;
623  }
624 
625  if (ldap_url->lud_attrs && ldap_url->lud_attrs[0]) {
626  cf_log_err(ci, "Attribute list cannot be speciried via server URL");
627  goto ldap_url_error;
628  }
629 
630  /*
631  * ldap_url_parse sets this to base by default.
632  */
633  if (ldap_url->lud_scope != LDAP_SCOPE_BASE) {
634  cf_log_err(ci, "Scope cannot be specified via server URL");
635  goto ldap_url_error;
636  }
637  ldap_url->lud_scope = -1; /* Otherwise LDAP adds ?base */
638 
639  /*
640  * The public ldap_url_parse function sets the default
641  * port, so we have to discover whether a port was
642  * included ourselves.
643  */
644  if ((p = strchr(server, ']')) && (p[1] == ':')) { /* IPv6 */
645  set_port_maybe = false;
646  } else if ((p = strchr(server, ':')) && (strchr(p+1, ':') != NULL)) { /* IPv4 */
647  set_port_maybe = false;
648  }
649 
650  /*
651  * Figure out the default port from the URL
652  */
653  if (ldap_url->lud_scheme) {
654  if (strcmp(ldap_url->lud_scheme, "ldaps") == 0) {
655  if (handle_config->start_tls == true) {
656  cf_log_err(ci, "ldap:s// scheme is not compatible with 'start_tls'");
657  goto ldap_url_error;
658  }
659  } else if (strcmp(ldap_url->lud_scheme, "ldapi") == 0) {
660  set_port_maybe = false;
661  }
662  }
663 
664  if (set_port_maybe) {
665  /*
666  * URL port overrides configured port.
667  */
668  ldap_url->lud_port = handle_config->port;
669 
670  /*
671  * If there's no URL port, then set it to the default
672  * this is so debugging messages show explicitly
673  * the port we're connecting to.
674  */
675  if (!ldap_url->lud_port) ldap_url->lud_port = default_port;
676  }
677 
678  url = ldap_url_desc2str(ldap_url);
679  if (!url) {
680  cf_log_err(ci, "Failed recombining URL components");
681  goto ldap_url_error;
682  }
683  handle_config->server = talloc_asprintf_append(handle_config->server, "%s ", url);
684 
685  ldap_free_urldesc(ldap_url);
686  ldap_memfree(url);
687  return (0);
688 }
689 
690 /** Check an LDAP server config in server:port format is valid
691  *
692  * @param[in,out] handle_config LDAP handle config being built
693  * @param[in] server string to parse
694  * @param[in] cs in which the server is defined
695  * @return
696  * - 0 for valid server definition
697  * - -1 for invalid server definition
698  */
699 int fr_ldap_server_config_check(fr_ldap_config_t *handle_config, char const *server, CONF_SECTION *cs)
700 {
701  char const *p;
702  char *q;
703  int port = 0;
704  size_t len;
705 
706  port = handle_config->port;
707 
708  /*
709  * We don't support URLs if the library didn't provide
710  * URL parsing functions.
711  */
712  if (strchr(server, '/')) {
713  CONF_ITEM *ci;
714  bad_server_fmt:
715  ci = (CONF_ITEM *)cf_pair_find(cs, "server");
716  cf_log_err(ci, "Invalid 'server' entry, must be in format <server>[:<port>] or "
717  "an ldap URI (ldap|cldap|ldaps|ldapi)://<server>:<port>");
718  return -1;
719  }
720 
721  p = strrchr(server, ':');
722  if (p) {
723  port = (int)strtol((p + 1), &q, 10);
724  if ((p == server) || ((p + 1) == q) || (*q != '\0')) goto bad_server_fmt;
725  len = p - server;
726  } else {
727  len = strlen(server);
728  }
729  if (port == 0) port = LDAP_PORT;
730 
731  handle_config->server = talloc_asprintf_append(handle_config->server, "ldap://%.*s:%i ",
732  (int)len, server, port);
733  return 0;
734 }
735 
736 /** Translate the error code emitted from ldap_url_parse and friends into something accessible with fr_strerror()
737  *
738  * @param[in] ldap_url_err The error code returned
739  */
740 char const *fr_ldap_url_err_to_str(int ldap_url_err)
741 {
742  switch (ldap_url_err) {
743  case LDAP_URL_SUCCESS:
744  return "success";
745 
746  case LDAP_URL_ERR_MEM:
747  return "no memory";
748 
749  case LDAP_URL_ERR_PARAM:
750  return "parameter is bad";
751 
752  case LDAP_URL_ERR_BADSCHEME:
753  return "URL doesn't begin with \"[c]ldap[si]://\"";
754 
755  case LDAP_URL_ERR_BADENCLOSURE:
756  return "URL is missing trailing \">\"";
757 
758  case LDAP_URL_ERR_BADURL:
759  return "URL is bad";
760 
761  case LDAP_URL_ERR_BADHOST:
762  return "host/port is bad";
763 
764  case LDAP_URL_ERR_BADATTRS:
765  return "bad (or missing) attributes";
766 
767  case LDAP_URL_ERR_BADSCOPE:
768  return "scope string is invalid (or missing)";
769 
770  case LDAP_URL_ERR_BADFILTER:
771  return "bad or missing filter";
772 
773  case LDAP_URL_ERR_BADEXTS:
774  return "bad or missing extensions";
775 
776  default:
777  return "unknown reason";
778  }
779 }
static int const char char buffer[256]
Definition: acutest.h:574
strcpy(log_entry->msg, buffer)
#define fr_base16_decode(_err, _out, _in, _no_trailing)
Definition: base16.h:95
#define USES_APPLE_DEPRECATED_API
Definition: build.h:431
#define RCSID(id)
Definition: build.h:444
#define UNUSED
Definition: build.h:313
Common header for all CONF_* types.
Definition: cf_priv.h:49
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:89
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
Definition: cf_util.c:1356
#define cf_log_err(_cf, _fmt,...)
Definition: cf_util.h:265
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition: dbuff.h:509
static fr_slen_t in
Definition: dict.h:645
char * server
Initial server to bind to.
Definition: base.h:222
bool start_tls
Send the Start TLS message to the LDAP directory to start encrypted communications using the standard...
Definition: base.h:256
uint16_t port
Port to use when binding to the server.
Definition: base.h:225
Connection configuration.
Definition: base.h:219
LDAP * fr_ldap_handle_thread_local(void)
Get a thread local dummy LDAP handle.
Definition: base.c:1051
static const char hextab[]
Definition: util.c:37
size_t fr_ldap_util_normalise_dn(char *out, char const *in)
Normalise escape sequences in a DN.
Definition: util.c:439
uint8_t * fr_ldap_berval_to_bin(TALLOC_CTX *ctx, struct berval const *in)
Convert a berval to a talloced buffer.
Definition: util.c:409
size_t fr_ldap_uri_escape_func(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
Converts "bad" strings into ones which are safe for LDAP.
Definition: util.c:70
bool fr_ldap_util_is_dn(char const *in, size_t inlen)
Check whether a string looks like a DN.
Definition: util.c:211
size_t fr_ldap_common_dn(char const *full, char const *part)
Find the place at which the two DN strings diverge.
Definition: util.c:488
int fr_ldap_attrs_check(char const **attrs, char const *attr)
Check that a particular attribute is included in an attribute list.
Definition: util.c:579
static USES_APPLE_DEPRECATED_API const char specials[]
Definition: util.c:36
char const * fr_ldap_url_err_to_str(int ldap_url_err)
Translate the error code emitted from ldap_url_parse and friends into something accessible with fr_st...
Definition: util.c:740
int fr_ldap_server_url_check(fr_ldap_config_t *handle_config, char const *server, CONF_SECTION const *cs)
Check an LDAP server entry in URL format is valid.
Definition: util.c:605
int fr_ldap_box_escape(fr_value_box_t *vb, UNUSED void *uctx)
Definition: util.c:110
int fr_ldap_server_config_check(fr_ldap_config_t *handle_config, char const *server, CONF_SECTION *cs)
Check an LDAP server config in server:port format is valid.
Definition: util.c:699
char * fr_ldap_berval_to_string(TALLOC_CTX *ctx, struct berval const *in)
Convert a berval to a talloced string.
Definition: util.c:390
size_t fr_ldap_uri_unescape_func(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
Converts escaped DNs and filter strings into normal.
Definition: util.c:164
static const bool escapes[UINT8_MAX+1]
Definition: util.c:38
int fr_ldap_parse_url_extensions(LDAPControl **sss, size_t sss_len, char *extensions[])
Parse a subset (just server side sort for now) of LDAP URL extensions.
Definition: util.c:309
int fr_ldap_filter_to_tmpl(TALLOC_CTX *ctx, tmpl_rules_t const *t_rules, char const **sub, size_t sublen, tmpl_t **out)
Combine filters and tokenize to a tmpl.
Definition: util.c:517
#define EMARKER(_str, _marker_idx, _marker)
Definition: log.h:232
talloc_free(reap)
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
#define UINT8_MAX
Definition: merged_model.c:32
int strcasecmp(char *s1, char *s2)
Definition: missing.c:66
static int8_t comp(void const *a, void const *b)
Definition: rbmonkey.c:13
static int encode(rlm_radius_udp_t const *inst, request_t *request, udp_request_t *u, uint8_t id)
int fr_sbuff_trim_talloc(fr_sbuff_t *sbuff, size_t len)
Trim a talloced sbuff to the minimum length required to represent the contained string.
Definition: sbuff.c:399
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_buff(_sbuff_or_marker)
Talloc sbuff extension structure.
Definition: sbuff.h:114
ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_token_t quote, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Convert an arbitrary string into a tmpl_t.
Optional arguments passed to vp_tmpl functions.
Definition: tmpl.h:341
@ T_DOUBLE_QUOTED_STRING
Definition: token.h:121
char const * fr_strerror(void)
Get the last library error.
Definition: strerror.c:554
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
Definition: strerror.h:84
#define fr_strerror_const(_msg)
Definition: strerror.h:223
int fr_value_box_cast_in_place(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv)
Convert one type of fr_value_box_t to another in place.
Definition: value.c:3521
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
Definition: value.c:3630
void fr_value_box_strdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a buffer containing a nul terminated string to a box, but don't copy it.
Definition: value.c:3985
#define fr_value_box_mark_safe_for(_box, _safe_for)
Definition: value.h:1035
#define fr_value_box_is_safe_for(_box, _safe_for)
Definition: value.h:1042
static size_t char fr_sbuff_t size_t inlen
Definition: value.h:984
static size_t char ** out
Definition: value.h:984