The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
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: 1442c36a5877fdff121f24da1ca26d6876d9fc43 $
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 */
26RCSID("$Id: 1442c36a5877fdff121f24da1ca26d6876d9fc43 $")
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
36static const char specials[] = ",+\"\\<>;*=()";
37static const char hextab[] = "0123456789abcdef";
38static 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 */
70size_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
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 */
164size_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 */
211bool 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 */
309int 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 */
390char *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 */
409uint8_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 */
439size_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 */
488size_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 */
517int 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 */
579int 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 */
605int 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, "ldaps:// scheme is not compatible with 'start_tls'");
657 goto ldap_url_error;
658 }
659 default_port = LDAPS_PORT;
660 handle_config->tls_mode = LDAP_OPT_X_TLS_HARD;
661 } else if (strcmp(ldap_url->lud_scheme, "ldapi") == 0) {
662 set_port_maybe = false;
663 }
664 }
665
666 if (set_port_maybe) {
667 /*
668 * URL port overrides configured port.
669 */
670 ldap_url->lud_port = handle_config->port;
671
672 /*
673 * If there's no URL port, then set it to the default
674 * this is so debugging messages show explicitly
675 * the port we're connecting to.
676 */
677 if (!ldap_url->lud_port) ldap_url->lud_port = default_port;
678 }
679
680 url = ldap_url_desc2str(ldap_url);
681 if (!url) {
682 cf_log_err(ci, "Failed recombining URL components");
683 goto ldap_url_error;
684 }
685 handle_config->server = talloc_asprintf_append(handle_config->server, "%s ", url);
686
687 ldap_free_urldesc(ldap_url);
688 ldap_memfree(url);
689 return (0);
690}
691
692/** Check an LDAP server config in server:port format is valid
693 *
694 * @param[in,out] handle_config LDAP handle config being built
695 * @param[in] server string to parse
696 * @param[in] cs in which the server is defined
697 * @return
698 * - 0 for valid server definition
699 * - -1 for invalid server definition
700 */
701int fr_ldap_server_config_check(fr_ldap_config_t *handle_config, char const *server, CONF_SECTION *cs)
702{
703 char const *p;
704 char *q;
705 int port = 0;
706 size_t len;
707
708 port = handle_config->port;
709
710 /*
711 * We don't support URLs if the library didn't provide
712 * URL parsing functions.
713 */
714 if (strchr(server, '/')) {
715 CONF_ITEM *ci;
716 bad_server_fmt:
717 ci = (CONF_ITEM *)cf_pair_find(cs, "server");
718 cf_log_err(ci, "Invalid 'server' entry, must be in format <server>[:<port>] or "
719 "an ldap URI (ldap|cldap|ldaps|ldapi)://<server>:<port>");
720 return -1;
721 }
722
723 p = strrchr(server, ':');
724 if (p) {
725 port = (int)strtol((p + 1), &q, 10);
726 if ((p == server) || ((p + 1) == q) || (*q != '\0')) goto bad_server_fmt;
727 len = p - server;
728 } else {
729 len = strlen(server);
730 }
731 if (port == 0) port = LDAP_PORT;
732
733 handle_config->server = talloc_asprintf_append(handle_config->server, "ldap://%.*s:%i ",
734 (int)len, server, port);
735 return 0;
736}
737
738/** Translate the error code emitted from ldap_url_parse and friends into something accessible with fr_strerror()
739 *
740 * @param[in] ldap_url_err The error code returned
741 */
742char const *fr_ldap_url_err_to_str(int ldap_url_err)
743{
744 switch (ldap_url_err) {
745 case LDAP_URL_SUCCESS:
746 return "success";
747
748 case LDAP_URL_ERR_MEM:
749 return "no memory";
750
751 case LDAP_URL_ERR_PARAM:
752 return "parameter is bad";
753
754 case LDAP_URL_ERR_BADSCHEME:
755 return "URL doesn't begin with \"[c]ldap[si]://\"";
756
757 case LDAP_URL_ERR_BADENCLOSURE:
758 return "URL is missing trailing \">\"";
759
760 case LDAP_URL_ERR_BADURL:
761 return "URL is bad";
762
763 case LDAP_URL_ERR_BADHOST:
764 return "host/port is bad";
765
766 case LDAP_URL_ERR_BADATTRS:
767 return "bad (or missing) attributes";
768
769 case LDAP_URL_ERR_BADSCOPE:
770 return "scope string is invalid (or missing)";
771
772 case LDAP_URL_ERR_BADFILTER:
773 return "bad or missing filter";
774
775 case LDAP_URL_ERR_BADEXTS:
776 return "bad or missing extensions";
777
778 default:
779 return "unknown reason";
780 }
781}
static int const char char buffer[256]
Definition acutest.h:576
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:470
#define RCSID(id)
Definition build.h:483
#define UNUSED
Definition build.h:315
Common header for all CONF_* types.
Definition cf_priv.h:49
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
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:1439
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:289
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:514
static fr_slen_t in
Definition dict.h:824
char * server
Initial server to bind to.
Definition base.h:224
bool start_tls
Send the Start TLS message to the LDAP directory to start encrypted communications using the standard...
Definition base.h:258
uint16_t port
Port to use when binding to the server.
Definition base.h:227
Connection configuration.
Definition base.h:221
LDAP * fr_ldap_handle_thread_local(void)
Get a thread local dummy LDAP handle.
Definition base.c:1106
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:742
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
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
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
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
char * fr_ldap_berval_to_string(TALLOC_CTX *ctx, struct berval const *in)
Convert a berval to a talloced string.
Definition util.c:390
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:701
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.
long int ssize_t
unsigned char uint8_t
#define UINT8_MAX
int strcasecmp(char *s1, char *s2)
Definition missing.c:66
static int encode(bio_handle_t *h, request_t *request, bio_request_t *u, uint8_t id)
Definition bio.c:1163
static int8_t comp(void const *a, void const *b)
Definition rbmonkey.c:13
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:419
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_buff(_sbuff_or_marker)
Talloc sbuff extension structure.
Definition sbuff.h:139
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:3572
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
Definition value.c:3681
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:4036
#define fr_value_box_mark_safe_for(_box, _safe_for)
Definition value.h:1048
#define fr_value_box_is_safe_for(_box, _safe_for)
Definition value.h:1055
static size_t char fr_sbuff_t size_t inlen
Definition value.h:997
static size_t char ** out
Definition value.h:997