68 #define RES_CONFIG_LDAP_CONF "res_ldap.conf"
69 #define RES_CONFIG_LDAP_DEFAULT_BASEDN "asterisk"
71 AST_MUTEX_DEFINE_STATIC(ldap_lock);
73 static LDAP *ldapConn;
75 static char user[512];
76 static char pass[512];
77 static char base_distinguished_name[512];
79 static time_t connect_time;
88 const char *variable_name;
89 const char *variable_value;
107 static struct ldap_table_config *base_table_config;
108 static struct ldap_table_config *static_table_config;
111 AST_CLI_DEFINE(
realtime_ldap_status,
"Shows connection information for the LDAP RealTime driver"),
155 for (; var; var = var->
next) {
156 if (!strcasecmp(name, var->
name))
173 for (; *somestr; somestr++) {
205 const char *attribute_name,
const char *attribute_value)
209 if (ast_strlen_zero(attribute_name) || ast_strlen_zero(attribute_value)) {
213 if (!(var = ast_variable_new(attribute_name, attribute_value, table_config->
table_name))) {
244 base_table_config = NULL;
245 static_table_config = NULL;
253 const char *attribute_name)
258 for (i = 0; i < ARRAY_LEN(configs); i++) {
266 for (; attribute; attribute = attribute->
next) {
267 if (!strcasecmp(attribute_name, attribute->
name)) {
268 return attribute->
value;
273 return attribute_name;
281 const char *attribute_name)
286 for (i = 0; i < ARRAY_LEN(configs); i++) {
294 for (; attribute; attribute = attribute->
next) {
295 if (strcasecmp(attribute_name, attribute->
value) == 0) {
296 return attribute->
name;
301 return attribute_name;
309 LDAPMessage *ldap_entry)
311 BerElement *ber = NULL;
315 int is_delimited = 0;
318 char *ldap_attribute_name;
319 struct berval *value;
322 ldap_attribute_name = ldap_first_attribute(ldapConn, ldap_entry, &ber);
324 while (ldap_attribute_name) {
325 struct berval **
values = NULL;
327 int is_realmed_password_attribute = strcasecmp(attribute_name,
"md5secret") == 0;
329 values = ldap_get_values_len(ldapConn, ldap_entry, ldap_attribute_name);
334 for (v = values; *v; v++) {
336 valptr = value->bv_val;
337 ast_debug(2,
"attribute_name: %s LDAP value: %s\n", attribute_name, valptr);
338 if (is_realmed_password_attribute) {
339 if (!strncasecmp(valptr,
"{md5}", 5)) {
350 while (!ast_strlen_zero(valptr + i)) {
351 if (valptr[i] ==
';') {
354 prev->
next = ast_variable_new(attribute_name, &valptr[pos], table_config->
table_name);
359 prev = var = ast_variable_new(attribute_name, &valptr[pos], table_config->
table_name);
369 prev->
next = ast_variable_new(attribute_name, &valptr[pos], table_config->
table_name);
374 prev = var = ast_variable_new(attribute_name, &valptr[pos], table_config->
table_name);
378 ldap_value_free_len(values);
380 ldap_memfree(ldap_attribute_name);
381 ldap_attribute_name = ldap_next_attribute(ldapConn, ldap_entry, ber);
395 LDAPMessage *ldap_result_msg,
unsigned int *entries_count_ptr)
401 LDAPMessage *ldap_entry = NULL;
402 BerElement *ber = NULL;
405 int is_delimited = 0;
406 char *delim_value = NULL;
407 int delim_tot_count = 0;
412 ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
414 for (tot_count = 0; ldap_entry; tot_count++) {
417 ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
421 if (entries_count_ptr) {
422 *entries_count_ptr = tot_count;
433 ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
439 for (entry_index = 0; ldap_entry; ) {
448 char *ldap_attribute_name = ldap_first_attribute(ldapConn, ldap_entry, &ber);
449 struct berval *value;
450 while (ldap_attribute_name) {
452 int is_realmed_password_attribute = strcasecmp(attribute_name,
"md5secret") == 0;
453 struct berval **
values = NULL;
455 values = ldap_get_values_len(ldapConn, ldap_entry, ldap_attribute_name);
460 for (v = values; *v; v++) {
462 valptr = value->bv_val;
463 if (is_realmed_password_attribute) {
464 if (strncasecmp(valptr,
"{md5}", 5) == 0) {
470 if (delim_value == NULL && !is_realmed_password_attribute
471 && (static_table_config != table_config || strcmp(attribute_name,
"variable_value") == 0)) {
476 ast_debug(4,
"is delimited %d times: %s\n", delim_tot_count, delim_value);
481 if (is_delimited != 0 && !is_realmed_password_attribute
482 && (static_table_config != table_config || strcmp(attribute_name,
"variable_value") == 0) ) {
485 for (i = pos; !ast_strlen_zero(valptr + i); i++) {
486 ast_debug(4,
"DELIM pos: %d i: %d\n", pos, i);
487 if (delim_value[i] ==
';') {
488 delim_value[i] =
'\0';
490 ast_debug(2,
"DELIM - attribute_name: %s value: %s pos: %d\n", attribute_name, &delim_value[pos], pos);
493 prev->
next = ast_variable_new(attribute_name, &delim_value[pos], table_config->
table_name);
498 prev = var = ast_variable_new(attribute_name, &delim_value[pos], table_config->
table_name);
502 if (static_table_config == table_config) {
507 if (ast_strlen_zero(valptr + i)) {
508 ast_debug(4,
"DELIM pos: %d i: %d delim_count: %d\n", pos, i, delim_count);
510 ast_debug(4,
"DELIM - attribute_name: %s value: %s pos: %d\n", attribute_name, &delim_value[pos], pos);
512 prev->
next = ast_variable_new(attribute_name, &delim_value[pos], table_config->
table_name);
517 prev = var = ast_variable_new(attribute_name, &delim_value[pos], table_config->
table_name);
523 ast_free(delim_value);
526 ast_debug(4,
"DELIM pos: %d i: %d\n", pos, i);
530 ast_free(delim_value);
533 ast_debug(2,
"attribute_name: %s value: %s\n", attribute_name, valptr);
536 prev->
next = ast_variable_new(attribute_name, valptr, table_config->
table_name);
541 prev = var = ast_variable_new(attribute_name, valptr, table_config->
table_name);
546 ldap_value_free_len(values);
548 ldap_memfree(ldap_attribute_name);
549 ldap_attribute_name = ldap_next_attribute(ldapConn, ldap_entry, ber);
552 if (static_table_config == table_config) {
553 if (DEBUG_ATLEAST(3)) {
556 if (tmpdebug && tmpdebug2) {
557 ast_log(LOG_DEBUG,
"Added to vars - %s = %s\n", tmpdebug->
value, tmpdebug2->
value);
560 vars[entry_index++] = var;
565 }
while (delim_count <= delim_tot_count && static_table_config == table_config);
567 if (static_table_config != table_config) {
568 ast_debug(3,
"Added to vars - non static\n");
570 vars[entry_index++] = var;
573 ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
584 return (err == LDAP_SERVER_DOWN || err == LDAP_TIMEOUT || err == LDAP_CONNECT_ERROR);
598 ast_log(LOG_ERROR,
"No table config\n");
604 LDAPMessage *ldap_result_msg = NULL;
607 ast_debug(2,
"ldap_loadentry dn=%s\n", dn);
610 result = ldap_search_ext_s(ldapConn, dn, LDAP_SCOPE_BASE,
611 "(objectclass=*)", NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &ldap_result_msg);
613 ast_log(LOG_WARNING,
"Failed to query directory. Try %d/3\n", tries + 1);
616 usleep(500000L * tries);
618 ldap_unbind_ext_s(ldapConn, NULL, NULL);
628 if (result != LDAP_SUCCESS) {
629 ast_log(LOG_WARNING,
"Failed to query directory. Error: %s.\n", ldap_err2string(result));
631 ast_mutex_unlock(&ldap_lock);
635 unsigned int *entries_count_ptr = NULL;
637 if ((num_entry = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) {
638 ast_debug(3,
"num_entry: %d\n", num_entry);
642 ast_log(LOG_NOTICE,
"More than one entry for dn=%s. Take only 1st one\n", dn);
645 ast_debug(2,
"Could not find any entry dn=%s.\n", dn);
648 ldap_msgfree(ldap_result_msg);
672 #define MAXRESULT 2048
673 char *ret_string = NULL;
675 if (!ast_strlen_zero(
string)) {
677 pbx_substitute_variables_helper(channel,
string, ret_string, MAXRESULT - 1);
679 ast_debug(2,
"substituted: string: '%s' => '%s' \n",
string, ret_string);
687 char *cbasedn = NULL;
691 if (*cbasedn ==
'"') {
693 if (!ast_strlen_zero(cbasedn)) {
694 int len = strlen(cbasedn);
695 if (cbasedn[len - 1] ==
'"')
696 cbasedn[len - 1] =
'\0';
707 ast_debug(2,
"basedn: '%s' => '%s' \n", basedn, cbasedn);
716 int search_len = strlen(search);
717 int by_len = strlen(by);
719 char *p = strstr(
string, search);
724 if (by_len == search_len) {
725 memcpy(p, by, by_len);
727 memmove(p + by_len, p + search_len, strlen(p + search_len) + 1);
728 memcpy(p, by, by_len);
730 p = strstr(p + by_len, search);
742 char *new_name = NULL;
743 char *new_value = NULL;
744 char *like_pos = strstr(name,
" LIKE");
746 ast_debug(2,
"name='%s' value='%s'\n", name, value);
749 int len = like_pos -
name;
752 new_name[len] =
'\0';
790 if (config != base_table_config
796 for (field = fields; field; field = field->
next) {
813 const char *basedn,
const char *table_name,
const struct ast_variable *fields)
822 LDAPMessage *ldap_result_msg = NULL;
825 ast_log(LOG_ERROR,
"No table_name specified.\n");
826 ast_free(clean_basedn);
831 ast_log(LOG_ERROR,
"Realtime retrieval requires at least 1 parameter"
832 " and 1 value to search on.\n");
833 ast_free(clean_basedn);
837 ast_mutex_lock(&ldap_lock);
841 ast_mutex_unlock(&ldap_lock);
842 ast_free(clean_basedn);
848 ast_log(LOG_WARNING,
"No table named '%s'.\n", table_name);
849 ast_mutex_unlock(&ldap_lock);
850 ast_free(clean_basedn);
854 filter = create_lookup_filter(table_config, fields);
856 ast_mutex_unlock(&ldap_lock);
857 ast_free(clean_basedn);
863 result = ldap_search_ext_s(ldapConn, clean_basedn,
864 LDAP_SCOPE_SUBTREE,
ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT,
867 ast_debug(1,
"Failed to query directory. Try %d/10\n", tries + 1);
871 ldap_unbind_ext_s(ldapConn, NULL, NULL);
881 if (result != LDAP_SUCCESS) {
882 ast_log(LOG_WARNING,
"Failed to query directory. Error: %s.\n", ldap_err2string(result));
887 if (ldap_count_entries(ldapConn, ldap_result_msg) > 0) {
894 ldap_msgfree(ldap_result_msg);
904 if (strcasecmp(tmp->
name,
"accountBaseDN") == 0) {
911 int base_var_found = 0;
915 if (strcasecmp(test_var->
name, base_var->
name) == 0) {
919 test_var = test_var->
next;
922 if (base_var_found) {
923 base_var->
next = NULL;
933 base_var->
next = append_var;
935 base_var->
next = NULL;
937 append_var = base_var;
942 if (!tmp->
next && append_var) {
943 tmp->
next = append_var;
955 ast_free(clean_basedn);
957 ast_mutex_unlock(&ldap_lock);
962 static struct ast_variable *realtime_arguments_to_fields(va_list ap)
965 const char *newparam, *newval;
967 while ((newparam = va_arg(ap,
const char *))) {
970 newval = va_arg(ap,
const char *);
971 if (!(field = ast_variable_new(newparam, newval,
""))) {
976 field->
next = fields;
986 const char *basedn,
const char *table_name, ...)
992 va_start(ap, table_name);
993 fields = realtime_arguments_to_fields(ap);
1006 const char *table_name,
const struct ast_variable *fields)
1018 while (last_var->
next) {
1019 last_var = last_var->
next;
1021 last_var->
next = *p;
1041 const char *table_name,
const struct ast_variable *fields)
1044 const char *initfield = NULL;
1050 ast_log(LOG_WARNING,
"realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
1054 if ((op = strchr(initfield,
' '))) {
1061 ast_log(LOG_ERROR,
"Unable to create a config!\n");
1073 if (initfield && !strcmp(initfield, var->
name)) {
1074 ast_category_rename(cat, var->
value);
1077 ast_variable_append(cat, var);
1104 if (as->metric < bs->metric) {
1106 }
else if (as->metric > bs->metric) {
1108 }
else if (as->metric == bs->metric && strcmp(as->name, bs->name) != 0) {
1109 return strcmp(as->name, bs->name);
1129 const char *file,
struct ast_config *cfg,
struct ast_flags config_flags,
const char *sugg_incl,
const char *who_asked)
1131 unsigned int vars_count = 0;
1136 const char *last_category = NULL;
1137 int last_category_metric = 0;
1141 if (ast_strlen_zero(file) || !strcasecmp(file, RES_CONFIG_LDAP_CONF)) {
1142 ast_log(LOG_ERROR,
"Missing configuration file: %s. Can't configure myself.\n", RES_CONFIG_LDAP_CONF);
1146 vars =
realtime_ldap_base(&vars_count, basedn, table_name,
"filename", file,
"commented",
"FALSE", NULL);
1149 ast_log(LOG_WARNING,
"Could not find config '%s' in directory.\n", file);
1157 if (!(categories =
ast_calloc(vars_count,
sizeof(*categories)))) {
1161 for (vars_count = 0, p = vars; *p; p++) {
1170 ast_log(LOG_ERROR,
"No category name in entry '%s' for file '%s'.\n",
1171 (dn ? dn->
value :
"?"), file);
1172 }
else if (!cat_metric) {
1173 ast_log(LOG_ERROR,
"No category metric in entry '%s'(category: %s) for file '%s'.\n",
1174 (dn ? dn->
value :
"?"), category->
value, file);
1175 }
else if (!var_metric) {
1176 ast_log(LOG_ERROR,
"No variable metric in entry '%s'(category: %s) for file '%s'.\n",
1177 (dn ? dn->
value :
"?"), category->
value, file);
1178 }
else if (!var_name) {
1179 ast_log(LOG_ERROR,
"No variable name in entry '%s' (category: %s metric: %s) for file '%s'.\n",
1181 cat_metric->
value, file);
1182 }
else if (!var_val) {
1183 ast_log(LOG_ERROR,
"No variable value in entry '%s' (category: %s metric: %s variable: %s) for file '%s'.\n",
1187 categories[vars_count].name = category->
value;
1188 categories[vars_count].metric = atoi(cat_metric->
value);
1189 categories[vars_count].variable_name = var_name->
value;
1190 categories[vars_count].variable_value = var_val->
value;
1204 for (i = 0; i < vars_count; i++) {
1205 if (!strcmp(categories[i].variable_name,
"#include")) {
1207 if (!ast_config_internal_load(categories[i].variable_value, cfg, flags,
"", who_asked)) {
1213 if (!last_category || strcmp(last_category, categories[i].name) ||
1214 last_category_metric != categories[i].metric) {
1220 last_category = categories[i].name;
1221 last_category_metric = categories[i].metric;
1225 if (!(new_v = ast_variable_new(categories[i].variable_name, categories[i].variable_value, table_name))) {
1229 ast_variable_append(cur_cat, new_v);
1233 ast_free(categories);
1247 static LDAPMod *ldap_mod_create(
const char *attribute,
const char *new_value)
1252 mod = ldap_memcalloc(1,
sizeof(LDAPMod));
1253 type = ldap_strdup(attribute);
1255 if (!(mod && type)) {
1256 ast_log(LOG_ERROR,
"Memory allocation failure creating LDAP modification\n");
1262 mod->mod_type = type;
1264 if (strlen(new_value)) {
1266 values = ldap_memcalloc(2,
sizeof(
char *));
1267 value = ldap_strdup(new_value);
1269 if (!(values && value)) {
1270 ast_log(LOG_ERROR,
"Memory allocation failure creating LDAP modification\n");
1271 ldap_memfree(value);
1272 ldap_memfree(values);
1278 mod->mod_op = LDAP_MOD_REPLACE;
1279 mod->mod_values = values;
1280 mod->mod_values[0] = value;
1282 mod->mod_op = LDAP_MOD_DELETE;
1297 static LDAPMod *ldap_mod_append(LDAPMod *src,
const char *new_value)
1301 if (src->mod_op != LDAP_MOD_REPLACE) {
1305 new_buffer = ldap_memrealloc(
1307 strlen(src->mod_values[0]) + strlen(new_value) +
sizeof(
";"));
1310 ast_log(LOG_ERROR,
"Memory allocation failure creating LDAP modification\n");
1314 strcat(new_buffer,
";");
1315 strcat(new_buffer, new_value);
1317 src->mod_values[0] = new_buffer;
1330 static LDAPMod *ldap_mod_duplicate(
const LDAPMod *src)
1333 char *type, **values = NULL;
1335 mod = ldap_memcalloc(1,
sizeof(LDAPMod));
1336 type = ldap_strdup(src->mod_type);
1338 if (!(mod && type)) {
1339 ast_log(LOG_ERROR,
"Memory allocation failure creating LDAP modification\n");
1345 if (src->mod_op == LDAP_MOD_REPLACE) {
1348 values = ldap_memcalloc(2,
sizeof(
char *));
1349 value = ldap_strdup(src->mod_values[0]);
1351 if (!(values && value)) {
1352 ast_log(LOG_ERROR,
"Memory allocation failure creating LDAP modification\n");
1353 ldap_memfree(value);
1354 ldap_memfree(values);
1363 mod->mod_op = src->mod_op;
1364 mod->mod_type = type;
1365 mod->mod_values = values;
1378 static LDAPMod *ldap_mod_find(LDAPMod **modifications,
const char *lookup)
1381 for (i = 0; modifications[i]; i++) {
1382 if (modifications[i]->mod_op == LDAP_MOD_REPLACE &&
1383 !strcasecmp(modifications[i]->mod_type, lookup)) {
1384 return modifications[i];
1399 static int ldap_entry_has_attribute(LDAPMessage *
entry,
const char *lookup)
1401 BerElement *ber = NULL;
1404 attribute = ldap_first_attribute(ldapConn, entry, &ber);
1406 if (!strcasecmp(attribute, lookup)) {
1407 ldap_memfree(attribute);
1411 ldap_memfree(attribute);
1412 attribute = ldap_next_attribute(ldapConn, entry, ber);
1434 static LDAPMod **massage_mods_for_entry(LDAPMessage *entry, LDAPMod **mods)
1436 size_t k, i, remove_count;
1439 for (i = remove_count = 0; mods[i]; i++) {
1440 if (mods[i]->mod_op == LDAP_MOD_DELETE
1441 && !ldap_entry_has_attribute(entry, mods[i]->mod_type)) {
1446 if (!remove_count) {
1450 copies = ldap_memcalloc(i - remove_count + 1,
sizeof(LDAPMod *));
1452 ast_log(LOG_ERROR,
"Memory allocation failure massaging LDAP modification\n");
1456 for (i = k = 0; mods[i]; i++) {
1457 if (mods[i]->mod_op != LDAP_MOD_DELETE
1458 || ldap_entry_has_attribute(entry, mods[i]->mod_type)) {
1459 copies[k] = ldap_mod_duplicate(mods[i]);
1461 ast_log(LOG_ERROR,
"Memory allocation failure massaging LDAP modification\n");
1462 ldap_mods_free(copies, 1);
1467 ast_debug(3,
"Skipping %s deletion because it doesn't exist\n",
1483 static size_t variables_count(
const struct ast_variable *vars)
1487 for (var = vars; var; var = var->
next) {
1493 static int update2_ldap(
const char *basedn,
const char *table_name,
const struct ast_variable *lookup_fields,
const struct ast_variable *update_fields)
1497 char *clean_basedn = NULL;
1498 struct ast_str *filter = NULL;
1499 int search_result = 0;
1502 size_t update_count, update_index, entry_count;
1504 LDAPMessage *ldap_entry = NULL;
1505 LDAPMod **modifications;
1506 LDAPMessage *ldap_result_msg = NULL;
1509 ast_log(LOG_ERROR,
"No table_name specified.\n");
1513 update_count = variables_count(update_fields);
1514 if (!update_count) {
1515 ast_log(LOG_WARNING,
"Need at least one parameter to modify.\n");
1519 ast_mutex_lock(&ldap_lock);
1523 ast_mutex_unlock(&ldap_lock);
1528 if (!table_config) {
1529 ast_log(LOG_ERROR,
"No table named '%s'.\n", table_name);
1530 ast_mutex_unlock(&ldap_lock);
1536 filter = create_lookup_filter(table_config, lookup_fields);
1538 ast_mutex_unlock(&ldap_lock);
1539 ast_free(clean_basedn);
1549 search_result = ldap_search_ext_s(
1554 NULL, 0, NULL, NULL, NULL,
1558 ast_log(LOG_WARNING,
"Failed to query directory. Try %d/3\n", tries + 1);
1561 usleep(500000L * tries);
1563 ldap_unbind_ext_s(ldapConn, NULL, NULL);
1573 if (search_result != LDAP_SUCCESS) {
1574 ast_log(LOG_WARNING,
"Failed to query directory. Error: %s.\n", ldap_err2string(search_result));
1579 entry_count = ldap_count_entries(ldapConn, ldap_result_msg);
1587 modifications = ldap_memcalloc(update_count + 1,
sizeof(LDAPMod *));
1588 if (!modifications) {
1589 ast_log(LOG_ERROR,
"Memory allocation failure\n");
1598 for (field = update_fields, update_index = 0; field; field = field->
next) {
1606 mod = ldap_mod_find(modifications, ldap_attribute_name);
1608 mod = ldap_mod_append(mod, field->
value);
1613 mod = ldap_mod_create(ldap_attribute_name, field->
value);
1617 modifications[update_index++] = mod;
1622 ast_debug(3,
"Modifying %zu matched entries\n", entry_count);
1623 if (DEBUG_ATLEAST(3)) {
1625 for (i = 0; modifications[i]; i++) {
1626 if (modifications[i]->mod_op != LDAP_MOD_DELETE) {
1627 ast_log(LOG_DEBUG,
"%s => %s\n", modifications[i]->mod_type,
1628 modifications[i]->mod_values[0]);
1630 ast_log(LOG_DEBUG,
"deleting %s\n", modifications[i]->mod_type);
1635 for (ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
1637 ldap_entry = ldap_next_entry(ldapConn, ldap_entry)) {
1639 LDAPMod **massaged, **working;
1641 char *dn = ldap_get_dn(ldapConn, ldap_entry);
1643 ast_log(LOG_ERROR,
"Memory allocation failure\n");
1647 working = modifications;
1649 massaged = massage_mods_for_entry(ldap_entry, modifications);
1653 ast_debug(3,
"Nothing left to modify - skipping\n");
1654 ldap_mods_free(massaged, 1);
1661 if ((error = ldap_modify_ext_s(ldapConn, dn, working, NULL, NULL)) != LDAP_SUCCESS) {
1662 ast_log(LOG_ERROR,
"Couldn't modify dn:%s because %s", dn, ldap_err2string(error));
1666 ldap_mods_free(massaged, 1);
1675 ldap_mods_free(modifications, 1);
1678 ldap_msgfree(ldap_result_msg);
1680 ast_free(clean_basedn);
1681 ast_mutex_unlock(&ldap_lock);
1686 static int update_ldap(
const char *basedn,
const char *table_name,
const char *attribute,
const char *lookup,
const struct ast_variable *fields)
1689 struct ast_variable *lookup_fields = ast_variable_new(attribute, lookup,
"");
1690 res = update2_ldap(basedn, table_name, lookup_fields, fields);
1700 .update_func = update_ldap,
1701 .update2_func = update2_ldap,
1720 ast_log(LOG_ERROR,
"Cannot load LDAP RealTime driver.\n");
1724 ast_mutex_lock(&ldap_lock);
1727 ast_log(LOG_WARNING,
"Couldn't establish connection to LDAP directory. Check debug.\n");
1731 ast_verb(1,
"LDAP RealTime driver loaded.\n");
1734 ast_mutex_unlock(&ldap_lock);
1745 ast_mutex_lock(&ldap_lock);
1750 ldap_unbind_ext_s(ldapConn, NULL, NULL);
1755 ast_verb(1,
"LDAP RealTime driver unloaded.\n");
1758 ast_mutex_unlock(&ldap_lock);
1768 ast_mutex_lock(&ldap_lock);
1771 ldap_unbind_ext_s(ldapConn, NULL, NULL);
1776 ast_log(LOG_NOTICE,
"Cannot reload LDAP RealTime driver.\n");
1777 ast_mutex_unlock(&ldap_lock);
1782 ast_log(LOG_WARNING,
"Couldn't establish connection to your directory server. Check debug.\n");
1785 ast_verb(2,
"LDAP RealTime driver reloaded.\n");
1788 ast_mutex_unlock(&ldap_lock);
1793 static int config_can_be_inherited(
const char *key)
1796 static const char *
const config[] = {
1797 "basedn",
"host",
"pass",
"port",
"protocol",
"url",
"user",
"version", NULL
1800 for (i = 0; config[i]; i++) {
1801 if (!strcasecmp(key, config[i])) {
1814 const char *s, *host;
1816 char *category_name = NULL;
1822 base_distinguished_name[0] =
'\0';
1826 if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
1827 ast_log(LOG_ERROR,
"Cannot load configuration file: %s\n", RES_CONFIG_LDAP_CONF);
1831 if (!(s = ast_variable_retrieve(config,
"_general",
"user"))) {
1832 ast_log(LOG_NOTICE,
"No directory user found, anonymous binding as default.\n");
1838 if (!ast_strlen_zero(
user)) {
1839 if (!(s = ast_variable_retrieve(config,
"_general",
"pass"))) {
1840 ast_log(LOG_WARNING,
"No directory password found, using 'asterisk' as default.\n");
1848 if ((s = ast_variable_retrieve(config,
"_general",
"url"))) {
1850 }
else if ((host = ast_variable_retrieve(config,
"_general",
"host"))) {
1851 if (!(s = ast_variable_retrieve(config,
"_general",
"port")) || sscanf(s,
"%5d", &port) != 1 || port > 65535) {
1852 ast_log(LOG_NOTICE,
"No directory port found, using 389 as default.\n");
1856 snprintf(url,
sizeof(url),
"ldap://%s:%d", host, port);
1858 ast_log(LOG_ERROR,
"No directory URL or host found.\n");
1863 if (!(s = ast_variable_retrieve(config,
"_general",
"basedn"))) {
1864 ast_log(LOG_ERROR,
"No LDAP base dn found, using '%s' as default.\n", RES_CONFIG_LDAP_DEFAULT_BASEDN);
1865 ast_copy_string(base_distinguished_name, RES_CONFIG_LDAP_DEFAULT_BASEDN,
sizeof(base_distinguished_name));
1867 ast_copy_string(base_distinguished_name, s,
sizeof(base_distinguished_name));
1869 if (!(s = ast_variable_retrieve(config,
"_general",
"version")) && !(s = ast_variable_retrieve(config,
"_general",
"protocol"))) {
1870 ast_log(LOG_NOTICE,
"No explicit LDAP version found, using 3 as default.\n");
1871 }
else if (sscanf(s,
"%30d", &version) != 1 || version < 1 || version > 6) {
1872 ast_log(LOG_WARNING,
"Invalid LDAP version '%s', using 3 as default.\n", s);
1879 int is_general = (strcasecmp(category_name,
"_general") == 0);
1880 int is_config = (strcasecmp(category_name,
"config") == 0);
1881 struct ast_variable *var = ast_variable_browse(config, category_name);
1886 if (!table_config) {
1890 base_table_config = table_config;
1892 static_table_config = table_config;
1894 for (; var; var = var->
next) {
1895 if (!strcasecmp(var->
name,
"additionalFilter")) {
1898 if (!is_general || config_can_be_inherited(var->
name)) {
1914 int bind_result = 0;
1918 ast_debug(2,
"Everything seems fine.\n");
1922 if (ast_strlen_zero(url)) {
1923 ast_log(LOG_ERROR,
"Not enough parameters to connect to ldap directory\n");
1927 if (LDAP_SUCCESS != ldap_initialize(&ldapConn, url)) {
1928 ast_log(LOG_ERROR,
"Failed to init ldap connection to '%s'. Check debug for more info.\n", url);
1932 if (LDAP_OPT_SUCCESS != ldap_set_option(ldapConn, LDAP_OPT_PROTOCOL_VERSION, &version)) {
1933 ast_log(LOG_WARNING,
"Unable to set LDAP protocol version to %d, falling back to default.\n", version);
1936 if (!ast_strlen_zero(
user)) {
1938 cred.bv_val = (
char *) pass;
1939 cred.bv_len = strlen(pass);
1940 bind_result = ldap_sasl_bind_s(ldapConn,
user, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
1942 ast_debug(2,
"bind %s anonymously\n", url);
1945 bind_result = ldap_sasl_bind_s(ldapConn, NULL, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
1947 if (bind_result == LDAP_SUCCESS) {
1948 ast_debug(2,
"Successfully connected to directory.\n");
1949 connect_time = time(NULL);
1952 ast_log(LOG_WARNING,
"bind failed: %s\n", ldap_err2string(bind_result));
1953 ldap_unbind_ext_s(ldapConn, NULL, NULL);
1965 int ctimesec = time(NULL) - connect_time;
1969 e->
command =
"realtime show ldap status";
1971 "Usage: realtime show ldap status\n"
1972 " Shows connection information for the LDAP RealTime driver\n";
1982 if (!ast_strlen_zero(url)) {
1983 ast_str_append(&buf, 0,
"Connected to '%s', baseDN %s", url, base_distinguished_name);
1986 if (!ast_strlen_zero(
user)) {
2000 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,
"LDAP realtime interface",
2001 .support_level = AST_MODULE_SUPPORT_EXTENDED,
2006 .requires =
"extconfig",
struct ast_variable * next
Main Channel structure associated with a channel.
Asterisk locking-related definitions:
static struct ast_variable ** realtime_ldap_base_ap(unsigned int *entries_count_ptr, const char *basedn, const char *table_name, const struct ast_variable *fields)
LDAP base function.
Asterisk main include file. File version handling, generic pbx functions.
static void append_var_and_value_to_filter(struct ast_str **filter, struct ldap_table_config *table_config, const char *name, const char *value)
Append a name=value filter string. The filter string can grow.
String manipulation functions.
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
descriptor for a cli entry.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
static int semicolon_count_str(const char *somestr)
Count semicolons in string.
Structure for variables, used for configurations and for channel variables.
static struct ast_variable * variable_named(struct ast_variable *var, const char *name)
Find variable by name.
int ast_config_engine_deregister(struct ast_config_engine *del)
Deregister config engine.
static char * cleaned_basedn(struct ast_channel *channel, const char *basedn)
int ast_config_engine_register(struct ast_config_engine *newconfig)
Register config engine.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
#define ast_strdup(str)
A wrapper for strdup()
static char * realtime_ldap_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Realtime Status.
static struct ldap_table_config * table_config_new(const char *table_name)
Create a new table_config.
static struct ast_variable * realtime_ldap(const char *basedn, const char *table_name, const struct ast_variable *fields)
See Asterisk doc.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
static int is_ldap_connect_error(int err)
Check if we have a connection error.
static struct ldap_table_config * table_config_for_table_name(const char *table_name)
Find a table_config.
Configuration engine structure, used to define realtime drivers.
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
#define ast_category_new_anonymous()
Create a nameless category that is not backed by a file.
static int replace_string_in_string(char *string, const char *search, const char *by)
Replace by in string.
Configuration File Parser.
static int reload(void)
Reload Module.
static int compare_categories(const void *a, const void *b)
Sorting alogrithm for qsort to find the order of the variables a and b.
#define ast_config_load(filename, flags)
Load a config file.
static void table_configs_free(void)
Free table_config.
General Asterisk PBX channel definitions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
static const char * convert_attribute_name_to_ldap(struct ldap_table_config *table_config, const char *attribute_name)
Convert variable name to ldap attribute name.
struct ast_variable * delimiters
A set of macros to manage forward-linked lists.
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Core PBX routines and definitions.
static const char * convert_attribute_name_from_ldap(struct ldap_table_config *table_config, const char *attribute_name)
Convert ldap attribute name to variable name.
static struct ast_variable ** realtime_ldap_base(unsigned int *entries_count_ptr, const char *basedn, const char *table_name,...)
same as realtime_ldap_base_ap but take variable arguments count list
#define AST_LIST_HEAD_NOLOCK_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
Support for dynamic strings.
static struct ast_config * realtime_multi_ldap(const char *basedn, const char *table_name, const struct ast_variable *fields)
See Asterisk doc.
static struct ast_variable ** realtime_ldap_result_to_vars(struct ldap_table_config *table_config, LDAPMessage *ldap_result_msg, unsigned int *entries_count_ptr)
Get variables from ldap entry attributes - Should be locked before using it.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
static struct ast_variable * realtime_ldap_entry_to_var(struct ldap_table_config *table_config, LDAPMessage *ldap_entry)
Get variables from ldap entry attributes.
#define ast_calloc(num, len)
A wrapper for calloc()
static void ldap_table_config_add_attribute(struct ldap_table_config *table_config, const char *attribute_name, const char *attribute_value)
add attribute to table config
Support for logging to various files, console and syslog Configuration in file logger.conf.
#define ast_category_new_dynamic(name)
Create a category that is not backed by a file.
static int semicolon_count_var(struct ast_variable *var)
Count semicolons in variables.
structure to hold users read from users.conf
Structure used to handle boolean flags.
static int unload_module(void)
Unload Module.
void ast_cli_print_timestr_fromseconds(int fd, int seconds, const char *prefix)
Print on cli a duration in seconds in format s year(s), s week(s), s day(s), s hour(s), s second(s)
static int parse_config(void)
parse the configuration file
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
struct ast_variable * attributes
static struct ast_config * config_ldap(const char *basedn, const char *table_name, const char *file, struct ast_config *cfg, struct ast_flags config_flags, const char *sugg_incl, const char *who_asked)
See Asterisk Realtime Documentation.
static struct ast_variable * ldap_loadentry(struct ldap_table_config *table_config, const char *dn)
Get LDAP entry by dn and return attributes as variables.
Options provided by main asterisk program.
static int filter(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
static int load_module(void)
Load the module.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
static char * substituted(struct ast_channel *channel, const char *string)
Should be locked before using it.
static int ldap_reconnect(void)
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.