26RCSID(
"$Id: 15a5ca2a3c6fe2049bff450343ce6bd7e49387ed $")
30#include <freeradius-devel/ldap/base.h>
31#include <freeradius-devel/util/base16.h>
37static const char hextab[] =
"0123456789abcdef";
107 return outlen - left;
115 fr_value_box_entry_t entry;
124 if (!fr_sbuff_init_talloc(vb, &sbuff, &sbuff_ctx, vb->vb_length * 3, vb->vb_length * 3)) {
134 if (len == vb->vb_length) {
168 size_t freespace = outlen;
170 if (outlen <= 1)
return 0;
173 while (*p && (--freespace > 0)) {
189 if (!(c1 = memchr(
hextab, tolower(p[0]), 16)) ||
190 !(c2 = memchr(
hextab, tolower(p[1]), 16)))
goto next;
199 return outlen - freespace;
216 bool too_soon =
true;
228 if (
inlen < 2)
return false;
251 if (
inlen < 3)
return false;
270 if (too_soon || (*p != want))
return false;
276 if (too_soon || (*p != want))
return false;
294 if (too_soon || (
comp < 2))
return false;
311 LDAPControl **sss_p = sss, **sss_end = sss_p + sss_len;
322 for (i = 0; extensions[i]; i++) {
324 bool is_critical =
false;
326 if (sss_p == sss_end) {
343 "in the format \"[!]sss=<key>[,key]\"");
347 if (*s) ldap_control_free(*s);
354 if (ret != LDAP_SUCCESS) {
360 if (*sss_p) ldap_control_free(*sss_p);
363 ldap_free_sort_keylist(keys);
364 if (ret != LDAP_SUCCESS) {
366 ldap_err2string(ret));
377 struct berval attr_value;
383 "in the format \"[!]vlv=<before>/<after>(/<offset>/<count>|:<value>)");
387 vlvinfo.ldvlv_context = NULL;
389 if (
fr_sbuff_out(NULL, &ext_value, &sbuff) <= 0)
goto vlv_error;
391 vlvinfo.ldvlv_before_count = ext_value;
393 if (
fr_sbuff_out(NULL, &ext_value, &sbuff) <= 0)
goto vlv_error;
394 vlvinfo.ldvlv_after_count = ext_value;
399 vlvinfo.ldvlv_attrvalue = NULL;
401 if (
fr_sbuff_out(NULL, &ext_value, &sbuff) <= 0)
goto vlv_error;
403 vlvinfo.ldvlv_offset = ext_value;
405 if (
fr_sbuff_out(NULL, &ext_value, &sbuff) <= 0)
goto vlv_error;
406 vlvinfo.ldvlv_count = ext_value;
412 vlvinfo.ldvlv_attrvalue = &attr_value;
418 if (ret != LDAP_SUCCESS) {
420 ldap_err2string(ret));
433 return (sss_end - sss_p);
452 out = talloc_array(ctx,
char,
in->bv_len + 1);
453 if (!
out)
return NULL;
455 memcpy(
out,
in->bv_val,
in->bv_len);
456 out[
in->bv_len] =
'\0';
472 if (!
out)
return NULL;
474 memcpy(
out,
in->bv_val,
in->bv_len);
502 for (p =
in; *p !=
'\0'; p++) {
548 size_t f_len, p_len, i;
550 if (!full)
return -1;
552 f_len = strlen(full);
554 if (!part)
return -1;
556 p_len = strlen(part);
557 if (!p_len)
return f_len;
559 if ((f_len < p_len) || !f_len)
return -1;
561 for (i = 0; i < p_len; i++)
if (part[p_len - i] != full[f_len - i])
return -1;
563 return f_len - p_len;
578 char const *
in = NULL;
589 for (i = 0; i < sublen; i++) {
590 if (sub[i] && *sub[i]) {
593 len += strlen(sub[i]);
603 buffer = talloc_array(ctx,
char, len + 4);
606 for (i = 0; i < sublen; i++) {
607 if (sub[i] && (*sub[i] !=
'\0')) {
641 if (!attr)
return -1;
643 len = talloc_array_length(attrs);
645 for (i = 0; i < len; i++) {
646 if (!attrs[i])
continue;
647 if (
strcasecmp(attrs[i], attr) == 0)
return 1;
665 LDAPURLDesc *ldap_url;
666 bool set_port_maybe =
true;
667 int default_port = LDAP_PORT;
671 if (ldap_url_parse(server, &ldap_url)) {
672 cf_log_err(ci,
"Parsing LDAP URL \"%s\" failed", server);
674 ldap_free_urldesc(ldap_url);
678 if (ldap_url->lud_dn && (ldap_url->lud_dn[0] !=
'\0')) {
679 cf_log_err(ci,
"Base DN cannot be specified via server URL");
683 if (ldap_url->lud_attrs && ldap_url->lud_attrs[0]) {
684 cf_log_err(ci,
"Attribute list cannot be speciried via server URL");
691 if (ldap_url->lud_scope != LDAP_SCOPE_BASE) {
692 cf_log_err(ci,
"Scope cannot be specified via server URL");
695 ldap_url->lud_scope = -1;
702 if ((p = strchr(server,
']')) && (p[1] ==
':')) {
703 set_port_maybe =
false;
704 }
else if ((p = strchr(server,
':')) && (strchr(p+1,
':') != NULL)) {
705 set_port_maybe =
false;
711 if (ldap_url->lud_scheme) {
712 if (strcmp(ldap_url->lud_scheme,
"ldaps") == 0) {
714 cf_log_err(ci,
"ldaps:// scheme is not compatible with 'start_tls'");
717 default_port = LDAPS_PORT;
718 handle_config->
tls_mode = LDAP_OPT_X_TLS_HARD;
719 }
else if (strcmp(ldap_url->lud_scheme,
"ldapi") == 0) {
720 set_port_maybe =
false;
724 if (set_port_maybe) {
728 ldap_url->lud_port = handle_config->
port;
735 if (!ldap_url->lud_port) ldap_url->lud_port = default_port;
738 url = ldap_url_desc2str(ldap_url);
740 cf_log_err(ci,
"Failed recombining URL components");
743 handle_config->
server = talloc_asprintf_append(handle_config->
server,
"%s ", url);
745 ldap_free_urldesc(ldap_url);
766 port = handle_config->
port;
772 if (strchr(server,
'/')) {
776 cf_log_err(ci,
"Invalid 'server' entry, must be in format <server>[:<port>] or "
777 "an ldap URI (ldap|cldap|ldaps|ldapi)://<server>:<port>");
781 p = strrchr(server,
':');
783 port = (int)strtol((p + 1), &q, 10);
784 if ((p == server) || ((p + 1) == q) || (*q !=
'\0'))
goto bad_server_fmt;
787 len = strlen(server);
789 if (port == 0) port = LDAP_PORT;
791 handle_config->
server = talloc_asprintf_append(handle_config->
server,
"ldap://%.*s:%i ",
792 (
int)len, server, port);
802 switch (ldap_url_err) {
803 case LDAP_URL_SUCCESS:
806 case LDAP_URL_ERR_MEM:
809 case LDAP_URL_ERR_PARAM:
810 return "parameter is bad";
812 case LDAP_URL_ERR_BADSCHEME:
813 return "URL doesn't begin with \"[c]ldap[si]://\"";
815 case LDAP_URL_ERR_BADENCLOSURE:
816 return "URL is missing trailing \">\"";
818 case LDAP_URL_ERR_BADURL:
821 case LDAP_URL_ERR_BADHOST:
822 return "host/port is bad";
824 case LDAP_URL_ERR_BADATTRS:
825 return "bad (or missing) attributes";
827 case LDAP_URL_ERR_BADSCOPE:
828 return "scope string is invalid (or missing)";
830 case LDAP_URL_ERR_BADFILTER:
831 return "bad or missing filter";
833 case LDAP_URL_ERR_BADEXTS:
834 return "bad or missing extensions";
837 return "unknown reason";
static int const char char buffer[256]
strcpy(log_entry->msg, buffer)
#define fr_base16_decode(_err, _out, _in, _no_trailing)
#define USES_APPLE_DEPRECATED_API
Common header for all CONF_* types.
A section grouping multiple CONF_PAIR.
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
#define cf_log_err(_cf, _fmt,...)
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
char * server
Initial server to bind to.
bool start_tls
Send the Start TLS message to the LDAP directory to start encrypted communications using the standard...
uint16_t port
Port to use when binding to the server.
Connection configuration.
LDAP * fr_ldap_handle_thread_local(void)
Get a thread local dummy LDAP handle.
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...
static const char hextab[]
size_t fr_ldap_util_normalise_dn(char *out, char const *in)
Normalise escape sequences in a DN.
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.
bool fr_ldap_util_is_dn(char const *in, size_t inlen)
Check whether a string looks like a DN.
size_t fr_ldap_common_dn(char const *full, char const *part)
Find the place at which the two DN strings diverge.
int fr_ldap_attrs_check(char const **attrs, char const *attr)
Check that a particular attribute is included in an attribute list.
static USES_APPLE_DEPRECATED_API const char specials[]
uint8_t * fr_ldap_berval_to_bin(TALLOC_CTX *ctx, struct berval const *in)
Convert a berval to a talloced buffer.
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.
char * fr_ldap_berval_to_string(TALLOC_CTX *ctx, struct berval const *in)
Convert a berval to a talloced string.
int fr_ldap_box_escape(fr_value_box_t *vb, UNUSED void *uctx)
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.
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.
static const bool escapes[UINT8_MAX+1]
int fr_ldap_parse_url_extensions(LDAPControl **sss, size_t sss_len, char *extensions[])
Parse a subset (just server side sort and virtual list view for now) of LDAP URL extensions.
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.
#define EMARKER(_str, _marker_idx, _marker)
@ FR_TYPE_STRING
String of printable characters.
int strcasecmp(char *s1, char *s2)
static int encode(bio_handle_t *h, request_t *request, bio_request_t *u, uint8_t id)
static int8_t comp(void const *a, void const *b)
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.
size_t fr_sbuff_adv_past_str(fr_sbuff_t *sbuff, char const *needle, size_t needle_len)
Return true and advance past the end of the needle if needle occurs next in the sbuff.
bool fr_sbuff_next_if_char(fr_sbuff_t *sbuff, char c)
Return true if the current char matches, and if it does, advance.
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_current(_sbuff_or_marker)
#define fr_sbuff_buff(_sbuff_or_marker)
#define fr_sbuff_out(_err, _out, _in)
#define fr_sbuff_remaining(_sbuff_or_marker)
Talloc sbuff extension structure.
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.
char const * fr_strerror(void)
Get the last library error.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
#define fr_strerror_const(_msg)
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.
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
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.
#define fr_value_box_mark_safe_for(_box, _safe_for)
#define fr_value_box_is_safe_for(_box, _safe_for)
static size_t char fr_sbuff_t size_t inlen
static size_t char ** out